固定列上的 SQL Pivot

Posted

技术标签:

【中文标题】固定列上的 SQL Pivot【英文标题】:SQL Pivot on fixed columns 【发布时间】:2020-06-18 13:09:15 【问题描述】:

我正在尝试整理一份报告,但无法生成所需的输出。

WITH DATA_PIVOT AS
(
SELECT 'GNA' SIGL, 'RC752293' ID_USER, '20200609' DATE_FILE, '11:30' HR_INTERVAL1,  10 DURATION1, '13:00' HR_INTERVAL2, 60 DURATION2,   '15:00' HR_INTERVAL3, 10 DURATION3, 'ENTRADA' OPERATION, TO_DATE('09/06/2020 11:35:21', 'DD/MM/YYYY HH24:MI:SS') TIME_INTERVAL, 'DESCANCO' TYPE_OF_INTERVAL FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'SAIDA' , TO_DATE('09/06/2020 11:46:33', 'DD/MM/YYYY HH24:MI:SS') , 'DESCANCO'  FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'ENTRADA' , TO_DATE('09/06/2020 15:48:04', 'DD/MM/YYYY HH24:MI:SS') , 'DESCANCO'  FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'SAIDA' , TO_DATE('09/06/2020 16:01:44', 'DD/MM/YYYY HH24:MI:SS') , 'DESCANCO'  FROM DUAL
)

SELECT * FROM DATA_PIVOT;

在理想的世界中,我设法使用 MAX (DECODE ()) 解决了问题,并且“ID_USER”将具有以下记录序列,但我有几条记录缺少“TYPE_OF_INTERVAL”列(如上图的示例) .在完美的世界中应该是:

WITH DATA_PIVOT AS
(
SELECT 'GNA' SIGL, 'RC752293' ID_USER, '20200609' DATE_FILE, '11:30' HR_INTERVAL1,  10 DURATION1, '13:00' HR_INTERVAL2, 60 DURATION2,   '15:00' HR_INTERVAL3, 10 DURATION3, 'ENTRADA' OPERATION, TO_DATE('09/06/2020 11:35:21', 'DD/MM/YYYY HH24:MI:SS') TIME_INTERVAL, 'DESCANCO' TYPE_OF_INTERVAL FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'SAIDA' , TO_DATE('09/06/2020 11:46:33', 'DD/MM/YYYY HH24:MI:SS') , 'DESCANCO'  FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'ENTRADA' , TO_DATE('09/06/2020 15:48:04', 'DD/MM/YYYY HH24:MI:SS') , 'LANCHE'  FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'SAIDA' , TO_DATE('09/06/2020 16:01:44', 'DD/MM/YYYY HH24:MI:SS') , 'LANCHE'  FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'ENTRADA' , TO_DATE('09/06/2020 17:48:04', 'DD/MM/YYYY HH24:MI:SS') , 'DESCANCO'  FROM DUAL UNION ALL
SELECT 'GNA' , 'RC752293' ,     '20200609' , '11:30' ,  10 , '13:00' , 60 , '15:00' , 10 , 'SAIDA' , TO_DATE('09/06/2020 18:01:34', 'DD/MM/YYYY HH24:MI:SS') , 'DESCANCO'  FROM DUAL
)
SELECT * FROM DATA_PIVOT;

在理想的世界中,我设法使用 MAX (DECODE ()) 解决了问题,并且“ID_USER”会有以下记录序列,但我有几条记录缺少“TYPE_OF_INTERVAL”列(作为示例上图)。在完美的世界中应该是:

但是,当 TYPE_OF_INTERVAL 列中缺少记录时,我无法格式化它们各自列中的类型。 如何在 Oracle 12C 版本中使用 SQL 生成输出?我完全迷路了,我不知道还能去哪里,我尝试了几个 PIVOT 实现

【问题讨论】:

【参考方案1】:

您必须首先准备数据,例如使用rank(),因此每个id 都有编号的行:

select data_pivot.*, 
       rank() over (partition by id_user, operation, type_of_interval 
                    order by time_interval) rn
  from data_pivot

然后你就可以做pivot了:

dbfiddle demo

select * 
  from (select data_pivot.*, 
               rank() over (partition by id_user, operation, type_of_interval 
                            order by time_interval) rn 
          from data_pivot) 
  pivot (max(time_interval) for (rn, operation, type_of_interval) in 
    ( (1, 'ENTRADA', 'DESCANCO') init1,
      (1, 'SAIDA',   'DESCANCO') end1,
      (1, 'ENTRADA', 'LANCHE')   init2,
      (1, 'SAIDA',   'LANCHE')   end2,
      (2, 'ENTRADA', 'DESCANCO') init3,
      (2, 'SAIDA',   'DESCANCO') end3
    ) )

【讨论】:

完美回答!谢谢 !我的实现非常相似,不同的是:RANK() OVER (PARTITION BY ID_USER, OPERATION, TYPE_OF_INTERVAL ORDER BY TIME_INTERVAL) RN 您可以测试数据,因此请相应地调整rank。但是要小心,我不知道您的数据中是否首先 initend 值可能为空,在这种情况下,我们可能需要更多的数据准备逻辑。

以上是关于固定列上的 SQL Pivot的主要内容,如果未能解决你的问题,请参考以下文章

同一列上具有多个聚合的 T-SQL Pivot

给定一个皇后固定在某个列上,如何找到 NQueens 问题的所有解决方案?

SQLServer 2008 PIVOT 上的多个字段问题

如何在不使用临时表或视图的情况下在多个列上使用 PIVOT [重复]

SQL Server - CASE 语句上的 PIVOT

两列上的 SQL 索引