带条件的动态数据透视表查询

MAK*_*MAK 7 sql-server pivot sql-server-2008-r2

我有下表,其中详细信息如下例所示.

示例:

表:测试

create table test
(
 cola varchar(10),
 colb varchar(10),
 colc varchar(10)
);
Run Code Online (Sandbox Code Playgroud)

插入:

insert into test values('111','222','A1');
insert into test values('111','333','A2');
insert into test values('111','344','A3');
insert into test values('111','444','A4');
insert into test values('767','222','A1');
insert into test values('767','333','A2');
insert into test values('767','344','A3');
insert into test values('5443','555','B1');
insert into tft values('8998','222','A1');
insert into tft values('8998','333','A2');    
Run Code Online (Sandbox Code Playgroud)

注意:现在我只想显示cola属于其colc值的记录A1,A2,A3.

预期成果:

cola   A1  A2  A3
------------------
111    1   1   1
767    1   1   1
Run Code Online (Sandbox Code Playgroud)

尝试:

枢轴查询:

DECLARE @Stuff varchar(max) = 'A1,A2,A3'
DECLARE @Sql varchar(max)

SET @Sql = 'SELECT cola,' +@Stuff+ '
            from
            (
                select cola,colc
                from test 
            )p
            PIVOT
            (
                COUNT(colc)
                FOR colc IN ('+@Stuff+')
            )AS pvt'

PRINT(@Sql)
EXEC(@Sql)      
Run Code Online (Sandbox Code Playgroud)

获得结果:

cola    A1  A2  A3
-------------------
111     1   1   1
5443    0   0   0
767     1   1   1
8998    1   1   0
Run Code Online (Sandbox Code Playgroud)

Tar*_*ryn 3

获得结果的关键是首先返回cola具有A1A2A3in的值colc。使用IN基本上是说A1或者A2这样A3您将返回具有其中之一的行,而不是全部。

为了获得包含cola所有这些行的行,您将需要使用 aGROUP BY和 aHAVING子句来配合WHERE子句过滤器。基本查询是:

select cola
from test
where colc in ('A1', 'A2', 'A3')
group by cola
having count(distinct colc) = 3;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle 演示。分解查询,您会看到有一个WHERE子句来过滤您的colc值。您将与子句一起使用GROUP BYon 。用于获取不同数量的值。在这种情况下,该子句将检查过滤时总共有 3 个值的行。colaHAVINGHAVINGcolcHAVINGcolc

一旦你有了这个列表,你就可以得到最终的结果。PIVOT您可以使用带有表达式的聚合函数来代替使用CASE

select 
  t.cola, 
  sum(case when t.colc = 'A1' then 1 else 0 end) A1,
  sum(case when t.colc = 'A2' then 1 else 0 end) A2,
  sum(case when t.colc = 'A3' then 1 else 0 end) A3
from test t
inner join
(
  select cola
  from test
  where colc in ('A1', 'A2', 'A3')
  group by cola
  having count(distinct colc) = 3
) d
  on t.cola = d.cola
group by t.cola;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle 演示

通常,您会对具有未知值的数据使用动态 SQL,但如果您想为此使用它,可以使用以下查询:

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

select @cols = 'A1, A2, A3'

set @query = N'SELECT cola, ' + @cols + N' 
            from 
            (
              select t.cola, t.colc
              from test t
              inner join
              (
                select cola
                from test
                where colc in (''A1'', ''A2'', ''A3'')
                group by cola
                having count(distinct colc) = 3
              ) d
                on t.cola = d.cola
            ) x
            pivot 
            (
                count(colc)
                for colc in (' + @cols + N')
            ) p '

exec sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle 演示