2010-06-25 23 views
24

Tôi có một bảng cơ sở dữ liệu Sql tương tự như sau:Làm thế nào để xoay hàng vào cột (tùy chỉnh pivoting)

Day Period Subject 

Mon 1   Ch 
Mon 2   Ph 
Mon 3   Mth 
Mon 4   CS 
Mon 5   Lab1 
Mon 6   Lab2 
Mon 7   Lab3 
Tue 1   Ph 
Tue 2   Ele 
Tue 3   Hu 
Tue 4   Ph 
Tue 5   En 
Tue 6   CS2 
Tue 7   Mth 

Tôi muốn nó hiển thị như sau: Loại crosstab hoặc Pivot

Day P1 P2 P3 P4 P5 P6 P7 

Mon Ch Ph Mth CS2 Lab1 Lab2 Lab3 
Tue Ph Ele Hu Ph En CS2 Mth 

Điều gì sẽ là cách lý tưởng để làm điều đó? Ai đó có thể vui lòng cho tôi xem mã Sql được không?

Trả lời

17

Bạn có thể có thể làm điều đó với chức năng PIVOT, nhưng tôi thích phương pháp học cũ:

SELECT 
    dy, 
    MAX(CASE WHEN period = 1 THEN subj ELSE NULL END) AS P1, 
    MAX(CASE WHEN period = 2 THEN subj ELSE NULL END) AS P2, 
    MAX(CASE WHEN period = 3 THEN subj ELSE NULL END) AS P3, 
    MAX(CASE WHEN period = 4 THEN subj ELSE NULL END) AS P4, 
    MAX(CASE WHEN period = 5 THEN subj ELSE NULL END) AS P5, 
    MAX(CASE WHEN period = 6 THEN subj ELSE NULL END) AS P6, 
    MAX(CASE WHEN period = 7 THEN subj ELSE NULL END) AS P7 
FROM 
    Classes 
GROUP BY 
    dy 
ORDER BY 
    CASE dy 
     WHEN 'Mon' THEN 1 
     WHEN 'Tue' THEN 2 
     WHEN 'Wed' THEN 3 
     WHEN 'Thu' THEN 4 
     WHEN 'Fri' THEN 5 
     WHEN 'Sat' THEN 6 
     WHEN 'Sun' THEN 7 
     ELSE 8 
    END 
  • tôi đã thay đổi một số tên cột để tránh từ dành riêng
+0

+1: Bạn là nhanh hơn & có ORDER BY . Vì vậy, tôi sẽ chỉ thêm: Như bạn có thể thấy, các cột động sẽ yêu cầu sử dụng SQL động. Có cú pháp ANSI PIVOT, nhưng nó chỉ được hỗ trợ trên SQL Server 2005+ và Oracle 11g. –

+0

Tôi hiện đang làm điều này trong SQLite, nhưng nó dường như là một hoạt động khá chuyên sâu. Có ai biết nếu có một giải pháp hiệu quả hơn? – EnemyBagJones

+0

Tôi không tin rằng SQLite có bất kỳ loại hàm pivot nào được tích hợp sẵn, vì vậy đây có lẽ là những gì bạn đang mắc phải. Tuy nhiên, tôi không sử dụng SQLite, vì vậy có lẽ ai đó có nhiều kinh nghiệm hơn với nhà cung cấp SQL cụ thể đó có ý tưởng tốt hơn. –

1

Bạn có thể thử ...

SELECT DISTINCT Day, 
     (SELECT Subject 
      FROM my_table mt2 
      WHERE mt2.Day = mt.Day AND 
        Period = 1) AS P1, 
     (SELECT Subject 
      FROM my_table mt2 
      WHERE mt2.Day = mt.Day AND 
        Period = 2) AS P2, 
    . 
    . 
    etc 
    . 
    . 
    . 
    (SELECT Subject 
     FROM my_table mt2 
     WHERE mt2.Day = mt.Day AND 
       Period = 7) AS P7 
FROM my_table mt; 

nhưng tôi không thể nói rằng tôi thích nó rất nhiều. Tốt hơn là không có gì, mặc dù.

1

Sử dụng chéo áp dụng cho có được tất cả các giá trị trong một định dạng dấu phẩy được xóa trong một cột đơn. thay vì "7" cột khác nhau. Các truy vấn sau đây có thể được sử dụng cho bất kỳ lập bản đồ column-> hàng

