Dynamic Pivot 中的列不会在下一个关键项目处重新开始

Posted

技术标签:

【中文标题】Dynamic Pivot 中的列不会在下一个关键项目处重新开始【英文标题】:Columns in Dynamic Pivot don't start over at next key item 【发布时间】:2017-04-25 17:16:17 【问题描述】:

这是已部分回答的其他问题的延续,但我认为当前状态现在已经丢失。

首先,我有一个临时表,其中存储了一些用于查询数据库的变量。从那里我建立了一个临时表来识别满足以下查询中某些条件的访问:

SELECT
    spl.trac_id
    ,CONVERT(DATE,pev.CONTACT_DATE) AS 'Contact'

INTO
    #medmtemp

FROM 
    #SAMHSA_PAT_LIST spl
    INNER JOIN dbo.IDENTITY_ID_VIEW iiv
    ON iiv.IDENTITY_ID=spl.MRN
    LEFT JOIN dbo.PAT_ENC_VIEW pev
    ON pev.PAT_ID = iiv.PAT_ID
    LEFT JOIN dbo.PAT_ENC_RSN_VISIT_VIEW rsn
    ON rsn.PAT_ENC_CSN_ID=pev.PAT_ENC_CSN_ID

WHERE
    pev.CONTACT_DATE >= @Start_Date
    AND pev.CONTACT_DATE < @End_Date
    AND pev.APPT_STATUS_C IN ( 2 , 6 , 8 , 9 )
    AND rsn.ENC_REASON_ID = 590;

从那里我创建了一个如下所示的数据透视查询:

DECLARE @SQL NVARCHAR(MAX)=''
        ,@PVT_COL NVARCHAR(MAX)='';

SELECT @PVT_COL =@PVT_COL + '[mm_'+CAST(ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS VARCHAR(4))+'],'
    FROM #medmtemp
SELECT @PVT_COL = LEFT(@PVT_COL,LEN(@PVT_COL)-1)

SELECT @SQL = 
N'SELECT * FROM (
SELECT [trac_id], Contact ,''mm_''+CAST(ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS VARCHAR(4)) AS COL_NME 
FROM #medmtemp
)AS A
PIVOT
(
    MAX(Contact) FOR COL_NME IN (' + @PVT_COL + ')
)PVT'

EXECUTE (@SQL)

不幸的是,我看到的结果是这样的:

trac_id mm_1    mm_2    mm_3    mm_4    mm_5    mm_6    mm_7    mm_8    mm_9    mm_10   mm_11   mm_12   mm_13   mm_14   mm_15   mm_16   mm_17   mm_18   mm_19   mm_20
001 2017-03-01  2017-03-08  2017-03-13  2017-03-16  2017-03-16  2017-03-17  2017-03-22  2017-03-23  2017-03-23  2017-03-24  2017-03-27  2017-03-27  2017-03-30  2017-03-31  NULL    NULL    NULL    NULL    NULL    NULL
005 NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    2017-02-16  2017-03-18  2017-03-08  NULL    NULL    NULL
008 NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    2017-03-08  2017-03-23  2017-03-30

我希望将数据格式化为:

trac_id mm_1    mm_2    mm_3    mm_4    mm_5    mm_6    mm_7    mm_8    mm_9    mm_10   mm_11   mm_12   mm_13   mm_14
1   3/1/2017    3/8/2017    3/13/2017   3/16/2017   3/16/2017   3/17/2017   3/22/2017   3/23/2017   3/23/2017   3/24/2017   3/27/2017   3/27/2017   3/30/2017   3/31/2017
5   2/16/2017   3/18/2017   3/8/2017    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
8   3/8/2017    3/23/2017   3/30/2017   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

如果 NULL 列是空白的,那就更好了,但这更好。我希望我能解决这个问题,因为我将在多个查询中使用相同格式的 PIVOT。

【问题讨论】:

【参考方案1】:

关键是在row_number()中包含partition by trac_id

declare @cols nvarchar(max);
declare @sql  nvarchar(max);

  select @cols = stuff((
    select distinct 
      ',' + quotename('mm_'
          + right('0' +convert(nvarchar(10),row_number() over (
              partition by trac_id 
              order by     contact
          )),2)
          )
      from t 
      for xml path (''), type).value('.','nvarchar(max)')
    ,1,1,'');

select @sql = '
 select trac_id, ' + @cols + '
  from  (
    select 
        trac_id
      , contact = convert(char(10),contact,120)
      , rn=''mm_''+right(''0'' +convert(nvarchar(10),row_number() over (
              partition by trac_id 
              order by     contact
          )),2)
      from t
      ) as a
 pivot (max([contact]) for [rn] in (' + @cols + ') ) p';
 select @sql as CodeGenerated;
 exec sp_executesql @sql;

