2012-05-29 18 views
7

Tôi đã viết truy vấn này:Pivot với một lượng không xác định các giá trị khác biệt

SELECT s, [1] AS a1, [2] AS a2, [3] AS a3, [4] AS a4 
FROM (SELECT grade, aid, s FROM m) p 
PIVOT 
(
SUM(grade) 
FOR aid IN ([1], [2], [3], [4]) 
) AS pvt ORDER BY pvt.s; 

Đó trả về kết quả:

s a1 a2 a3 a4 
1 25 69 95 56 
2 27 99 16 87 
. . . . 
99 98 12 34 76 

Mà chính xác là kết quả tôi muốn. Vấn đề của tôi là sẽ không phải lúc nào cũng có bốn giá trị riêng biệt trong 'viện trợ'. Có thể viết lại truy vấn này (hoặc sử dụng một thủ tục đã lưu trữ) để số lượng cột 'a *' phụ thuộc vào số lượng giá trị khác nhau trong 'viện trợ' không?

Trả lời

11

Bạn sẽ cần phải sử dụng Pivot động để có danh sách các cột bạn muốn. Điều này sẽ lấy danh sách các cột đầu tiên và sau đó xoay vòng danh sách đó. Một cái gì đó tương tự như thế này:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX); 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(aid) 
      FROM m 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT s, ' + @cols + ' from 
      (
       select grade, aid, s 
       from m 
      ) x 
      pivot 
      (
       sum(grade) 
       for aid in (' + @cols + ') 
      ) p 
      ORDER BY p.s' 

execute(@query) 
+0

Xin cảm ơn, đó chính là điều tôi muốn! –

+1

+1 - Mặc dù là nitpicky, bạn đang thiếu bí danh cho các cột của mình – Lamak

2

Lamak: Đây là cách tôi đã làm nó với bí danh cột. Bí danh được liên kết với giá trị từ một cột trong bảng khác được liên kết bởi `viện trợ '.

DECLARE 
    @cols AS NVARCHAR(MAX), 
    @colsAlias AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX); 

SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(aid) 
    FROM m 
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'') 

SELECT @colsAlias = STUFF((SELECT DISTINCT ',' + QUOTENAME(m.aid) + ' AS ' + QUOTENAME(n.aName) 
    FROM m INNER JOIN n ON m.aid = n.aid 
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'') 

SET @query = 'SELECT s, ' + @colsAlias + ' FROM 
       (
       SELECT grade, aid, s 
        FROM m 
       ) x 

      PIVOT 
      (
       MIN(grade) FOR aid IN (' + @cols + ') 
      ) p ' 

EXECUTE(@query) 
Các vấn đề liên quan