使用两列的tSQL Dynamic Pivot

时间:2018-07-24 19:57:01

标签: tsql

DECLARE @Test Table
(
  Name   Varchar(32),
  Code   Varchar(20)
)

INSERT INTO @Test(Name, Code) VALUES
  ('A-1', 'A-One')
, ('A 2', 'A-Two')
, ('B 1-b', 'B-One')
, ('B', 'A-Two')
, ('C', 'A-One')
, ('C', 'B-One')
, ('C', 'C-One')

样本数据集看起来像这样[同样,这只是一个小样本]:

Name    Code
A-1     A-One
A 1     A-Two
B 1-b   B-One
B       A-Two 
C       A-One
C       B-One
C       C-One

请注意,代码值(例如A-One,A-Two和B-One)可能与多个Name值相关联。

例如A-One出现,名称为A-1,以及名称C ...

我想输出它,使它看起来像这样[除了,比我显示的值多得多-这些值可以更改]:

             A-1      A 1        B 1-b          B      C
A-One        X                                         X
A-Two                  X                        X   
B-One                             X                    X
C-One                                                  X

“名称”值和“代码”值的数量可以更改。它们不是恒定的。

目标是能够查看左侧的Code值列表-并轻松查看与Codes关联的Name值。

我相信这需要创建动态数据透视图sql,并且我对理解数据透视图sql有困难,我将不胜感激任何帮助或指针。

2 个答案:

答案 0 :(得分:1)

具有枢轴:

select Code, 
case when A > 0 then 'X' else '' end as A, 
case when B > 0 then 'X' else '' end as B, 
case when C > 0 then 'X' else '' end as C
from (
    select Name, Code from @Test
) p
pivot(count(Name) for Name in ([A], [B], [C])) as res;

动态的,其中Test是一个永久表:

set quoted_identifier off;

declare @caseStmts varchar(max) = '', @inList varchar(max) = '';

select 
    @caseStmts += 
    (case when len(@caseStmts) > 0 then ', ' else '' end) +
    ("case when " + t.Name + " > 0 then 'X' else '' end as " + t.Name + " "),
    @inList += 
    (case when len(@inList) > 0 then ', ' else '' end) +
    ('[' + t.Name + ']')
from (select distinct Name from Test)
as t;

declare @pivotSql nvarchar(max);
select @pivotSql =
    "select Code, " + @caseStmts + 
    " from (select Name, Code from Test) p " +
    "pivot(count(Name) for Name in (" + @inList + ")) as res;";

exec sp_executesql @pivotSql;

并且仅用单引号引起来,并在名称中处理空格/破折号:

declare @caseStmts varchar(max) = '', @inList varchar(max) = '';

select 
    @caseStmts += 
    (case when len(@caseStmts) > 0 then ', ' else '' end) +
    ('case when [' + t.Name + '] > 0 then ''X'' else '''' end as ''' + t.Name + ''' '),
    @inList += 
    (case when len(@inList) > 0 then ', ' else '' end) +
    ('[' + t.Name + ']')
from (select distinct Name from Test)
as t;

declare @pivotSql nvarchar(max);
select @pivotSql =
    'select Code, ' + @caseStmts + 
    ' from (select Name, Code from Test) p ' +
    'pivot(count(Name) for Name in (' + @inList + ')) as res;';

exec sp_executesql @pivotSql;

答案 1 :(得分:0)

PIVOT将在通用列名称下显示一个现有值(更确切地说: aggregated 现有值)。您可以通过使用PIVOT语句返回CASE并使用X解决这个问题,并尝试使用该值进行旋转。

但是我认为,条件聚集可能是您的朋友:

DECLARE @Test Table
(
  Name   Varchar(1),
  Code   Varchar(10)
)

INSERT INTO @Test(Name, Code) VALUES
  ('A', 'A-One')
, ('A', 'A-Two')
, ('B', 'B-One')
, ('B', 'A-Two')
, ('C', 'A-One')
, ('C', 'B-One')
, ('C', 'C-One');

SELECT t.Code
      ,MAX(CASE WHEN t.[Name]='A' THEN 'X' END) AS A
      ,MAX(CASE WHEN t.[Name]='B' THEN 'X' END) AS B
      ,MAX(CASE WHEN t.[Name]='C' THEN 'X' END) AS C
      ,MAX(CASE WHEN t.[Name]='D' THEN 'X' END) AS D
FROM @Test t
GROUP BY Code