rextester 演示:http://rextester.com/XDVOTD39040

返回:

+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                                        CodeGenerated                                                                         |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
|  select trac_id, [mm_01],[mm_02],[mm_03],[mm_04],[mm_05],[mm_06],[mm_07],[mm_08],[mm_09],[mm_10],[mm_11],[mm_12],[mm_13],[mm_14]                             |
|       from  (                                                                                                                                                |
|         select                                                                                                                                               |
|             trac_id                                                                                                                                          |
|           , contact = convert(char(10),contact,120)                                                                                                          |
|           , rn='mm_'+right('0' +convert(nvarchar(10),row_number() over (                                                                                     |
|                   partition by trac_id                                                                                                                       |
|                   order by     contact                                                                                                                       |
|               )),2)                                                                                                                                          |
|           from t                                                                                                                                             |
|           ) as a                                                                                                                                             |
|      pivot (max([contact]) for [rn] in ([mm_01],[mm_02],[mm_03],[mm_04],[mm_05],[mm_06],[mm_07],[mm_08],[mm_09],[mm_10],[mm_11],[mm_12],[mm_13],[mm_14]) ) p |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+

+---------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
| trac_id |   mm_01    |   mm_02    |   mm_03    |   mm_04    |   mm_05    |   mm_06    |   mm_07    |   mm_08    |   mm_09    |   mm_10    |   mm_11    |   mm_12    |   mm_13    |   mm_14    |
+---------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
|     001 | 2017-03-01 | 2017-03-08 | 2017-03-13 | 2017-03-16 | 2017-03-16 | 2017-03-17 | 2017-03-22 | 2017-03-23 | 2017-03-23 | 2017-03-24 | 2017-03-27 | 2017-03-27 | 2017-03-30 | 2017-03-31 |
|     005 | 2017-02-16 | 2017-03-08 | 2017-03-18 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
|     011 | 2017-02-16 | 2017-03-01 | 2017-03-23 | 2017-03-30 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
|     013 | 2017-03-08 | 2017-03-13 | 2017-03-16 | 2017-03-16 | 2017-03-17 | 2017-03-22 | 2017-03-23 | 2017-03-24 | 2017-03-27 | 2017-03-27 | 2017-03-30 | 2017-03-30 | 2017-03-31 | NULL       |
|     040 | 2017-02-20 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
|     043 | 2017-02-03 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
|     059 | 2017-03-08 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
|     060 | 2017-02-08 | 2017-03-07 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
|     067 | 2017-01-24 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
|     068 | 2017-02-13 | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       | NULL       |
+---------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+

null 值转换为空字符串:

declare @cols nvarchar(max);
declare @select_cols nvarchar(max);
declare @sql  nvarchar(max);

  select @cols = stuff((
    select distinct 
      ',' + quotename('mm_'
          + right('0' +convert(nvarchar(10),row_number() over (
              partition by trac_id 
              order by     contact
          )),2)
          )
      from t 
      for xml path (''), type).value('.','nvarchar(max)')
    ,1,1,'');

