2013-08-30 8 views
6

I Tisch haben wie dieseSQL Server einzelne Zeile mehrere Spalten in einer Spalte

Reg_No  Student_Name   Subject1 Subject2 Subject3 Subject4 Total 
----------- -------------------- ----------- ----------- ----------- ----------- ----------- 
101   Kevin    85   94   78   90   347 
102   Andy     75   88   91   78   332 

Daraus muss ich wie diese eine temporäre Tabelle oder eine Tabelle erstellen:

Reg_No  Student_Name   Subject  Total 
----------- -------------------- ----------- ----------- 
101   Kevin    85   347 
           94   
           78   
           90   
102   Andy     75   332 
           88   
           91   
           78   

Gibt es eine Möglichkeit, kann dies in SQL Server tun?

+3

Haben Sie diese HTML-Formatierung in Ihrer Frage von Hand gemacht? Wenn Sie Tabellendaten posten und die Formatierung beibehalten möchten, hätten Sie einfach den Block markieren und den '{}' Knopf drücken können (ich gebe zu, dass ich nicht bereit bin, all diese Formatierungen selbst zu löschen) –

+0

Are Sie suchen nach Leerstellen Felder in Reihen der gleichen Gruppe? –

+0

@Damien_The_Unbeliever - Ich habe das bemerkt. +1 auf Aufwand zu OP. –

Antwort

2

prüfen this Fiddle

;WITH MyCTE AS 
(
    SELECT * 
    FROM  (
        SELECT Reg_No, 
          [Subject1], 
          [Subject2], 
          [Subject3], 
          [Subject4] 
        FROM  Table1 
      )p 
    UNPIVOT 
    ( 
     Result FOR SubjectName in ([Subject1], [Subject2], [Subject3], [Subject4]) 
    )unpvt 
) 

SELECT T.Reg_No, 
      T.Student_Name, 
      M.SubjectName, 
      M.Result, 
      T.Total 
FROM  Table1 T 
      JOIN MyCTE M 
       ON T.Reg_No = M.Reg_No 

Wenn Sie NULL-Werte in den Rest tun möchten, können Sie versuchen die folgende:

This is the new Fiddle

Und hier ist der Code:

;WITH MyCTE AS 
(
    SELECT * 
    FROM  (
        SELECT Reg_No, 
          [Subject1], 
          [Subject2], 
          [Subject3], 
          [Subject4] 
        FROM  Table1 
      )p 
    UNPIVOT 
    ( 
     Result FOR SubjectName in ([Subject1], [Subject2], [Subject3], [Subject4]) 
    )unpvt 
), 
MyNumberedCTE AS 
(
    SELECT *, 
       ROW_NUMBER() OVER(PARTITION BY Reg_No ORDER BY Reg_No,SubjectName) AS RowNum 
    FROM  MyCTE 
) 
SELECT T.Reg_No, 
      T.Student_Name, 
      M.SubjectName, 
      M.Result, 
      T.Total 
FROM  MyCTE M 
      LEFT JOIN MyNumberedCTE N 
       ON N.Reg_No = M.Reg_No 
       AND N.SubjectName = M.SubjectName 
       AND N.RowNum=1 
      LEFT JOIN Table1 T 
       ON T.Reg_No = N.Reg_No 
+0

Ist nicht wirklich was OP will. Der Pivot-Teil ist in Ordnung, aber er möchte auch alle sich wiederholenden Werte "löschen". –

+2

@TimSchmelter, Dies wird nirgendwo explizit erwähnt. Es ist nur impliziert durch die angeforderten Ergebnisse ... –

+0

@TimSchmelter Ich habe meine Antwort bearbeitet und eine zusätzliche Lösung zur Verfügung gestellt, wenn Sie überprüfen möchten :) –

3

würde Der einfachste Ansatz eine UNION Klausel

select Reg_No, Student_Name, Subject1, Total from YourTable union all 
select Reg_No, Student_Name, Subject2, Total from YourTable union all 
select Reg_No, Student_Name, Subject3, Total from YourTable union all 
select Reg_No, Student_Name, Subject3, Total from YourTable 

UNION

kombiniert die Ergebnisse von zwei oder mehr Abfragen in ein einziges Ergebnis Set zu verwenden, die alle Zeilen enthalten, die zu gehören alle Abfragen in der Union. Die UNION-Operation unterscheidet sich von der Verwendung von Joins, die die Spalten aus zwei Tabellen kombinieren.

Die folgenden grundlegenden Regeln zum Kombinieren der Ergebnismengen von zwei Abfragen von UNION mit:

• Die Anzahl und die Reihenfolge der Spalten müssen gleich in allen Abfragen sein.

• Die Datentypen müssen kompatibel sein.

+0

Vielleicht möchten Sie Nullen anstelle von reg_no, student_name ... in Zeilen, wo Sie Subject2, 3 und so weiter –

+0

@RomanPekar wählen - Wenn OP tatsächlich benötigt, wie in der Frage dargestellt, haben Sie Recht, aber wie ist er jemals Wählen Sie aus dieser Tabelle einen zusätzlichen Schlüssel wäre komplizierter Dinge imo erforderlich. –

5

DDL:

DECLARE @temp TABLE 
(
     Reg_No INT 
    , Student_Name VARCHAR(20) 
    , Subject1 INT 
    , Subject2 INT 
    , Subject3 INT 
    , Subject4 INT 
    , Total INT 
) 

INSERT INTO @temp (Reg_No, Student_Name, Subject1, Subject2, Subject3, Subject4, Total) 
VALUES 
    (101, 'Kevin', 85, 94, 78, 90, 347), 
    (102, 'Andy ', 75, 88, 91, 78, 332) 

Abfrage # 1 - ROW_NUMBER:

SELECT Reg_No = CASE WHEN rn = 1 THEN t.Reg_No END 
    , Student_Name = CASE WHEN rn = 1 THEN t.Student_Name END 
    , t.[Subject] 
    , Total = CASE WHEN rn = 1 THEN t.Total END 
FROM (
    SELECT 
      Reg_No 
     , Student_Name 
     , [Subject] 
     , Total 
     , rn = ROW_NUMBER() OVER (PARTITION BY Reg_No ORDER BY 1/0) 
    FROM @temp 
    UNPIVOT 
    (
     [Subject] FOR tt IN (Subject1, Subject2, Subject3, Subject4) 
    ) unpvt 
) t 

Abfrage # 2 - OUTER APPLY:

SELECT t.* 
FROM @temp 
OUTER APPLY 
(
    VALUES 
     (Reg_No, Student_Name, Subject1, Total), 
     (NULL, NULL, Subject2, NULL), 
     (NULL, NULL, Subject3, NULL), 
     (NULL, NULL, Subject4, NULL) 
) t(Reg_No, Student_Name, [Subject], Total) 

Query Plan:

tt

Abfrage Kosten:

tt2

Ausgang:

Reg_No  Student_Name   Subject  Total 
----------- -------------------- ----------- ----------- 
101   Kevin    85   347 
NULL  NULL     94   NULL 
NULL  NULL     78   NULL 
NULL  NULL     90   NULL 
102   Andy     75   332 
NULL  NULL     88   NULL 
NULL  NULL     91   NULL 
NULL  NULL     78   NULL 

PS: In Ihrem Fall Abfrage mit OUTER APPLY ist schneller als ROW_NUMBER Lösung.

+1

+1 SQl-Geige: http://sqlfiddle.com/#!6/a6c86/11/0 –

+0

@Tim Schmelter danke für die Geige. – Devart

+0

+1 Auf der äußeren anwenden. –

Verwandte Themen