Sql server 2008 在SQLServer2008中将行数据转换为列

Sql server 2008 在SQLServer2008中将行数据转换为列,sql-server-2008,Sql Server 2008,在下面的情况下,我有2条记录,但每个id没有或没有记录是固定的 SELECT InsuredMemberIdentifier,CoverageStartDate,CoverageEndDate FROM APCD.DBO.EdgeServer_EligibilityConsolidated_Part3 WHERE InsuredMemberIdentifier=10190 输出为: InsuredMemberIdentifier | CoverageStartDate | Cov

在下面的情况下,我有2条记录,但每个id没有或没有记录是固定的

SELECT InsuredMemberIdentifier,CoverageStartDate,CoverageEndDate FROM     
APCD.DBO.EdgeServer_EligibilityConsolidated_Part3 WHERE
InsuredMemberIdentifier=10190
输出为:

InsuredMemberIdentifier | CoverageStartDate |   CoverageEndDate
10190                      2014-01-01             2014-01-31
10190                      2014-02-01             2014-09-30
所需输出:

 10190 | 2014-01-01 | 2014-01-31 | 2014-02-01 | 2014-09-30

有一种方法可以使用FOR XML运算符将日期值连接到单个列中:

DECLARE @tb AS TABLE
(
    InsuredMemberIdentifier INT
    ,CoverageStartDate DATE
    ,CoverageEndDate DATE
)

INSERT INTO @tb VALUES (10190, '2014-01-01', '2014-01-31');
INSERT INTO @tb VALUES (10190, '2014-02-01', '2014-09-30');
INSERT INTO @tb VALUES (10191, '2014-02-01', '2014-09-30');

SELECT DISTINCT InsuredMemberIdentifier
    ,ISNULL(STUFF(
        (SELECT ' ' + CAST(CoverageStartDate  AS NVARCHAR(15)) + ' ' + CAST(CoverageEndDate  AS NVARCHAR(15))
         FROM @tb tb_inner
         WHERE tb_inner.InsuredMemberIdentifier = tb.InsuredMemberIdentifier 
         FOR XML PATH (''))
         ,1,1,''), '') AS ConcatenatedDates
FROM @tb tb
WHERE InsuredMemberIdentifier = 10190

看看SQL pivot和unpivot

样本表

第一步

1.由于需要基于两列值将行转换为columnsPivot,因此需要首先将两列中的值转换为一个称为Unpivot的列。 2.由于您是pivot新手,我正在创建一个临时表来保存值,以便您易于理解。 因此,查询将如下所示

SELECT  ROW_NUMBER() OVER(ORDER BY DATES) COLUMNHEADERS,
InsuredMemberIdentifier,DATES
INTO #TEMP
FROM   #EdgeServer_EligibilityConsolidated_Part3
CROSS apply (VALUES (CoverageStartDate),
                   (CoverageEndDate)) cs (DATES)
WHERE InsuredMemberIdentifier = 10190
交叉应用的工作原理与

SELECT InsuredMemberIdentifier,CoverageStartDate
FROM #EdgeServer_EligibilityConsolidated_Part3
WHERE InsuredMemberIdentifier = 10190

UNION ALL

SELECT InsuredMemberIdentifier,CoverageEndDate
FROM #EdgeServer_EligibilityConsolidated_Part3
WHERE InsuredMemberIdentifier = 10190
所以不要感到困惑

步骤2

此变量中的值将是作为pivot的一部分生成的表的列名

步骤3

由于无法预测日期值或硬编码日期值的数量,因此列的数量将是动态的,无法通过放置逗号进行写入,因此需要使用动态Sql

当您给出PRINT@QUERY而不是EXEC SP_EXECUTESQL@QUERY时,它将显示以下结果

请参见,SQL Server为您动态生成了列名1、2、3、4,因为您使用的是动态SQL。当只有两个日期时,将只生成列名1,2

查看结果 最终结果


选择a.InsuratedMemberIdentifier、a.CoverageStartDate、a.CoverageAndDate、b.CoverageStartDate、b.CoverageAndDate from 选择顶部1*,行号按被保险成员标识符顺序超额分配,从APCD.DBO.EdgeServer中选择0作为r,可提供性按r排序合并的第3部分,
选择顶部1*,行号按被保险人超额分配标识符顺序按从APCD.DBO.EdgeServer中选择0作为r可提供性合并的第3部分按r描述的顺序b

有日期different@Robin,明白你的意思了,那么TOP 1将符合您的要求编辑回答我需要两行值,但在一行中您需要这些日期在一列中还是不同?是否有3行或更多行具有所需的InsuredMemberIdentifier?是的,可以有3行或更多行,我需要在不同的列中显示这些日期不同的列数确实不是个好主意,这与表中数据表示的概念背道而驰。你应该改变你的要求。PIVOT运算符只能使用固定数量的列,例如,在工作日星期日、星期一和星期天。。。到七列。使用XML FOR,您可以将所有这些值连接到一个单独的列nvarchar类型中,而不必考虑行重复,而只需一列!那么,如何使用xml在单个列中获取所有值呢?您现在可以检查我的答案了
SELECT InsuredMemberIdentifier,CoverageStartDate
FROM #EdgeServer_EligibilityConsolidated_Part3
WHERE InsuredMemberIdentifier = 10190

UNION ALL

SELECT InsuredMemberIdentifier,CoverageEndDate
FROM #EdgeServer_EligibilityConsolidated_Part3
WHERE InsuredMemberIdentifier = 10190
DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + CAST(COLUMNHEADERS AS VARCHAR(50)) + ']', 
                '[' + CAST(COLUMNHEADERS AS VARCHAR(50)) + ']')
               FROM (SELECT COLUMNHEADERS FROM #TEMP) PV 
               ORDER BY COLUMNHEADERS
DECLARE @query NVARCHAR(MAX)

SET @query = '--This is the query result - InsuredMemberIdentifier and columns with dates
             SELECT InsuredMemberIdentifier,' + @cols + ' FROM 
             (
                 -- Here you will select the columns before pivoting. COLUMNHEADERS will be name of column
                 -- and each date will be displayed under that column 
                 SELECT COLUMNHEADERS,InsuredMemberIdentifier,DATES
                 FROM #TEMP
             ) x
             PIVOT 
             (
                 -- Tells what should be the values in each column(ie, values in 2014-01-01,2014-01-31 etc)
                 MIN(DATES)
                 -- You will tell SQL to show values in @cols to be the column names
                 -- by taking corresponding DATES from its corresponding COLUMNHEADERS
                 FOR [COLUMNHEADERS] IN (' + @cols + ')
            ) p
            ' 

EXEC SP_EXECUTESQL @query