Oracle
 sql >> база данни >  >> RDS >> Oracle

Транспониране на резултат от заявка в Oracle 11g

Близо сте - това, което искате, е комбинация от UNPIVOT и PIVOT :

with T AS (
  select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
  select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
  select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual 
)
select * from (
  select * from t
  unpivot (reading_value
    for reading_name in ("READING1", "READING2", "READING3")
    )
  pivot(max(reading_value) for element in (1,2,3)
  )
)
order by reading_name

Тази заявка

  • преобразува колоните reading1, reading2, reading3 в отделни редове (името влиза в reading_name , стойността в reading_value ); това ни дава по един ред на (елемент,име_на_четене)
  • преобразува редовете 1, 2*, 3 (стойностите за елемент ) в колони '1', '2', '3'; това ни дава по един ред на reading_name

АКТУАЛИЗАЦИЯ

Ако списъкът с елементи не е известен до момента на изпълнение (напр. защото потребителят има възможност да ги избере), имате нужда от по-динамичен подход. Ето едно решение, което динамично създава SQL израз за дадения списък от елементи и използва sys_refcursor за набора от резултати.

-- setup table
create table T AS 
  select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
  select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
  select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual ;  
/

declare
  l_Elements dbms_sql.Number_Table;

  function pivot_it(p_Elements in dbms_sql.Number_Table) 
    return sys_refcursor is
      l_SQL CLOB := empty_clob();
      l_Result sys_refcursor;
    begin
      l_SQL := '
        select * from (
          select * from t 
            unpivot (reading_value
              for reading_name in ("READING1", "READING2", "READING3")
            )
          pivot(max(reading_value) for element in (';
      for i in 1 .. p_Elements.count
              loop
                  l_SQL := l_SQL || to_char(p_Elements(i)) || ',';
                end loop;
      -- remove trailing ','                
      l_SQL := regexp_replace(l_SQL, ',$');                
      l_SQL := l_SQL || ')
        )
      )';
      dbms_output.put_line(l_SQL);
      open l_Result for l_SQL;
      return l_Result;
  end;      
begin
  l_Elements(1) := 1;
  l_Elements(2) := 2;
  -- uncomment this line to get all 3 elements
  -- l_Elements(3) := 3;
  -- return the cursor into a bind variable (to be used in the host environment)
  :p_Cursor := pivot_it(l_Elements);  
end;

Начинът, по който използвате курсора, върнат от тази функция, зависи от средата, която използвате - в SQL/Plus можете просто да го отпечатате, а свързванията на Oracle на повечето езици за програмиране го поддържат готови.

ПРЕДУПРЕЖДЕНИЕ: Докато този код работи за предоставените данни, липсва дори основна проверка на грешки. Това е особено важно, тъй като динамичният SQL винаги е възможна цел за атаки чрез SQL инжектиране.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Създаване на заявка UPDATE RETURNING в Hibernate

  2. Oracle 11g SQL за получаване на уникални стойности в една колона на заявка с няколко колони

  3. EF 5 с oracle edmx StoreGeneratedPattern=Проблем със самоличността

  4. Как да разделим една колона на няколко колони

  5. RobotFramework :cx_Oracle - FAIL :InternalError:Няма Oracle грешка?