用旗帜转置和识别单元格

时间:2016-10-26 14:31:51

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

我有一个包含三列的表格。值列始终为NULL。我知道如何将行转换为列,但我也想用'X'来识别单元格。

EditorTypeSymbolicName ClaimFieldSymbolicName Value
01                     AA                     NULL
01                     BB                     NULL
01                     CC                     NULL
02                     BB                     NULL
02                     CC                     NULL
03                     AA                     NULL

这是我的代码

DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX)

SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(ClaimFieldSymbolicName)
            FROM #TempEditElements
            ORDER BY 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'),1,1,'')

SET @sql = 'SELECT EditorTypeSymbolicName, ' + @cols + '
              FROM
            (
              select EditorTypeSymbolicName, ClaimFieldSymbolicName, Value 
              from #TempEditElements
            ) s
            PIVOT
            (
              MAX(Value) FOR ClaimFieldSymbolicName IN (' + @cols + ')
            ) p
            order by EditorTypeSymbolicName'

EXECUTE(@sql)

我的代码转换它但我不知道如何用'X'标记它们。我希望输出如下:

EditorTypeSymbolicName  AA   BB   CC
01                      X    X    X
02                      NULL X    X
03                      X    NULL NULL

当前输出如下所示

EditorTypeSymbolicName  AA   BB   CC
01                      NULL NULL NULL
02                      NULL NULL NULL
03                      NULL NULL NULL

2 个答案:

答案 0 :(得分:1)

静态解决方案

select      *

from        (select 'X' as x,EditorTypeSymbolicName,ClaimFieldSymbolicName from t) t 
                pivot (max(x) for ClaimFieldSymbolicName in ([AA],[BB],[CC]))   t

order by    EditorTypeSymbolicName
;

动态解决方案

declare @columns    nvarchar(max)   = ''
       ,@stmt       nvarchar(max)
;

----------

select      @columns += case @columns when '' then '' else ',' end + QUOTENAME (ClaimFieldSymbolicName,'[')

from        t

group by    ClaimFieldSymbolicName

order by    ClaimFieldSymbolicName
;

----------

set @stmt =

    '
    select      *

    from        (select ''X'' as x,EditorTypeSymbolicName,ClaimFieldSymbolicName from t) t 
                    pivot (max(x) for ClaimFieldSymbolicName in ('+ @columns + '))   t

    order by    EditorTypeSymbolicName
    '
;

----------

exec (@stmt)

半静态解决方案

select      (select top 0 EditorTypeSymbolicName from t) as EditorTypeSymbolicName,t.*

from        (select distinct ClaimFieldSymbolicName,dense_rank () over (order by ClaimFieldSymbolicName) as dr from t) t 
                pivot (max(ClaimFieldSymbolicName) for dr in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10])) t


union all

select      *

from        (select 'X' as x,EditorTypeSymbolicName,dense_rank () over (order by ClaimFieldSymbolicName) as dr from t) t 
                pivot (max(x) for dr in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10])) t

order by    1
;
╔════════════════════════╦══════╦══════╦══════╦══════╦══════╦══════╦══════╦══════╦══════╦══════╗
║ EditorTypeSymbolicName ║  1   ║  2   ║  3   ║  4   ║  5   ║  6   ║  7   ║  8   ║  9   ║  10  ║
╠════════════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣
║ NULL                   ║ AA   ║ BB   ║ CC   ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║
║ 01                     ║ X    ║ X    ║ X    ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║
║ 02                     ║ NULL ║ X    ║ X    ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║
║ 03                     ║ X    ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║ NULL ║
╚════════════════════════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╝

答案 1 :(得分:1)

这是一种方法。在动态查询中,

  • A"矩阵"是为EditorTypeSymbolicName X ClaimFieldSymbolicNameCROSS JOIN部分)
  • 创建的
  • 然后将其链接到原始表,以查找每个组合是否存在行(LEFT JOIN部分)
  • 如果存在一行,Value将替换为您需要的XValue=CASE ...部分)
CREATE TABLE #TempEditElements(EditorTypeSymbolicName VARCHAR(128),ClaimFieldSymbolicName VARCHAR(128),Value VARCHAR(128));
INSERT INTO #TempEditElements(EditorTypeSymbolicName,ClaimFieldSymbolicName,Value)
VALUES ('01','AA',NULL),('01','BB',NULL),('01','CC',NULL),('02','BB',NULL),('02','CC',NULL),('03','AA',NULL);

DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX);

SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(ClaimFieldSymbolicName)
            FROM #TempEditElements
            ORDER BY 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'),1,1,'')

SET @sql = 'SELECT EditorTypeSymbolicName, ' + @cols + '
              FROM
            (
                SELECT 
                    ets.EditorTypeSymbolicName,
                    cfs.ClaimFieldSymbolicName,
                    Value=CASE WHEN tee.EditorTypeSymbolicName IS NULL AND tee.ClaimFieldSymbolicName IS NULL THEN NULL ELSE ''X'' END
                FROM
                    (SELECT DISTINCT EditorTypeSymbolicName FROM #TempEditElements) AS ets
                    CROSS JOIN (SELECT DISTINCT ClaimFieldSymbolicName FROM #TempEditElements) AS cfs
                    LEFT JOIN #TempEditElements AS tee ON 
                        tee.EditorTypeSymbolicName=ets.EditorTypeSymbolicName AND 
                        tee.ClaimFieldSymbolicName=cfs.ClaimFieldSymbolicName
            ) s
            PIVOT
            (
              MAX(Value) FOR ClaimFieldSymbolicName IN (' + @cols + ')
            ) p
            order by EditorTypeSymbolicName'

EXECUTE (@sql);

DROP TABLE #TempEditElements;

结果是:

╔════════════════════════╦══════╦══════╦══════╗
║ EditorTypeSymbolicName ║  AA  ║  BB  ║  CC  ║
╠════════════════════════╬══════╬══════╬══════╣
║                     01 ║ X    ║ X    ║ X    ║
║                     02 ║ NULL ║ X    ║ X    ║
║                     03 ║ X    ║ NULL ║ NULL ║
╚════════════════════════╩══════╩══════╩══════╝