2016-07-31 25 views
1

我与它的结果下面的查询:将行转换为SQL Server中的常量列?

SELECT * FROM dbo.DeviceView AS dv 
WHERE DeviceId = 5 

结果:

Id  Name      AttachId  ColorId  Date 
---  -------      ----------  -------  ------- 
5  Apple iPhone 5s A1533  NULL   1   2013-09-10 00:00:00.000 
5  Apple iPhone 5s A1533  NULL   8   2013-09-10 00:00:00.000 
5  Apple iPhone 5s A1533  NULL   19   2013-09-10 00:00:00.000 

ColorId是不同势值之内,它可以多于或少于3个值
我想ColorId转换为3列,如ColorId1中的第一个值和ColorId2中的第二个值以及ColorId3中的第三个值。
如:

Id  Name      AttachId ColorId1 ColorId2 ColorId3 Date 
---  -------      ---------- ---------- ---------- ---------- ------- 
5  Apple iPhone 5s A1533  NULL  1   8   19   2013-09-10 00:00:00.000 

我怎样才能将其转换为以下?

编辑
除了ColorId所有其他领域都是一样的。

+0

首先,所有其他列依赖于Id吗?即,你可以在第二行有Name ='SamSung Galaxy 4'吗?或不? 'AttachId'和'Date'是否一样? –

+0

如果这些列依赖于Id,那么你的数据库有规范化问题,你应该首先解决这个问题 –

+0

@CharlesBretana请参阅文章的编辑部分。 –

回答

3

您可以使用基于PIVOT和CTE的这个通用的查询,可以很容易地扩展到任意数量的颜色和执行很好:

-- First, we assign unique numbers to each of the ColorId's. These will become column names 
;WITH NumberedColors (ColorId,ColorNumber) AS (
    SELECT ColorId,'Color'+CAST((ROW_NUMBER() OVER (ORDER BY ColorId)) AS VARCHAR) AS ColorNumber 
    FROM dbo.DeviceView 
    GROUP BY ColorId 
), 
-- Here we return the dbo.DeviceView extended with ColorNumber column name 
DeviceViewWithNumberedColors (Id,Name,AttachId,[Date],ColorNumber,ColorId) AS (
    SELECT Id,Name,AttachId,Date,NC.ColorNumber,NC.ColorId 
      FROM dbo.DeviceView DV 
       INNER JOIN NumberedColors NC ON DV.ColorId=NC.ColorId 
) 
-- Finally, we use the PIVOT to assign color's to the appropriate columns 
SELECT * 
FROM (
     SELECT Id,Name,AttachId,[Date],ColorId,ColorNumber 
     FROM DeviceViewWithNumberedColors D 
    ) AS Source 
    PIVOT (
     SUM(ColorId) FOR ColorNumber IN ([Color1],[Color2],[Color3],[Color4],[Color5],[Color6],[Color7],[Color8],[Color9],[Color10]) 
    ) Piv 

在PIVOT子句中,确保您有足够的Color列。如果这不能进行硬编码,即颜色的数量可能超过固定数量,则使用动态SQL生成此查询。

1

如果你想要的是三种颜色,你可以使用条件的聚集或支点:

select id, name, attachid, 
     max(case when seqnum = 1 then color end) as color1, 
     max(case when seqnum = 2 then color end) as color2, 
     max(case when seqnum = 3 then color end) as color3, 
     date 
from (select t.*, 
      row_number() over (partition by id order by (select null)) as seqnum 
     from t 
    ) t 
group by id, name, attachid, date; 
+0

谢谢,但颜色ID超过3种颜色。它是可变的 –

0

如果ColorId值的计数不是固定数字,则必须使用动态sql。

DECLARE @sql nvarchar(MAX) = 'SELECT Id, Name, AttachId' 

SELECT @sql = @sql 
    + ', MAX(IIF(ValueNum = ' + LTRIM(STR(ColumnNum)) + ', ColorId, NULL)) AS ColorId' + LTRIM(STR(ColumnNum)) 
FROM (
    SELECT DISTINCT 
    DENSE_RANK() OVER (ORDER BY ColorId) AS ColumnNum 
    FROM dbo.DeviceView 
    WHERE Id IN (
    SELECT TOP 1 Id 
    FROM dbo.DeviceView 
    GROUP BY Id 
    ORDER BY COUNT(DISTINCT ColorId) DESC) 
) AS c 

EXEC (@sql 
    + ', [Date] FROM (' 
    + 'SELECT Id, Name, AttachId, ColorId, [Date], DENSE_RANK() OVER (PARTITION BY Id ORDER BY ColorId) AS ValueNum FROM dbo.DeviceView' 
    + ') AS it ' 
    + 'GROUP BY Id, Name, AttachId, [Date]');