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

时间:2014-11-20 10:06:35

标签: sql-server sql-server-2008-r2 pivot

我的下表中有详细信息,如下例所示。

示例

表:测试

create table test
(
 cola varchar(10),
 colb varchar(10),
 colc varchar(10)
);

插入

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');    

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

预期结果

cola   A1  A2  A3
------------------
111    1   1   1
767    1   1   1

尝试:

透视查询

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)      

获得结果

cola    A1  A2  A3
-------------------
111     1   1   1
5443    0   0   0
767     1   1   1
8998    1   1   0

3 个答案:

答案 0 :(得分:3)

获得结果的关键是首先返回colaA1A2A3的{​​{1}}值。使用colc基本上是INA1A2,因此您将返回包含其中一个的行,而不是所有行。

为了获得包含所有这些行的A3行,您需要使用colaGROUP BY子句来同时使用HAVING子句过滤。基本查询将是:

WHERE

SQL Fiddle with Demo。在断开查询后,您会看到有一个select cola from test where colc in ('A1', 'A2', 'A3') group by cola having count(distinct colc) = 3; 子句来过滤您的WHERE值。您将在colc上使用GROUP BY以及cola子句。 HAVING用于获取不同数量的HAVING值。在这种情况下,colc子句将检查过滤时总共有3 HAVING个值的行。

获得此列表后,即可获得最终结果。您可以使用带有colc表达式的聚合函数,而不是PIVOT

CASE

请参阅SQL Fiddle with Demo

通常,您将动态SQL用于您具有未知值的数据,但如果您想将其用于此目的,则可以使用以下查询:

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;

请参阅SQL Fiddle with Demo

答案 1 :(得分:0)

您还必须过滤源数据:

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

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

PRINT(@Sql)
EXEC(@Sql)   

答案 2 :(得分:0)

试试这个。要过滤Cola A1A2A3colc的{​​{1}}值,请使用conditional aggregate

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

SET @Sql = 'SELECT cola,' +@Stuff+ '
            from
            (
                select  t.cola,t.colc
                from #test t join (SELECT cola from (SELECT Max(CASE WHEN colc = ''A1'' THEN 1 END) [a1],
               Max(CASE WHEN colc = ''A2'' THEN 2 END) [a2],
               Max(CASE WHEN colc = ''A3'' THEN 3 END) [a3] ,
               cola
        FROM   #test
        WHERE  colc IN( '+@StuffForFilter+' )
        GROUP  BY cola) A
WHERE  [a1] IS NOT NULL
       AND [a2] IS NOT NULL
       AND [a3] IS NOT NULL ) B on t.cola=B.cola 
            )p
            PIVOT
            (
                COUNT(colc)
                FOR colc IN ('+@Stuff+')
            )AS pvt'

EXEC sp_executesql @Sql 

输出:

+-----+----+---+----+  
|cola | A1 | A2| A3 |
+-----+----+---+----+
|111  | 1  | 1 | 1  |
|767  | 1  | 1 | 1  |
+-----+----+---+----+