将行数据转换为sqlserver 2008中的列

时间:2015-02-17 12:14:05

标签: sql-server-2008

在下面的例子中我有2条记录,但每个id的no或记录都没有修复......

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

4 个答案:

答案 0 :(得分:0)

有一种方法可以使用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

答案 1 :(得分:0)

样本表

CREATE TABLE #EdgeServer_EligibilityConsolidated_Part3 (InsuredMemberIdentifier INT, CoverageStartDate DATE,   CoverageEndDate DATE)

INSERT INTO #EdgeServer_EligibilityConsolidated_Part3
SELECT 10190 ,                     '2014-01-01',             '2014-01-31'
UNION ALL
SELECT 10190,                      '2014-02-01',             '2014-09-30'

第1步

1.由于您需要根据两个列值将行转换为列(Pivot),因此您需要先将两列中的值转换为一列(称为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

CROSS APPLY的工作方式与

相同
SELECT InsuredMemberIdentifier,CoverageStartDate
FROM #EdgeServer_EligibilityConsolidated_Part3
WHERE InsuredMemberIdentifier = 10190

UNION ALL

SELECT InsuredMemberIdentifier,CoverageEndDate
FROM #EdgeServer_EligibilityConsolidated_Part3
WHERE InsuredMemberIdentifier = 10190

所以不要混淆。

第2步

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

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

第3步

由于您无法预测日期值或硬编码日期值的数量(因为列数将是动态的,无法通过逗号写入),您需要使用Dynamic Sql

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

当您提供PRINT @QUERY而不是EXEC SP_EXECUTESQL @query时,它会显示以下结果

enter image description here

请参阅,SQL Server为您动态生成了列名1,2,3,4,因为您使用的是Dynamic Sql。如果只有两个日期,则只会生成列名1,2

最终结果

enter image description here

答案 2 :(得分:0)

选择a.InsuredMemberIdentifier,a.CoverageStartDate,a.CoverageEndDate,b.CoverageStartDate,b.CoverageEndDate from (选择top 1 *,ROW_NUMBER()over(InsuredMemberIdentifier order by(select 0))by r from APCD.DBO.EdgeServer_EligibilityConsolidated_Part3 order by r)a, (选择top 1 *,ROW_NUMBER()over(InsuredMemberIdentifier order by(select 0))by r from APCD.DBO.EdgeServer_EligibilityConsolidated_Part3 order by r desc)b

答案 3 :(得分:-1)

相关问题