用于根据行的唯一值将行转换为列的SQL select语句
我在oracle数据库中名为training的表中有以下数据用于根据行的唯一值将行转换为列的SQL select语句,sql,oracle11g,pivot,Sql,Oracle11g,Pivot,我在oracle数据库中名为training的表中有以下数据 id dept usr tt em sk sal 10 2 user1 ttl1 eml2 skl1 100 10 2 user1 ttl1 eml2 skl2 200 10 2 user1 ttl1 eml2 skl3 300 10 2 user1 ttl1 eml2 skl4 400 20 3 user2 ttl3 eml4 skl1 1
id dept usr tt em sk sal
10 2 user1 ttl1 eml2 skl1 100
10 2 user1 ttl1 eml2 skl2 200
10 2 user1 ttl1 eml2 skl3 300
10 2 user1 ttl1 eml2 skl4 400
20 3 user2 ttl3 eml4 skl1 150
30 4 user3 ttl6 eml8 skl1 100
30 4 user3 ttl6 eml8 skl2 200
30 4 user3 ttl6 eml8 skl3 300
30 4 user3 ttl6 eml8 skl4 400
30 4 user3 ttl6 eml8 skl5 150
...
and many more rows
有没有办法用sql select语句获得以下结果
id dept usr tt em sk1 sal1 sk2 sal2 sk3 sal3 sk4 sal4 sk5 sal5 sk6 sal6
10 2 user1 ttl1 eml2 skl1 100 skl2 200 skl3 300 skl4 300
20 3 user2 ttl3 eml4 skl1 150
30 4 user3 ttl6 eml8 skl1 100 skl2 200 skl3 300 skl4 400 skl5 150
...
获得结果的简单方法是使用带有CASE表达式的聚合函数。我将首先查询数据,并使用窗口功能
row_number()
根据id
、dept
和usr
为数据组生成唯一序列:
select id,
dept,
usr,
tt,
em,
max(case when seq = 1 then sk end) sk1,
max(case when seq = 1 then sal end) sal1,
max(case when seq = 2 then sk end) sk2,
max(case when seq = 2 then sal end) sal2,
max(case when seq = 3 then sk end) sk3,
max(case when seq = 3 then sal end) sal3,
max(case when seq = 4 then sk end) sk4,
max(case when seq = 4 then sal end) sal4,
max(case when seq = 5 then sk end) sk5,
max(case when seq = 5 then sal end) sal5,
max(case when seq = 6 then sk end) sk6,
max(case when seq = 6 then sal end) sal6
from
(
select id, dept, usr, tt, em, sk, sal,
row_number() over(partition by id, dept, usr
order by sk) seq
from yourtable
) d
group by id, dept, usr, tt, em;
看
由于您使用的是Oracle 11g,因此可以实现PIVOT和UNPIVOT函数来获得结果。UNPIVOT将用于将sk
和sal
的多列转换为多行,然后您可以使用PIVOT将其转换为最终结果。语法类似于:
with cte as
(
select id, dept, usr, tt, em, sk,
to_char(sal) sal,
row_number() over(partition by id, dept, usr
order by sk) seq
from yourtable
)
select
id, dept, usr, tt, em,
sk1, sal1, sk2, sal2,
sk3, sal3, sk4, sal4,
sk5, sal5, sk6, sal6
from
(
select id, dept, usr, tt, em,
lower(col)||to_char(seq) col, value
from cte
unpivot
(
value
for col in (sk, sal)
) u
) d
pivot
(
max(value)
for col in ('sk1' as sk1, 'sal1' as sal1,
'sk2' as sk2, 'sal2' as sal2,
'sk3' as sk3, 'sal3' as sal3,
'sk4' as sk4, 'sal4' as sal4,
'sk5' as sk5, 'sal5' as sal5,
'sk6' as sk6, 'sal6' as sal6)
) ;
看。两者都给出了一个结果:
| ID | DEPT | USR | TT | EM | SK1 | SAL1 | SK2 | SAL2 | SK3 | SAL3 | SK4 | SAL4 | SK5 | SAL5 | SK6 | SAL6 |
|----|------|-------|------|------|------|------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|
| 10 | 2 | user1 | ttl1 | eml2 | skl1 | 100 | skl2 | 200 | skl3 | 300 | skl4 | 400 | (null) | (null) | (null) | (null) |
| 20 | 3 | user2 | ttl3 | eml4 | skl1 | 150 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 30 | 4 | user3 | ttl6 | eml8 | skl1 | 100 | skl2 | 200 | skl3 | 300 | skl4 | 400 | skl5 | 150 | (null) | (null) |
是否提前知道skl的数量?最多可以有10个skl。我只显示到sk6,但可以扩展到SK10如何在结果中添加另一列,将每个用户的sal中的所有值相加?@sian非常简单,请参阅第一个版本和pivot版本。我还有一个问题-不是将SK1 SAL1..SK2 SAL2…等放在两个单独的列中,有没有一种方法可以将这两个列值合并为一个列来显示?@sian您需要看看如何使用LISTAGGfunction@blufeet出于某种原因,它无法识别LISTAGG