为此使用动态数据透视查询?

Use Dyamic Pivot query for this?

我有以下 table。 (此table中没有主键)

ID   |    IC      |    Name   |     UGCOS   |  MCOS     
---------------------------------------------------------
1AA  |  A123456B  |  Edmund   |  Australia  |  Denmark    
1AA  |  A123456B  |  Edmund   |  Australia  |  France     
2CS  |  C435664C  |  Grace    |  Norway     |  NULL       
3TG  |  G885595H  |  Rae      |  NULL       |  Japan    

我需要这样的结果。

ID   |    IC      |    Name   |     UGCOS   |  MCOS     |  MCOS1   
--------------------------------------------------------------------
1AA  |  A123456B  |  Edmund   |  Australia  |  Denmark  |  France
2CS  |  C435664C  |  Grace    |  Norway     |  NULL     |  NULL
3TG  |  G885595H  |  Rae      |  NULL       |  Japan    |  NULL

用谷歌搜索了一下,似乎 PIVOT 是我需要做的。但是我不确定如何将其应用到我的 table 中。如果有人可以帮助我,那将是很大的帮助。谢谢!

使用 Cross Apply 和 Pivot 我们可以实现这个

 DECLARE @Table1 TABLE 
        ( ID  varchar(3),  IC  varchar(8),  Name  varchar(6),  UGCOS  varchar(9),  MCOS  varchar(7))
    ;

    INSERT INTO @Table1
        ( ID ,  IC ,  Name ,  UGCOS ,  MCOS )
    VALUES
        ('1AA', 'A123456B', 'Edmund', 'Australia', 'Denmark'),
        ('1AA', 'A123456B', 'Edmund', 'Australia', 'France'),
        ('2CS', 'C435664C', 'Grace', 'Norway', NULL),
        ('3TG', 'G885595H', 'Rae', NULL, 'Japan')
    ;
    Select ID ,  IC ,  Name ,  UGCOS,MAX([MCOS1])[MCOS1],MAX([MCOS2])[MCOS2] from (
    select ID ,  IC ,  Name ,  UGCOS ,  MCOS,col,val,col +''+CAST(ROW_NUMBER()OVER(PARTITION BY ID ORDER BY col) AS VARCHAR)RN from @Table1
    CROSS APPLY (values('MCOS',MCOS))CS(col,val))T
    PIVOT (MAX(val) FOR RN IN ([MCOS1],[MCOS2]))PVT
    GROUP BY ID ,  IC ,  Name ,  UGCOS

您是否总是希望将最多 2 行数据转换为列?如果是这样,这对你有用;

CREATE TABLE #TableName (ID varchar(3), IC varchar(8), Name varchar(6), UCGOS varchar(9), MCOS varchar(7))
INSERT INTO #TableName
VALUES
('1AA','A123456B','Edmund','Australia','Denmark')
,('1AA','A123456B','Edmund','Australia','France')
,('2CS','C435664C','Grace','Norway',NULL)
,('3TG','G885595H','Rae',NULL,'Japan')

SELECT DISTINCT a.ID
    ,a.IC
    ,a.NAME
    ,a.UCGOS
    ,b.Mcos1 MCOS
    ,c.Mcos2 MCOS1
FROM #TableName a
LEFT JOIN (
    SELECT ID
        ,MAX(MCOS) Mcos1
    FROM #TableName
    GROUP BY ID
    ) b ON a.ID = b.ID
LEFT JOIN (
    SELECT ID
        ,MIN(MCOS) Mcos2
    FROM #TableName
    GROUP BY ID
    ) c ON a.ID = c.ID
    AND (
        b.ID = c.ID
        AND b.Mcos1 <> c.Mcos2
        )

DROP TABLE #TableName

给你你想要的结果。

这是一个包含串联结果的建议:

CREATE TABLE #tmpTbl (ID VARCHAR(100),IC VARCHAR(100),Name VARCHAR(100),UGCOS VARCHAR(100),MCOS VARCHAR(100))  
INSERT INTO #tmpTbl VALUES
 ('1AA','A123456B','Edmund','Australia','Denmark')    
,('1AA','A123456B','Edmund','Australia','France')   
,('2CS','C435664C','Grace','Norway',NULL)     
,('3TG','G885595H','Rae',NULL,'Japan');

SELECT ID,IC,Name,UGCOS,
       (
        STUFF(
          (
            SELECT ' ,' + x.MCOS
            FROM #tmpTbl AS x
            WHERE x.ID=outerTbl.ID
            FOR XML PATH('')
          ),1,2,''
        )
       ) AS MCOS
FROM #tmpTbl AS outerTbl
GROUP BY ID,IC,Name,UGCOS;
GO
DROP TABLE #tmpTbl;

结果

1AA A123456B    Edmund  Australia   Denmark ,France
2CS C435664C    Grace   Norway      NULL
3TG G885595H    Rae     NULL        Japan

我将创建第二个答案,因为这种方法与我的第一个完全不同:

此动态查询将首先找到不同 ID 的最大计数,然后构建动态数据透视表

CREATE TABLE #tmpTbl (ID VARCHAR(100),IC VARCHAR(100),Name VARCHAR(100),UGCOS VARCHAR(100),MCOS VARCHAR(100))  
INSERT INTO #tmpTbl VALUES
 ('1AA','A123456B','Edmund','Australia','Denmark')    
,('1AA','A123456B','Edmund','Australia','France')   
,('1AA','A123456B','Edmund','Australia','OneMore')   
,('2CS','C435664C','Grace','Norway',NULL)     
,('3TG','G885595H','Rae',NULL,'Japan');
GO

DECLARE @maxCount INT=(SELECT TOP 1 COUNT(*) FROM #tmpTbl GROUP BY ID ORDER BY COUNT(ID) DESC);
DECLARE @colNames VARCHAR(MAX)=
(
    STUFF
    (
        (
        SELECT TOP(@maxCount)
               ',MCOS' + CAST(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS VARCHAR(10))
        FROM sys.objects --take any large table or - better! - an numbers table or a tally CTE
        FOR XML PATH('')
        ),1,1,''
    )
);

DECLARE @cmd VARCHAR(MAX)=
'SELECT p.*
FROM
(
    SELECT *
          ,''MCOS'' + CAST(ROW_NUMBER() OVER(PARTITION BY ID ORDER BY (SELECT NULL)) AS VARCHAR(10)) AS colName 
    FROM #tmpTbl
) AS tbl
PIVOT
(
    MIN(MCOS) FOR colName IN(' + @colNames + ')
) AS p';

EXEC(@cmd);
GO

DROP TABLE #tmpTbl;

结果

1AA A123456B    Edmund  Australia   Denmark France  OneMore
2CS C435664C    Grace   Norway      NULL    NULL    NULL
3TG G885595H    Rae     NULL        Japan   NULL    NULL