2013-08-30 16 views
6

mam stolik jak tenSQL Server jednorzędowe wiele kolumn w jedną kolumnę

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

od tego trzeba utworzyć tabelę temp lub tabelę tak:

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

Czy istnieje sposób I może to zrobić w SQL Server?

+3

Czy zrobiłeś to wszystko formatowanie HTML w swoim pytaniu ręcznie? Jeśli chcesz publikować dane tabelaryczne i zachować formatowanie, możesz po prostu podświetlić blok i nacisnąć przycisk '{}' (przyznam się do porażki pod względem niechęci do usunięcia całego tego formatowania) –

+0

szukasz pustych pól w rzędach tej samej grupy? –

+0

@Damien_The_Unbeliever - Zauważyłem, że. +1 przy wysiłku na rzecz OP. –

Odpowiedz

2

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

Jeżeli chcesz wartości NULL w spoczynku, można spróbować wykonać następujące czynności:

This is the new Fiddle

A oto kod:

;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

Naprawdę nie jest to, co chce OP. Część obrotowa jest w porządku, ale chce również "wyczyścić" wszystkie powtarzające się wartości. –

+2

@TimSchmelter, To nie jest nigdzie wyraźnie wspomniane. Jest to tylko domniemane przez żądane wyniki ... –

+0

@ TimSchmelter Edytowałem swoją odpowiedź i dostarczyłem dodatkowe rozwiązanie, jeśli chcesz to sprawdzić :) –

3

Najprostszym rozwiązaniem byłoby użyć UNION klauzula

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

Łączy wyniki dwóch lub więcej zapytań w jeden zestaw wyników który zawiera wszystkie wiersze, które należą do wszystkie pytania w związku. Operacja UNION różni się od używania złącz łączących kolumny z dwóch tabel.

Poniżej przedstawiono podstawowe zasady łączenia zestawów wyników dwóch zapytań za pomocą UNION:

• liczba i kolejność kolumn muszą być takie same we wszystkich zapytaniami.

• Typy danych muszą być zgodne.

+0

może chcesz wybrać wartości null zamiast reg_no, nazwa_ ucznia ... w wierszach, w których otrzymasz Subject2, 3 itd. –

+0

@RomanPekar - Jeśli OP rzeczywiście potrzebuje tego, jak przedstawiono w pytaniu, masz rację, ale jak on jest wybieram z tej tabeli? Dodatkowy klucz będzie wymagał skomplikowania rzeczy imo. –

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) 

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

Zapytanie nr 2 - ZEWNĘTRZNE ZASTOSOWANIA:

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) 

Plan Zapytanie:

tt

Koszt Zapytanie:

tt2

wyjściowa:

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: W zapytaniu etui z OUTER APPLY jest szybszy niż ROW_NUMBER rozwiązania.

+1

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

+0

@Tim Schmelter dzięki za skrzypce. – Devart

+0

+1 Z zewnętrznej strony. –

Powiązane problemy