select @select_cols = (
    select distinct 
      char(10)+'        , ' + quotename('mm_'
          + right('0' +convert(nvarchar(10),row_number() over (
              partition by trac_id 
              order by     contact
          )),2)
          ) +' = isnull('+
        quotename('mm_'
          + right('0' +convert(nvarchar(10),row_number() over (
              partition by trac_id 
              order by     contact
          )),2)
          )+','''')'
      from t 
      for xml path (''), type).value('.','nvarchar(max)')

select @sql = '
 select trac_id' + @select_cols + '
 from  (
    select 
        trac_id
      , contact = convert(char(10),contact,120)
      , rn=''mm_''+right(''0'' +convert(nvarchar(10),row_number() over (
              partition by trac_id 
              order by     contact
          )),2)
    from t
      ) as a
 pivot (max([contact]) for [rn] in (' + @cols + ') ) p';
 select @sql as CodeGenerated;
 exec sp_executesql @sql;

rextester 演示:http://rextester.com/HDTK5946

返回:

+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                                        CodeGenerated                                                                         |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
|     select trac_id                                                                                                                                           |
|         , [mm_01] = isnull([mm_01],'')                                                                                                                       |
|         , [mm_02] = isnull([mm_02],'')                                                                                                                       |
|         , [mm_03] = isnull([mm_03],'')                                                                                                                       |
|         , [mm_04] = isnull([mm_04],'')                                                                                                                       |
|         , [mm_05] = isnull([mm_05],'')                                                                                                                       |
|         , [mm_06] = isnull([mm_06],'')                                                                                                                       |
|         , [mm_07] = isnull([mm_07],'')                                                                                                                       |
|         , [mm_08] = isnull([mm_08],'')                                                                                                                       |
|         , [mm_09] = isnull([mm_09],'')                                                                                                                       |
|         , [mm_10] = isnull([mm_10],'')                                                                                                                       |
|         , [mm_11] = isnull([mm_11],'')                                                                                                                       |
|         , [mm_12] = isnull([mm_12],'')                                                                                                                       |
|         , [mm_13] = isnull([mm_13],'')                                                                                                                       |
|         , [mm_14] = isnull([mm_14],'')                                                                                                                       |
|      from  (                                                                                                                                                 |
|         select                                                                                                                                               |
|             trac_id                                                                                                                                          |
|           , contact = convert(char(10),contact,120)                                                                                                          |
|           , rn='mm_'+right('0' +convert(nvarchar(10),row_number() over (                                                                                     |
|                   partition by trac_id                                                                                                                       |
|                   order by     contact                                                                                                                       |
|               )),2)                                                                                                                                          |
|         from t                                                                                                                                               |
|           ) as a                                                                                                                                             |
|      pivot (max([contact]) for [rn] in ([mm_01],[mm_02],[mm_03],[mm_04],[mm_05],[mm_06],[mm_07],[mm_08],[mm_09],[mm_10],[mm_11],[mm_12],[mm_13],[mm_14]) ) p |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+

+---------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
| trac_id |   mm_01    |   mm_02    |   mm_03    |   mm_04    |   mm_05    |   mm_06    |   mm_07    |   mm_08    |   mm_09    |   mm_10    |   mm_11    |   mm_12    |   mm_13    |   mm_14    |
+---------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
|     001 | 2017-03-01 | 2017-03-08 | 2017-03-13 | 2017-03-16 | 2017-03-16 | 2017-03-17 | 2017-03-22 | 2017-03-23 | 2017-03-23 | 2017-03-24 | 2017-03-27 | 2017-03-27 | 2017-03-30 | 2017-03-31 |
|     005 | 2017-02-16 | 2017-03-08 | 2017-03-18 |            |            |            |            |            |            |            |            |            |            |            |
|     011 | 2017-02-16 | 2017-03-01 | 2017-03-23 | 2017-03-30 |            |            |            |            |            |            |            |            |            |            |
|     013 | 2017-03-08 | 2017-03-13 | 2017-03-16 | 2017-03-16 | 2017-03-17 | 2017-03-22 | 2017-03-23 | 2017-03-24 | 2017-03-27 | 2017-03-27 | 2017-03-30 | 2017-03-30 | 2017-03-31 |            |
|     040 | 2017-02-20 |            |            |            |            |            |            |            |            |            |            |            |            |            |
|     043 | 2017-02-03 |            |            |            |            |            |            |            |            |            |            |            |            |            |
|     059 | 2017-03-08 |            |            |            |            |            |            |            |            |            |            |            |            |            |
|     060 | 2017-02-08 | 2017-03-07 |            |            |            |            |            |            |            |            |            |            |            |            |
|     067 | 2017-01-24 |            |            |            |            |            |            |            |            |            |            |            |            |            |
|     068 | 2017-02-13 |            |            |            |            |            |            |            |            |            |            |            |            |            |
+---------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+

【讨论】:

非常感谢@SqlZim。因此,将您列为“t”的内容替换为源临时表的名称会给我我所追求的。最后一个问题是,我可以将它插入到一个新的临时表中吗? @Erik 当然。您可以在动态代码 select ... into ##pivoted 中使用全局临时表,例如rextester.com/EQDH71409 如果我只是将 select * 添加到 ##pivoted 中,我会收到以下错误:对象或列名丢失或为空。对于 SELECT INTO 语句,验证每一列都有一个名称。对于其他语句,请查找空别名。不允许使用定义为 "" 或 [] 的别名。将别名更改为有效名称。 @Erik 你看过演示吗? 我又看了一眼@SqlZim。我第一次看错了,把它放错了位置。现在可以了。一个快速的问题,如果我在临时表中插入数据透视结果,但稍后需要进行另一个数据透视,我不必再次声明,但可以从下面重用正确吗?

以上是关于Dynamic Pivot 中的列不会在下一个关键项目处重新开始的主要内容,如果未能解决你的问题,请参考以下文章

Dynamic Pivot 语句中的条件聚合

如何将 SQL 中的列中的值 PIVOT 到新的列名中,然后在这些 PIVOT 列下列出其他列值?

oracle pivot 中的列

Dart语言关键词之dynamic

将 Total 列添加到 Dynamic SQL pivot

[LeetCode] 724. Find Pivot Index_Easy tag: Dynamic Programming