如何在主查询中编写 Unpivot 查询?

Posted

技术标签:

【中文标题】如何在主查询中编写 Unpivot 查询?【英文标题】:How to write Unpivot query within Main Query? 【发布时间】:2020-01-27 18:47:38 【问题描述】:

我有一个主查询,其中有一些列正在引入数据。我需要将这些列转换为单列,但能够保持查询中的其他元素不变。它主要编写 UNPIVOT 数据查询来转换这些单独的列。

从下面的查询中,STRING_ATTR1 到 STRING_ATTR20(全部 20 个)需要是 UNPIVOT 并显示为 2 列,其中包含“字符串名称”(即 STRING_ATTR1、STRING_ATTR2 等)和包含实际未透视的第二列“字符串数据”数据。

请帮忙!

SELECT
[AGG_ELEMENT].[I_COUNT] AS [ELEMENT I COUNT],
[AGG_ELEMENT].[E_TIME_SUM] AS [ELEMENT E TIME],
[AGG_ELEMENT].[A_TIME_SUM] AS [ELEMENT A TIME],
[AGG_ELEMENT].[I_TIME_SUM] AS [ELEMENT I TIME],
[AGG_ELEMENT].[O_COUNT] AS [OPS COUNT],
[AGG_ELEMENT].[R_TIME_SUM] AS [R TIME],
[AGG_ELEMENT].[M_COUNT] AS [MSG COUNT],
[AGG_ELEMENT].[SE_COUNT] AS [SE COUNT],
[AGG_ELEMENT].[UE_COUNT] AS [UE COUNT],
[USERS].[ID] AS [USER ID],
[USERS].[LOGIN] AS [USER LOGIN],
[USERS].[DOMAIN] AS [USER DOMAIN],
[USERS].[NAME] AS [USER NAME],
[USERS].[STRING_ATTR1] AS [STRING_ATTR1],
[USERS].[STRING_ATTR2] AS [STRING_ATTR2],
[USERS].[STRING_ATTR3] AS [STRING_ATTR3],
[USERS].[STRING_ATTR4] AS [STRING_ATTR4],
[USERS].[STRING_ATTR5] AS [STRING_ATTR5],
[USERS].[STRING_ATTR6] AS [STRING_ATTR6],
[USERS].[STRING_ATTR7] AS [STRING_ATTR7],
[USERS].[STRING_ATTR8] AS [STRING_ATTR8],
[USERS].[STRING_ATTR9] AS [STRING_ATTR9],
[USERS].[STRING_ATTR10] AS [STRING_ATTR10],
[USERS].[STRING_ATTR11] AS [STRING_ATTR11],
[USERS].[STRING_ATTR12] AS [STRING_ATTR12],
[USERS].[STRING_ATTR13] AS [STRING_ATTR13],
[USERS].[STRING_ATTR14] AS [STRING_ATTR14],
[USERS].[STRING_ATTR15] AS [STRING_ATTR15],
[USERS].[STRING_ATTR16] AS [STRING_ATTR16],
[USERS].[STRING_ATTR17] AS [STRING_ATTR17],
[USERS].[STRING_ATTR18] AS [STRING_ATTR18],
[USERS].[STRING_ATTR19] AS [STRING_ATTR19],
[USERS].[STRING_ATTR20] AS [STRING_ATTR20],
[DAY].[TIMESTAMP] AS [DATE DAY],
[COMPUTER].[DOMAIN_NAME] AS [DOMAIN NAME],
[COMPUTER].[COMPUTER_NAME] AS [COMPUTER NAME],
[APPLICATION].[NAME] AS [APPLICATION NAME],
[MODULE].[NAME] AS [MODULE NAME],
[SCREEN].[NAME] AS [SCREEN NAME],
[SCREEN_TYPE].[NAME] AS [SCREEN TYPE]
FROM [AGG_ELEMENT] [AGG_ELEMENT]
LEFT JOIN [USERS] [USERS] ON ([AGG_ELEMENT].[USER_ID] = [USERS].[ID])
LEFT JOIN [DAY] [DAY] ON ([AGG_ELEMENT].[DAY_ID] = [DAY].[ID])
LEFT JOIN [COMPUTER] [COMPUTER] ON ([AGG_ELEMENT].[COMPUTER_ID] = [COMPUTER].[ID])
LEFT JOIN [APPLICATION] [APPLICATION] ON ([AGG_ELEMENT].[APPLICATION_ID] = [APPLICATION].[ID])
LEFT JOIN [MODULE] [MODULE] ON ([AGG_ELEMENT].[MODULE_ID] = [MODULE].[ID])
LEFT JOIN [SCREEN] [SCREEN] ON ([AGG_ELEMENT].[SCREEN_ID] = [SCREEN].[ID])
LEFT JOIN [SCREEN_TYPE] [SCREEN_TYPE] ON ([AGG_ELEMENT].[SCREEN_TYPE] = [SCREEN_TYPE].[ID])
WHERE
[DAY].[TIMESTAMP] BETWEEN '10/1/2019' AND '12/31/2019'

【问题讨论】:

【参考方案1】:

只需使用OUTER APPLY:

SELECT v.*, . . .
FROM . . . OUTER APPLY
     (VALUES ('ATTR1', USERS.STRING_ATTR1),
             ('ATTR2', USERS.STRING_ATTR2),
             ('ATTR3', USERS.STRING_ATTR3),
              . . .
     ) v(which, val)
WHERE [DAY].[TIMESTAMP] BETWEEN '2019-10-01' AND '2019-12-31'

【讨论】:

对不起,我迷路了 - 我将如何以及在哪里申请 OUTER APPLY?在主查询中?请指出我正确的方向。谢谢。 @JoeCooper。 . .在FROM 子句中,毕竟JOINs. 明白了 - 所以接下来我需要在 select 语句中添加 (which, val) 列以便查看数据对吗? @JoeCooper。 . .是的。只需包含select 中的列即可。 这会增加我的记录数 - 就像重复数据一样?还是不行?

以上是关于如何在主查询中编写 Unpivot 查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 unpivot 查询中包含 id 列

使用子查询填充 unpivot 列列表

在不确定数量的列上进行 UNPIVOT

SQL 查询:在主键中查找间隙

在同一个查询中两次使用 UNPIVOT

SQL Fundamentals: 子查询 || 行列转换(PIVOT,UNPIVOT,DECODE),设置数据层次(LEVEL...CONNECT BY)