SELECT DISTINCT Day, [DerivedColumn] FROM <Table> A CROSS APPLY (SELECT Period + ',' FROM <Table> B WHERE A.Day = B.Day Order By Period FOR XML PATH('')) AS C (DerivedColumn) 

Bạn sẽ nhận được [Ch, Ph, MTH, CS2, Lab1, Lab2, Lab3] trong một cột cho Mon và vân vân ... Bạn có thể sử dụng bảng này để truy vấn cho bất kỳ Ngày cụ thể nào.

Hy vọng điều này sẽ giúp

12

Chỉ trong trường hợp bạn muốn có phương pháp học mới. (Tuyên bố Pivot nên làm việc trong SQL2005 +, các bit VALUES cho ví dụ dữ liệu chỉ SQL2008)

WITH ExampleData AS 
(
SELECT X.* 
    FROM (VALUES 
('Mon', 1, 'Ch'), 
('Mon', 2, 'Ph'), 
('Mon', 3, 'Mth'), 
('Mon', 4, 'CS'), 
('Mon', 5, 'Lab1'), 
('Mon', 6, 'Lab2'), 
('Mon', 7, 'Lab3'), 
('Tue', 1, 'Ph'), 
('Tue', 2, 'Ele'), 
('Tue', 3, 'Hu'), 
('Tue', 4, 'Ph'), 
('Tue', 5, 'En'), 
('Tue', 6, 'CS2'), 
('Tue', 7, 'Mth') 
) AS X (Day, Period, Subject) 
) 

SELECT Day, [1] AS P1, [2] AS P2,[3] AS P3, [4] AS P4, [5] AS P5,[6] AS P6,[7] AS P7 
FROM ExampleData 
PIVOT 
( 
Max(Subject) 
FOR Period IN ([1], [2],[3],[4], [5],[6], [7]) 
) AS PivotTable; 

quả

Day P1 P2 P3 P4 P5 P6 P7 
---- ---- ---- ---- ---- ---- ---- ---- 
Mon Ch Ph Mth CS Lab1 Lab2 Lab3 
Tue Ph Ele Hu Ph En CS2 Mth 
+1

Tại sao Max (Chủ đề)? Đây có phải là vì PIVOT phải có chức năng tổng hợp không? – JBRWilkinson

+1

@JBRWilkinson Có. Chính xác. Chỉ nên có một bản ghi phù hợp cho kết hợp Ngày/Thời gian để 'MIN' có thể hoạt động tốt như nhau. –

0
with pivot_data as 
(
select [day], -- groping column 
period, -- spreading column 
subject -- aggreate column 
from pivot_tb 
) 
select [day], [1] AS P1, [2] AS P2,[3] AS P3, [4] AS P4, [5] AS P5,[6] AS P6,[7] AS P7 
from pivot_data 
pivot (max(subject) for period in ([1], [2],[3],[4], [5],[6], [7])) as p; 
1
DECLARE @TIMETABLE TABLE (
    [Day]  CHAR(3), 
    [Period] TINYINT, 
    [Subject] CHAR(5) 
) 
INSERT INTO @TIMETABLE([Day], [Period], [Subject]) 
VALUES 
    ('Mon', 1, 'Ch'), 
    ('Mon', 2, 'Ph'), 
    ('Mon', 3, 'Mth'), 
    ('Mon', 4, 'CS'), 
    ('Mon', 5, 'Lab1'), 
    ('Mon', 6, 'Lab2'), 
    ('Mon', 7, 'Lab3'), 
    ('Tue', 1, 'Ph'), 
    ('Tue', 2, 'Ele'), 
    ('Tue', 3, 'Hu'), 
    ('Tue', 4, 'Ph'), 
    ('Tue', 5, 'En'), 
    ('Tue', 6, 'CS2'), 
    ('Tue', 7, 'Mth') 

SELECT 
    [Day], 
    MAX(CASE [Period] WHEN 1 THEN [Subject] END) AS P1, 
    MAX(CASE [Period] WHEN 2 THEN [Subject] END) AS P2, 
    MAX(CASE [Period] WHEN 3 THEN [Subject] END) AS P3, 
    MAX(CASE [Period] WHEN 4 THEN [Subject] END) AS P4, 
    MAX(CASE [Period] WHEN 5 THEN [Subject] END) AS P5, 
    MAX(CASE [Period] WHEN 6 THEN [Subject] END) AS P6, 
    MAX(CASE [Period] WHEN 7 THEN [Subject] END) AS P7 
FROM @TIMETABLE 
GROUP BY [Day] 
+0

Đây có phải là ANSI SQL không? – ViniciusPires

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