从 SQL 输出中删除所有值为 0 的列

Remove columns from SQL output where all values are 0

所以, 我对 SQL 中的 PIVOT 不是很好(因为我通常在 Excel 中使用 "flat" 数据这样做),但设法拼凑了以下输出:

CONTID  FULLNAME    %!  %%  %3
001     Store 1      0   0   0
002     Store 2      0   0   0
003     Store 3      0   0   0
004     Store 4      0   0   0
005     Store 5      0   0   0

(希望能正常显示)

这是我的 SQL:

USE mydb 

go 

WITH basequery 
     AS (SELECT c.contid, 
                p.fullname, 
                h.keyalm 
         FROM   customer c 
                LEFT JOIN clogs h 
                       ON c.serialno = h.serialno 
                LEFT JOIN contact P 
                       ON c.serialno = P.serialno 
         WHERE  evtype = 1 
                AND p.conttype = 1) 
SELECT * 
FROM   basequery 
       PIVOT(Count(keyalm) 
            FOR keyalm IN ("%!", 
                           "%%", 
                           "%3", 
                           "%4", 
                           "%6", 
                           "%8", 
                           "%9", 
                           "%A", 
                           "%B", 
                           "%C", 
                           "%D", 
                           "%E", 
                           "%F", 
                           "%G", 
                           "%H", 
                           "%I", 
                           "%K", 
                           "%L", 
                           "%M", 
                           "%O", 
                           "%P", 
                           "%Q", 
                           "%R", 
                           "%S", 
                           "%T", 
                           "%U", 
                           "%V", 
                           "%W", 
                           "%X")) AS pvt --I truncated some of this

我想要的是以某种方式不显示总计为 0 的列,就像此处显示的那样。试图在枢轴后做一个 "WHERE",但我为此大喊大叫。

我出于 SO 目的截断了这些列,但我的输出实际上有大约 100 列,而且大多数都是 0。如果可能的话,想从显示的枢轴中消除那些。有没有正确的方法来做到这一点?

如果我没看错,你指望的是 keyalm,并且你想消除展开列由 0 组成的所有行。这意味着对于 contid 和 fullname 的特定组合(分组列由 elimination 标识),clogs 中没有行。如果是这样,您可以在 cte 中消除此类行。在 cte

中添加新列

Count(keyalm) Over(Partition by contid, fullname) as cnt

并在旋转之前过滤 cte where ctn > 0

所以你最终得到这样的结果:

DECLARE @clogs TABLE
    (
      serialno INT ,
      keyalm NVARCHAR(MAX)
    )
DECLARE @contact TABLE
    (
      serialno INT ,
      fullname NVARCHAR(MAX)
    )
DECLARE @customer TABLE
    (
      contid INT ,
      serialno INT
    )


INSERT  INTO @customer
VALUES  ( 1, 10 ),
        ( 2, 20 ),
        ( 3, 30 )

INSERT  INTO @contact
VALUES  ( 10, 'Michael Jordan' ),
        ( 20, 'Dennis Rodman' ),
        ( 30, 'Scottie Pippen' )


INSERT  INTO @clogs
VALUES  ( 10, '%!' ),
        ( 10, '%%' ),
        ( 10, '%3' ),
        ( 20, '%%' );
WITH    basequery
          AS ( SELECT   c.contid ,
                        p.fullname ,
                        h.keyalm ,
                        COUNT(h.keyalm) OVER ( PARTITION BY c.contid,
                                               p.fullname ) AS cnt
               FROM     @customer c
                        LEFT JOIN @clogs h ON c.serialno = h.serialno
                        LEFT JOIN @contact P ON c.serialno = P.serialno 
                       --WHERE  evtype = 1 AND p.conttype = 1
             ),
        wrapper
          AS ( SELECT   contid ,
                        fullname ,
                        keyalm
               FROM     basequery
               WHERE    cnt > 0
             )
    SELECT  *
    FROM    wrapper PIVOT( COUNT(keyalm) FOR keyalm IN ( "%!", "%%", "%3" ) ) AS pvt

输出:

contid  fullname        %!  %%  %3
1       Michael Jordan  1   1   1
2       Dennis Rodman   0   1   0

对动态列尝试此查询:

USE mydb 

go 
declare @str as nvarchar(max),@query as nvarchar(max);
set @str = stuff((SELECT distinct ',['+keyalm+']' FROM   customer c 
                LEFT JOIN clogs h 
                       ON c.serialno = h.serialno 
                LEFT JOIN contact P 
                       ON c.serialno = P.serialno 
         WHERE  evtype = 1 
                AND p.conttype = 1 for xml path('')),1,1,'')
set @query = 
'WITH basequery 
     AS (SELECT c.contid, 
                p.fullname, 
                h.keyalm 
         FROM   customer c 
                LEFT JOIN clogs h 
                       ON c.serialno = h.serialno 
                LEFT JOIN contact P 
                       ON c.serialno = P.serialno 
         WHERE  evtype = 1 
                AND p.conttype = 1) 
SELECT * 
FROM   basequery 
       PIVOT(Count(keyalm) 
            FOR keyalm IN ('+ @str +')) AS pvt'
execute sp_executesql @query