使用Dynamic Pivot Function进行水平到垂直显示

时间:2015-01-13 15:08:07

标签: sql sql-server pivot

我有一对多的映射表,如下所示。我需要显示ICD10 HORIZONTALLY。 对于每个ICD9。数据是动态的,因此我不能使用静态枢轴功能。

ICD9 | ICD10
-----+------
0156 | 0178
0156 | 0179
0123 | 0181
0152 | 0202
0231 | 0210
0231 | 0211
0231 | 0212

我希望结果显示为 -

ICD9 | ICD10 | ICD10 | ICD10
0156 | 0178  | 0179  | null
0123 | 0181  | null  | null
0152 | 0202  | null  | null
0231 | 0210  | 0211  | 0212

目前我尝试使用此代码:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(icd10) 
            FROM mv_icd
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT icd9, ' + @cols + ' from 
            (
                select icd9,icd10 from mv_icd
           ) x
            pivot 
            (
                min(icd9)
                for icd10 in (' + @cols + ')
            ) p '
            execute(@query)

但它不起作用,因为我有太多记录(大约12000)。如何更改代码以显示列中每个ICD10的{​​{1}}?

1 个答案:

答案 0 :(得分:5)

根据您当前的代码,您将ICD10列中的所有12000个值转换为新列。这是太多的列,并且对于任何用户来说都是完全无法管理的。

您似乎确实希望将与ICD10相关联的每个ICD9值转换为新列。为此,您需要使用row_number()之类的窗口函数,并为将用作新列名的每个ICD10创建一个唯一值。

您的查询将使用以下内容:

select icd9, icd10,
  rn = row_number() over(partition by icd9 order by icd10)
from mv_icd

Demo。这给出了一个结果:

| ICD9 | ICD10 | RN |
|------|-------|----|
|  123 |   181 |  1 |
|  152 |   202 |  1 |
|  156 |   178 |  1 |
|  156 |   179 |  2 |
|  231 |   210 |  1 |
|  231 |   211 |  2 |
|  231 |   212 |  3 |

您现在有一个新列rn,其中包含每个ICD10的{​​{1}}个值。此新列将用于数据透视表以创建新列。如果您的列数有限,则可以对查询进行硬编码:

ICD9

SQL Fiddle with Demo。现在,如果您不知道每个select icd9, [1], [2], [3] from ( select icd9, icd10, rn = row_number() over(partition by icd9 order by icd10) from mv_icd ) d pivot ( max(icd10) for rn in ([1], [2], [3]) ) piv; 有多少ICD10个项目,那么您必须使用动态SQL。您可以将原始查询中的代码更改为:

ICD9

SQL Fiddle with Demo。这些给出了最终结果:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

-- get list of the unique # of ICD10's per ICD9
SET @cols = STUFF((SELECT ',' + QUOTENAME(rn) 
            FROM
            (
              SELECT rn = row_number() over(partition by icd9 order by icd10)
              FROM mv_icd
            ) d
            GROUP BY rn
            ORDER BY rn
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query 
       = 'SELECT icd9, ' + @cols + ' 
          from 
          (
            select icd9, icd10,
              rn = row_number() over(partition by icd9 order by icd10)
            from mv_icd
           ) x
           pivot 
           (
             max(icd10)
             for rn in (' + @cols + ')
           ) p '

exec sp_executesql @query;

现在,您可以将最终列的名称更改为您需要的任何内容,但这样可以在不创建12000列的情况下为您提供所需的结果。