2013-08-30 45 views
6

Tôi có bảng như thế nàysql máy chủ đơn hàng nhiều cột thành một cột

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

Từ này tôi cần phải tạo ra một bảng tạm thời hoặc bảng như thế này:

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

Có cách nào tôi có thể làm điều này trong SQL Server?

+3

Bạn đã thực hiện tất cả định dạng HTML đó trong câu hỏi của mình chưa? Nếu bạn muốn đăng dữ liệu dạng bảng và giữ nguyên định dạng, bạn có thể vừa đánh dấu khối và nhấn nút '{}' (tôi sẽ thừa nhận thất bại về việc không sẵn sàng đưa ra tất cả định dạng đó) –

+0

bạn đang tìm kiếm các khoảng trống trong các hàng của cùng một nhóm? –

+0

@Damien_The_Unbeliever - Tôi đã nhận thấy điều đó. +1 trên nỗ lực để OP. –

Trả lời

2

Kiểm tra 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 

Nếu bạn làm muốn giá trị NULL trong phần còn lại, bạn có thể thử như sau:

This is the new Fiddle

Và đây là đoạn 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

Không thực sự là những gì OP muốn. Phần trục là tốt, nhưng anh ta cũng muốn "xóa" tất cả các giá trị lặp lại. –

+2

@TimSchmelter, Điều này không được đề cập rõ ràng ở bất kỳ đâu. Nó chỉ được ngụ ý bởi các kết quả được yêu cầu ... –

+0

@TimSchmelter Tôi đã chỉnh sửa câu trả lời của mình và cung cấp giải pháp bổ sung, nếu bạn muốn kiểm tra :) –

3

Phương pháp đơn giản nhất là nên sử dụng một điều khoản UNION

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

Kết hợp các kết quả của hai hay nhiều truy vấn vào một kết quả duy nhất thiết lập bao gồm tất cả các hàng thuộc tất cả các truy vấn trong liên minh. Hoạt động UNION khác với sử dụng các phép nối kết hợp các cột từ hai bảng.

Sau đây là những nguyên tắc cơ bản để kết hợp các bộ kết quả của hai truy vấn bằng cách sử dụng UNION:

• Số lượng và thứ tự của các cột phải giống nhau trong tất cả các truy vấn.

• Các loại dữ liệu phải tương thích.

+0

có thể bạn muốn chọn null thay vì reg_no, student_name ... trong các hàng mà bạn nhận được Subject2, 3 và như vậy trên –

+0

@RomanPekar - Nếu OP thực sự cần nó như được trình bày trong câu hỏi, bạn là đúng nhưng làm thế nào là ông bao giờ sẽ chọn từ bảng đó? Một khóa bổ sung sẽ được yêu cầu làm phức tạp những thứ 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) 

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

Query # 2 - OUTER ÁP DỤNG:

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) 

Kế hoạch truy vấn:

tt

Query Chi phí:

tt2

Output:

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: Trong truy vấn trường hợp của bạn với OUTER APPLY là nhanh hơn so với giải pháp ROW_NUMBER.

+1

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

+0

@Tim Schmelter cảm ơn câu chuyện. – Devart

+0

+1 Trên mặt ngoài được áp dụng. –

Các vấn đề liên quan