Oracle SQL列到不带UNPIVOT的行
我当前拥有的内容:
Team User Apples Oranges Pears
Red Adam 4 5 6
Red Avril 11 12 13
Blue David 21 22 23
需要什么:
Team User Product Count
Red Adam Apples 4
Red Adam Oranges 5
Red Adam Pears 6
Red Avril Apples 11
Red Avril Oranges 12
Red Avril Pears 13
Blue David Apples 21
....
这将使用Oracle SQL实现。我知道这可以使用UNPIVOT来完成,但是我的Oracle SQL版本太旧,不支持这种方法。谁能举例说明如何使用交叉应用或等效方法来实现此目的?计数取决于团队-用户-产品组合,并且产品类型的数量将来可能会略有变化,因此可能需要可伸缩的解决方案。
这是有时间限制的,所以非常感谢您的帮助。
解决方案
您可以使用交叉联接和某些CASE语句来执行此操作,方法是使用包含与要取消透视的列的行数相同的虚拟子查询(因为您希望每列进入其自己的行),如下所示:
WITH your_table AS (SELECT 'Red' Team, 'Adam' usr, 4 Apples, 5 Oranges, 6 Pears FROM dual UNION ALL
SELECT 'Red' Team, 'Avril' usr, 11 Apples, 12 Oranges, 13 Pears FROM dual UNION ALL
SELECT 'Blue' Team, 'David' usr, 21 Apples, 22 Oranges, 23 Pears FROM dual)
-- end of mimicking your table. See SQL below:
SELECT yt.team,
yt.usr,
CASE WHEN d.id = 1 THEN 'Apples'
WHEN d.id = 2 THEN 'Oranges'
WHEN d.id = 3 THEN 'Pears'
END product,
CASE WHEN d.id = 1 THEN yt.apples
WHEN d.id = 2 THEN yt.oranges
WHEN d.id = 3 THEN yt.pears
END count_of_product
FROM your_table yt
CROSS JOIN (SELECT LEVEL ID
FROM dual
CONNECT BY LEVEL <= 3) d -- number of columns to unpivot
ORDER BY team, usr, product;
TEAM USR PRODUCT COUNT_OF_PRODUCT
---- ----- ------- ----------------
Blue David Apples 21
Blue David Oranges 22
Blue David Pears 23
Red Adam Apples 4
Red Adam Oranges 5
Red Adam Pears 6
Red Avril Apples 11
Red Avril Oranges 12
Red Avril Pears 13
这样做意味着您只需遍历该表一次,而如果您正在执行Union All方法,则不必多次。
ETA:以下是Aleksej提到的方法-我建议使用您的数据集(希望数据集足够大以具有代表性)来测试这两种方法,看看哪种方法性能更好:
WITH your_table AS (SELECT 'Red' Team, 'Adam' usr, 4 Apples, 5 Oranges, 6 Pears FROM dual UNION ALL
SELECT 'Red' Team, 'Avril' usr, 11 Apples, 12 Oranges, 13 Pears FROM dual UNION ALL
SELECT 'Blue' Team, 'David' usr, 21 Apples, 22 Oranges, 23 Pears FROM dual)
-- end of mimicking your table. See SQL below:
SELECT yt.team,
yt.usr,
CASE WHEN LEVEL = 1 THEN 'Apples'
WHEN LEVEL = 2 THEN 'Oranges'
WHEN LEVEL = 3 THEN 'Pears'
END product,
CASE WHEN LEVEL = 1 THEN yt.apples
WHEN LEVEL = 2 THEN yt.oranges
WHEN LEVEL = 3 THEN yt.pears
END count_of_product
FROM your_table yt
CONNECT BY PRIOR team = team
AND PRIOR usr = usr
AND PRIOR sys_guid() IS NOT NULL
AND LEVEL <= 3
ORDER BY team, usr, product;
TEAM USR PRODUCT COUNT_OF_PRODUCT
---- ----- ------- ----------------
Blue David Apples 21
Blue David Oranges 22
Blue David Pears 23
Red Adam Apples 4
Red Adam Oranges 5
Red Adam Pears 6
Red Avril Apples 11
Red Avril Oranges 12
Red Avril Pears 13
相关文章