2016-07-31 17 views
1

Ich habe die folgende Abfrage mit seinem Ergebnis:Konvertieren von Zeilen in konstante Spalten in SQL Server?

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

Ergebnis:

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 ist innerhalb diffrent Werte und es kann mehr oder weniger als drei Werte sein
Ich möchte konvertieren ColorID zu 3 Spalten, wie der erste Wert in ColorId1 und der zweite Wert in ColorId2 und der dritte Wert in .
zB:

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

Wie kann ich es auf das folgende Format konvertieren?

bearbeiten:
Alle anderen Felder außer ColorId sind die gleichen.

+0

Erstens: Sind alle anderen Spalten von der ID abhängig? d. ,, Könnten Sie Name = 'SamSung Galaxy 4' in der zweiten Reihe haben? oder nicht? Gleiches mit 'AttachId' und' Date'? –

+0

Wenn diese Spalten von ID abhängig sind, dann hat Ihre Datenbank Normalisierungsprobleme., Die Sie zuerst lösen sollten –

+0

@CharlesBretana Siehe Abschnitt bearbeiten von Post. –

Antwort

3

Sie können diese generische Abfrage basierend auf Kreis- und CTE, die leicht für eine beliebige Anzahl von Farben erweitert werden kann, und dass führt sehr gut:

-- 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 

Vergewissern Sie sich in der PIVOT-Klausel, dass Sie genügend Farbspalten haben. Wenn dies nicht fest codiert werden kann, d. H. Die Anzahl der Farben könnte über eine feste Zahl hinaus wachsen, dann verwenden Sie dynamisches SQL, um diese Abfrage zu erzeugen.

1

Wenn Sie genau drei Farben wünschen, Sie bedingte Aggregation oder Pivot verwenden können:

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

Danke, aber Farb-IDs sind mehr als 3 Farben. es ist variabel –

0

Wenn die Anzahl der ColorId-Werte keine feste Zahl ist, müssen Sie dynamic sql verwenden.

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]');