将行划分为 SQL 中的特定列 (Oracle)

Divide rows into specific columns in SQL (Oracle)

一直在尝试将 return 数据分散到多列而不是冗长的行中的方案

例如

COL1       |  COL2    |   COL3
-----------------------------
DATAHEAD   |  VALUE1  | VALUE9
DATAHEAD   |  VALUE2  | VALUE10 
DATAHEAD   |  VALUE3  | VALUE11
DATAHEAD   |  VALUE4  | VALUE12
DATAHEAD   |  VALUE5  | VALUE13
DATAHEAD   |  VALUE6  | VALUE14
DATAHEAD   |  VALUE7  | VALUE15
DATAHEAD   |  VALUE8  | VALUE16 

I want it to spread  into 6/n columns dynamically like 
this below

COL1       |  COL2     |   COL3   | COL4     | COL 5  |    COL6  |
--------------------------------------------------------------------
DATAHEAD   |  VALUE1   | VALUE2   |  VALUE3  | VALUE4  |  VALUE5  |
DATAHEAD   |  VALUE6   | VALUE7   | VALUE8   |  VALUE9 |  VALUE10 |
DATAHEAD   |  VALUE11  | VALUE12  |  VALUE13 | VALUE14 |  VALUE15 |
DATAHEAD   |  VALUE16  |  Null    | Null     |  Null   |  Null    |

数据的数量无关紧要,只要它像上面的格式一样展开即可。我看到了一些关于 Pivot() 的相关文章,但我找不到如何在这种情况下应用它。非常感谢您的帮助,因为我在 sql.

方面表现不佳

首先,我将经过排序的单元格基数制成一个枢轴 table。

    select col1, col2 as col from table1
     union
    select col1, col3 as col from table1 
;

然后我提供了信息,其中行 d 和列 m 将是值。

  select
    col1,
    col,
    trunc((rank() over (order by col)-1)/5) as d,
    mod(rank() over (order by col)-1,5) as m
  from
  (
    select col1, col2 as col from table1
     union
    select col1, col3 as col from table1 
  )
;

最后,我根据documentation做了一个pivot。



select * from
(
  select
    col1,
    col,
    trunc((rank() over (order by col)-1)/5) as d,
    mod(rank() over (order by col)-1,5) as m
  from
  (
    select col1, col2 as col from table1
     union
    select col1, col3 as col from table1 
  )
)
pivot
(
  min(col) for m in (0 as COL2,1 as COL3,2 as COL4,3 as COL5,4 as COL6)
)
order by d
;

输出:

COL1 D COL2 COL3 COL4 COL5 COL6
DATAHEAD 0 VALUE01 VALUE02 VALUE03 VALUE04 VALUE05
DATAHEAD 1 VALUE06 VALUE07 VALUE08 VALUE09 VALUE10
DATAHEAD 2 VALUE11 VALUE12 VALUE13 VALUE14 VALUE15
DATAHEAD 3 VALUE16 (null) (null) (null) (null)

DDL:

CREATE TABLE Table1
    ("COL1" varchar2(8), "COL2" varchar2(7), "COL3" varchar2(7))
;

INSERT ALL 
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE01', 'VALUE09')
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE02', 'VALUE10')
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE03', 'VALUE11')
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE04', 'VALUE12')
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE05', 'VALUE13')
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE06', 'VALUE14')
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE07', 'VALUE15')
    INTO Table1 ("COL1", "COL2", "COL3")
         VALUES ('DATAHEAD', 'VALUE08', 'VALUE16')
SELECT * FROM dual
;

编辑 1:

Oracle中的rank over函数用于按顺序对行进行编号。

例如rank() over (order by col)是一列,其中有从1开始的数字,如果按列排列,则为1,2,3,...如果重新排列行, rank 还是会保留col 列的值。

所以我以前的解决方案是按字母顺序排列值,而不管它们在源中的位置 table。

如果您想按第一列排序并在最后按相同顺序对第二列进行排序,您可以使用此内部 select:

    select
      col1,
      rank() over (order by col2) as r,
      col2 as col
    from table1
    union
    select 
      col1,
      rank() over (order by col2) + (select count(*) from table1) as r,
      col3 as col
    from table1 
;

然后生成的 select 将如下所示:

select * from
(
  select
    col1,
    col,
    trunc((r-1)/5) as d,
    mod(r-1,5) as m
  from
  (
    select
      col1,
      rank() over (order by col2) as r,
      col2 as col
    from table1
    union
    select 
      col1,
      rank() over (order by col2) + (select count(*) from table1) as r,
      col3 as col
    from table1 
  )
)
pivot
(
  min(col) for m in (0 as COL2,1 as COL3,2 as COL4,3 as COL5,4 as COL6)
)
order by d
;