转置和识别带有标志的单元格

Transposing and identifying the cell with a flag

我有一个包含三列的 table。值列始终为 NULL。我知道如何将行转置为列,但我还想用 'X'.

标识单元格

Table

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

静态解决方案

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 ║
╚════════════════════════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╝

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

  • EditorTypeSymbolicName X ClaimFieldSymbolicNameCROSS JOIN 部分)创建了一个 "matrix"
  • 然后链接到原始 table 以查找每个组合是否存在一行(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 ║
╚════════════════════════╩══════╩══════╩══════╝