Sql 从多维表获取关系数据集结果的Oracle查询

Sql 从多维表获取关系数据集结果的Oracle查询,sql,oracle,unpivot,Sql,Oracle,Unpivot,我有一个多维/非关系的数据表。我试图编写一个查询,动态地写出所有的列名,并按关系排列数据 这个例子是一个简单的表格,显示了5本书。这些列显示了书中页面的大小。我要查找的结果集有3列:BOOK\u ID、PAGE、PAGE\u SIZE。我已经包含了构造表的简单代码 我已经设法通过使用联合查询解决了这个问题,但是对于大量的列来说,这是不合理的。数据集几乎有100列 CREATE TABLE BOOK_PAGE_SIZE ( BOOK_ID VARC

我有一个多维/非关系的数据表。我试图编写一个查询,动态地写出所有的列名,并按关系排列数据

这个例子是一个简单的表格,显示了5本书。这些列显示了书中页面的大小。我要查找的结果集有3列:BOOK\u ID、PAGE、PAGE\u SIZE。我已经包含了构造表的简单代码

我已经设法通过使用联合查询解决了这个问题,但是对于大量的列来说,这是不合理的。数据集几乎有100列

CREATE TABLE 
    BOOK_PAGE_SIZE 
        ( 
          BOOK_ID VARCHAR2(5)
        , SIZE_PAGE_1 NUMBER 
        , SIZE_PAGE_2 NUMBER
        , SIZE_PAGE_3 NUMBER
        , SIZE_PAGE_4 NUMBER
        , SIZE_PAGE_5 NUMBER
        );


INSERT INTO BOOK_PAGE_SIZE  VALUES ('T7001',10,35,0,0,0);
INSERT INTO BOOK_PAGE_SIZE  VALUES ('T7002',45,84,78,0,0);
INSERT INTO BOOK_PAGE_SIZE  VALUES ('T7003',28,65,12,32,0);
INSERT INTO BOOK_PAGE_SIZE  VALUES ('T7004',94,74,69,21,76);
INSERT INTO BOOK_PAGE_SIZE  VALUES ('T7005',91,23,14,61,46);
结果集:

  BOOK_ID  PAGE_NUMBER  PAGE_SIZE
   T70001     Page 1       10
   T70001     Page 2       35
   T70001     Page 3        0
   T70001     Page 4        0
   T70001     Page 5        0
   T70002     Page 1       45
   T70002     Page 2       84
   T70002     Page 3       78
   T70002     Page 4        0
   T70002     Page 5        0
   T70003     Page 1       28
   T70003     Page 2       65
   T70003     Page 3       12
   T70003     Page 4       32
   T70003     Page 5        0
   T70004     Page 1       94
   T70004     Page 2       74
   T70004     Page 3       69
   T70004     Page 4       21
   T70004     Page 5       76
   T70005     Page 1       91
   T70005     Page 2       23
   T70005     Page 3       14
   T70005     Page 4       61
   T70005     Page 5       46

你可能需要一些联盟

    select  BOOK_ID,  'Page 1'  PAGE_NUMBER, SIZE_PAGE_1 PAGE_SIZE
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 2'  , SIZE_PAGE_2
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 3'  , SIZE_PAGE_3
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 4'  , SIZE_PAGE_4
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 5'  , SIZE_PAGE_5
    from  BOOK_PAGE_SIZE 
    order by BOOK_ID PAGE_NUMBER, PAGE_SIZE

但您不应该使用列集合,您应该规范化您的模式

您可以使用一些union all

    select  BOOK_ID,  'Page 1'  PAGE_NUMBER, SIZE_PAGE_1 PAGE_SIZE
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 2'  , SIZE_PAGE_2
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 3'  , SIZE_PAGE_3
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 4'  , SIZE_PAGE_4
    from  BOOK_PAGE_SIZE 
    union all  
    select  BOOK_ID,  'Page 5'  , SIZE_PAGE_5
    from  BOOK_PAGE_SIZE 
    order by BOOK_ID PAGE_NUMBER, PAGE_SIZE

但是您不应该使用列集合,您应该规范化您的模式

您可以使用
unpivot

select *
  from  
  (
   with book_page_size(book_id,size_page_1,size_page_2,size_page_3,size_page_4,size_page_5) as
   (
    select 'T7001', 10, 35,  0,  0,  0 from dual union all
    select 'T7002', 45, 84, 78,  0,  0 from dual union all
    select 'T7003', 28, 65, 12, 32,  0 from dual union all
    select 'T7004', 94, 74, 69, 21, 76 from dual union all
    select 'T7005', 91, 23, 14, 61, 46 from dual 
   )
   select *
     from book_page_size a
  ) 
  unpivot (page_size for page_number in (size_page_1 as 'Page 1',
                                         size_page_2 as 'Page 2',
                                         size_page_3 as 'Page 3',
                                         size_page_4 as 'Page 4',
                                         size_page_5 as 'Page 5'))
  order by book_id, page_number;

您可以使用
unpivot

select *
  from  
  (
   with book_page_size(book_id,size_page_1,size_page_2,size_page_3,size_page_4,size_page_5) as
   (
    select 'T7001', 10, 35,  0,  0,  0 from dual union all
    select 'T7002', 45, 84, 78,  0,  0 from dual union all
    select 'T7003', 28, 65, 12, 32,  0 from dual union all
    select 'T7004', 94, 74, 69, 21, 76 from dual union all
    select 'T7005', 91, 23, 14, 61, 46 from dual 
   )
   select *
     from book_page_size a
  ) 
  unpivot (page_size for page_number in (size_page_1 as 'Page 1',
                                         size_page_2 as 'Page 2',
                                         size_page_3 as 'Page 3',
                                         size_page_4 as 'Page 4',
                                         size_page_5 as 'Page 5'))
  order by book_id, page_number;

正如BarbarosÖzhan所回答的,UNPIVOT看起来是这项工作的好工具,而且它需要更少的代码。此外,还可以使用SQL查询生成所需的查询!我经常这样做。我已经创建了一个表,其中有20个大小的页面*列要演示

select 'select book_id, ''Page ''||page_number as page_number, page_size from book_page_size' txt from dual union all
select 'unpivot (' from dual union all
select '  page_size for page_number in (' from dual union all
select '    ' || column_name || ' as ' || replace(column_name, 'SIZE_PAGE_') ||
case when lead(column_id) over(order by column_id) is not null
  then ','
end
from user_tab_columns
where table_name = 'BOOK_PAGE_SIZE'
and column_name != 'BOOK_ID'
union all
select ')) u' from dual union all
select 'order by u.book_id, u.page_number' from dual;
运行此命令,我将返回以下查询:

select book_id, 'Page '||page_number as page_number, page_size from book_page_size
unpivot (
  page_size for page_number in (
    SIZE_PAGE_1 as 1,
    SIZE_PAGE_2 as 2,
    SIZE_PAGE_3 as 3,
    SIZE_PAGE_4 as 4,
    SIZE_PAGE_5 as 5,
    SIZE_PAGE_6 as 6,
    SIZE_PAGE_7 as 7,
    SIZE_PAGE_8 as 8,
    SIZE_PAGE_9 as 9,
    SIZE_PAGE_10 as 10,
    SIZE_PAGE_11 as 11,
    SIZE_PAGE_12 as 12,
    SIZE_PAGE_13 as 13,
    SIZE_PAGE_14 as 14,
    SIZE_PAGE_15 as 15,
    SIZE_PAGE_16 as 16,
    SIZE_PAGE_17 as 17,
    SIZE_PAGE_18 as 18,
    SIZE_PAGE_19 as 19,
    SIZE_PAGE_20 as 20
)) u
order by u.book_id, u.page_number
当我运行查询时,结果是:

BOOK_ID   PAGE_NUMBER  PAGE_SIZE   
BK001     Page 1               1 
BK001     Page 2               2 
BK001     Page 3               3 
BK001     Page 4               4 
BK001     Page 5               5 
BK001     Page 6               6 
BK001     Page 7               7 
BK001     Page 8               8 
BK001     Page 9               9 
BK001     Page 10             10 
BK001     Page 11             11 
BK001     Page 12             12 
BK001     Page 13             13 
BK001     Page 14             14 
BK001     Page 15             15 
BK001     Page 16             16 
BK001     Page 17             17 
BK001     Page 18             18 
BK001     Page 19             19 
BK001     Page 20             20 

正如BarbarosÖzhan所回答的,UNPIVOT看起来是这项工作的好工具,而且它需要更少的代码。此外,还可以使用SQL查询生成所需的查询!我经常这样做。我已经创建了一个表,其中有20个大小的页面*列要演示

select 'select book_id, ''Page ''||page_number as page_number, page_size from book_page_size' txt from dual union all
select 'unpivot (' from dual union all
select '  page_size for page_number in (' from dual union all
select '    ' || column_name || ' as ' || replace(column_name, 'SIZE_PAGE_') ||
case when lead(column_id) over(order by column_id) is not null
  then ','
end
from user_tab_columns
where table_name = 'BOOK_PAGE_SIZE'
and column_name != 'BOOK_ID'
union all
select ')) u' from dual union all
select 'order by u.book_id, u.page_number' from dual;
运行此命令,我将返回以下查询:

select book_id, 'Page '||page_number as page_number, page_size from book_page_size
unpivot (
  page_size for page_number in (
    SIZE_PAGE_1 as 1,
    SIZE_PAGE_2 as 2,
    SIZE_PAGE_3 as 3,
    SIZE_PAGE_4 as 4,
    SIZE_PAGE_5 as 5,
    SIZE_PAGE_6 as 6,
    SIZE_PAGE_7 as 7,
    SIZE_PAGE_8 as 8,
    SIZE_PAGE_9 as 9,
    SIZE_PAGE_10 as 10,
    SIZE_PAGE_11 as 11,
    SIZE_PAGE_12 as 12,
    SIZE_PAGE_13 as 13,
    SIZE_PAGE_14 as 14,
    SIZE_PAGE_15 as 15,
    SIZE_PAGE_16 as 16,
    SIZE_PAGE_17 as 17,
    SIZE_PAGE_18 as 18,
    SIZE_PAGE_19 as 19,
    SIZE_PAGE_20 as 20
)) u
order by u.book_id, u.page_number
当我运行查询时,结果是:

BOOK_ID   PAGE_NUMBER  PAGE_SIZE   
BK001     Page 1               1 
BK001     Page 2               2 
BK001     Page 3               3 
BK001     Page 4               4 
BK001     Page 5               5 
BK001     Page 6               6 
BK001     Page 7               7 
BK001     Page 8               8 
BK001     Page 9               9 
BK001     Page 10             10 
BK001     Page 11             11 
BK001     Page 12             12 
BK001     Page 13             13 
BK001     Page 14             14 
BK001     Page 15             15 
BK001     Page 16             16 
BK001     Page 17             17 
BK001     Page 18             18 
BK001     Page 19             19 
BK001     Page 20             20 

这是我的第一个想法,然而,当你看到超过100个专栏时,这就变得不合理了。好主意,这就是我目前拥有的。理想情况下,我希望表规范化,但是输出数据的系统使用这种结构。我们正在努力进行开发,以改变这一点,但与此同时,需要一个可行的解决办法。正如我前面提到的,你的回答是正确的,只是太费劲了。这是我的第一个想法,然而,当你看到100多个专栏时,这就变得不合理了。好主意,这就是我目前拥有的。理想情况下,我希望表规范化,但是输出数据的系统使用这种结构。我们正在努力进行开发,以改变这一点,但与此同时,需要一个可行的解决办法。正如我前面提到的,你的回答是正确的,只是太费力了。很好,这真的很有帮助。非常感谢你!很好,这真的很有帮助。非常感谢你!