2015-01-08 14 views
8

Tôi biết nhiều bạn đã quan sát hành vi này, nhưng tôi tự hỏi liệu có ai có thể giải thích lý do tại sao không. Khi tôi tạo ra một bảng nhỏ để tạo ra một ví dụ về cách sử dụng các chức năng trục, tôi nhận được kết quả tôi mong đợi:Tại sao trục xoay với cột "phụ" không kết hợp các kết quả

CREATE TABLE dbo.AverageFishLength 
    (
     Fishtype VARCHAR(50) , 
     AvgLength DECIMAL(8, 2) , 
     FishAge_Years INT 
    ) 
INSERT INTO dbo.AverageFishLength 
     (Fishtype, AvgLength, FishAge_Years) 
VALUES ('Muskie', 32.75, 3), 
     ('Muskie', 37.5, 4), 
     ('Muskie', 39.75, 5), 
     ('Walleye', 16.5, 3), 
     ('Walleye', 18.25, 4), 
     ('Walleye', 20.0, 5), 
     ('Northern Pike', 20.75, 3), 
     ('Northern Pike', 23.25, 4), 
     ('Northern Pike', 26.0, 5); 

Dưới đây là truy vấn trục:

SELECT Fishtype , 
     [3] AS [3 Years Old] , 
     [4] AS [4 Years Old] , 
     [5] AS [5 Years Old] 
FROM dbo.AverageFishLength PIVOT(SUM(AvgLength) 
           FOR FishAge_Years IN ([3], [4], [5])) AS PivotTbl 

Dưới đây là kết quả:

enter image description here

Tuy nhiên, nếu tôi có thể tạo bảng với một cột sắc, kết quả được chia thành dòng riêng biệt:

DROP TABLE dbo.AverageFishLength 
CREATE TABLE dbo.AverageFishLength 
    (
     ID INT IDENTITY(1,1) , 
     Fishtype VARCHAR(50) , 
     AvgLength DECIMAL(8, 2) , 
     FishAge_Years INT 
    ) 
INSERT INTO dbo.AverageFishLength 
     (Fishtype, AvgLength, FishAge_Years) 
VALUES ('Muskie', 32.75, 3), 
     ('Muskie', 37.5, 4), 
     ('Muskie', 39.75, 5), 
     ('Walleye', 16.5, 3), 
     ('Walleye', 18.25, 4), 
     ('Walleye', 20.0, 5), 
     ('Northern Pike', 20.75, 3), 
     ('Northern Pike', 23.25, 4), 
     ('Northern Pike', 26.0, 5); 

Cùng truy vấn chính xác:

SELECT Fishtype , 
     [3] AS [3 Years Old] , 
     [4] AS [4 Years Old] , 
     [5] AS [5 Years Old] 
FROM dbo.AverageFishLength PIVOT(SUM(AvgLength) 
           FOR FishAge_Years IN ([3], [4], [5])) AS PivotTbl 

kết quả khác nhau:

enter image description here

Nó xuất hiện với tôi rằng cột ID đang được sử dụng trong truy vấn, mặc dù nó không xuất hiện trong tất cả các truy vấn. Nó gần giống như nó được bao gồm trong truy vấn, nhưng không được hiển thị trong tập kết quả.

Có ai giải thích tại sao điều này xảy ra không?

+1

Tôi nên thêm rằng tôi biết cách sử dụng nó, sử dụng truy vấn phụ hoặc row_number hơn ... Tôi thực sự chỉ quan tâm đến lý do tại sao nó xảy ra. –

+2

Câu hỏi này khiến tôi đói – billinkc

Trả lời

11

Điều này xảy ra vì cột ID là duy nhất cho mỗi hàng và vì bạn đang truy vấn trực tiếp bảng (không có truy vấn phụ), cột đó được bao gồm như một phần của nhu cầu chức năng tổng hợp.

Các tài liệu các MSDN docs about FROM nhà nước như sau:

table_source PIVOT <pivot_clause>

Chỉ định rằng table_source được xoay dựa trên pivot_column. table_source là một biểu thức bảng hoặc bảng. Đầu ra là một bảng chứa tất cả các cột của table_source ngoại trừ pivot_column và value_column. Các cột của table_source, ngoại trừ pivot_column và value_column, được gọi là các cột nhóm của toán tử xoay vòng.

PIVOT thực hiện một hoạt động nhóm trên bảng đầu vào liên quan đến các cột nhóm với và trả một hàng cho mỗi nhóm. Ngoài ra, đầu ra chứa một cột cho mỗi giá trị được chỉ định trong cột_list xuất hiện trong pivot_column của input_table.

Phiên bản của bạn về cơ bản là nói số SELECT * FROM yourtable và PIVOT dữ liệu đó. Mặc dù cột ID không có trong danh sách SELECT cuối cùng của bạn, nó là một phần tử nhóm trên truy vấn. Nếu bạn so sánh PIVOT với ví dụ "tiền PIVOT" để hiển thị, bạn sẽ thấy phiên bản của mình.Ví dụ này sử dụng một biểu thức CASE và một chức năng tổng hợp:

SELECT Fishtype, 
    sum(case when FishAge_Years = 3 then AvgLength else 0 end) as [3], 
    sum(case when FishAge_Years = 4 then AvgLength else 0 end) as [4], 
    sum(case when FishAge_Years = 5 then AvgLength else 0 end) as [5] 
FROM dbo.AverageFishLength 
GROUP BY Fishtype, ID; 

Kết quả sẽ được lệch vì ngay cả khi bạn không có ID trong danh sách cuối cùng, nó vẫn còn được sử dụng để nhóm bằng và vì chúng là độc đáo , bạn nhận được nhiều hàng.

Cách đơn giản nhất để giải quyết này khi sử dụng PIVOT đang sử dụng một subquery:

SELECT Fishtype , 
     [3] AS [3 Years Old] , 
     [4] AS [4 Years Old] , 
     [5] AS [5 Years Old] 
FROM 
(
    SELECT Fishtype, 
    AvgLength, 
    FishAge_Years 
    FROM dbo.AverageFishLength 
) d 
PIVOT 
( 
    SUM(AvgLength) 
    FOR FishAge_Years IN ([3], [4], [5]) 
) AS PivotTbl; 

Trong phiên bản này bạn chỉ trả lại các cột mà bạn thực sự cần và muốn từ bảng của bạn - điều này không bao gồm ID nên nó sẽ không được sử dụng để nhóm dữ liệu của bạn.

+0

Ok, tôi hiểu rồi. Nó sẽ được tốt đẹp nếu nó đã được minh bạch hơn trong cú pháp hoặc nếu bạn có thể loại trừ các cột nhất định từ bảng bằng cách loại trừ chúng từ SELECT thay vì phải làm một truy vấn phụ. Cảm ơn bạn đã giải thích kỹ lưỡng. –

+0

@ Dave.Gugg Nó thực sự là trong các tài liệu, xem chỉnh sửa của tôi. Nó được ẩn trong các tài liệu cho ['FROM'] (http://technet.microsoft.com/en-us/library/ms177634%28v=sql.105%29.aspx). – Taryn

+3

(+1) Tôi hiếm khi sử dụng 'PIVOT' những ngày này. Phương pháp thủ công thường rõ ràng hơn, được cho là dễ đọc hơn và kết quả chính xác trong cùng một kế hoạch thực hiện. –

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