Tôi biết câu hỏi này đã cũ hơn nhưng tôi đã tìm kiếm câu trả lời và nghĩ rằng tôi có thể mở rộng phần "động" của vấn đề và có thể giúp đỡ ai đó.
Trước hết tôi đã xây dựng giải pháp này để giải quyết vấn đề mà một vài đồng nghiệp đang gặp phải với các bộ dữ liệu lớn và bất tiện cần phải được xoay vòng nhanh chóng.
Giải pháp này yêu cầu tạo ra một thủ tục được lưu trữ, vì vậy nếu đó không phải là câu hỏi cho nhu cầu của bạn, xin vui lòng ngừng đọc ngay bây giờ.
Quy trình này sẽ thực hiện các biến chính của câu lệnh trục để tạo động các câu lệnh trục cho các bảng, tên cột và tổng hợp khác nhau. Cột tĩnh được sử dụng làm cột theo nhóm / nhận dạng cho trục (điều này có thể được loại bỏ khỏi mã nếu không cần thiết nhưng khá phổ biến trong các câu lệnh trục và cần thiết để giải quyết vấn đề ban đầu), cột trụ là nơi tên cột kết quả cuối cùng sẽ được tạo từ và cột giá trị là những gì tổng hợp sẽ được áp dụng cho. Tham số Bảng là tên của bảng bao gồm lược đồ (lược đồ.tablename) phần mã này có thể sử dụng một số tình yêu vì nó không sạch như tôi mong muốn. Nó hiệu quả với tôi vì việc sử dụng của tôi không phải đối mặt công khai và tiêm sql không phải là vấn đề đáng lo ngại.
Hãy bắt đầu với mã để tạo thủ tục được lưu trữ. Mã này sẽ hoạt động trong tất cả các phiên bản SSMS 2005 trở lên nhưng tôi chưa thử nghiệm nó vào năm 2005 hoặc 2016 nhưng tôi không thể hiểu tại sao nó không hoạt động.
create PROCEDURE [dbo].[USP_DYNAMIC_PIVOT]
(
@STATIC_COLUMN VARCHAR(255),
@PIVOT_COLUMN VARCHAR(255),
@VALUE_COLUMN VARCHAR(255),
@TABLE VARCHAR(255),
@AGGREGATE VARCHAR(20) = null
)
AS
BEGIN
SET NOCOUNT ON;
declare @AVAIABLE_TO_PIVOT NVARCHAR(MAX),
@SQLSTRING NVARCHAR(MAX),
@PIVOT_SQL_STRING NVARCHAR(MAX),
@TEMPVARCOLUMNS NVARCHAR(MAX),
@TABLESQL NVARCHAR(MAX)
if isnull(@AGGREGATE,'') = ''
begin
SET @AGGREGATE = 'MAX'
end
SET @PIVOT_SQL_STRING = 'SELECT top 1 STUFF((SELECT distinct '', '' + CAST(''[''+CONVERT(VARCHAR,'+ @PIVOT_COLUMN+')+'']'' AS VARCHAR(50)) [text()]
FROM '+@TABLE+'
WHERE ISNULL('+@PIVOT_COLUMN+','''') <> ''''
FOR XML PATH(''''), TYPE)
.value(''.'',''NVARCHAR(MAX)''),1,2,'' '') as PIVOT_VALUES
from '+@TABLE+' ma
ORDER BY ' + @PIVOT_COLUMN + ''
declare @TAB AS TABLE(COL NVARCHAR(MAX) )
INSERT INTO @TAB EXEC SP_EXECUTESQL @PIVOT_SQL_STRING, @AVAIABLE_TO_PIVOT
SET @AVAIABLE_TO_PIVOT = (SELECT * FROM @TAB)
SET @TEMPVARCOLUMNS = (SELECT replace(@AVAIABLE_TO_PIVOT,',',' nvarchar(255) null,') + ' nvarchar(255) null')
SET @SQLSTRING = 'DECLARE @RETURN_TABLE TABLE ('+@STATIC_COLUMN+' NVARCHAR(255) NULL,'+@TEMPVARCOLUMNS+')
INSERT INTO @RETURN_TABLE('+@STATIC_COLUMN+','+@AVAIABLE_TO_PIVOT+')
select * from (
SELECT ' + @STATIC_COLUMN + ' , ' + @PIVOT_COLUMN + ', ' + @VALUE_COLUMN + ' FROM '+@TABLE+' ) a
PIVOT
(
'+@AGGREGATE+'('+@VALUE_COLUMN+')
FOR '+@PIVOT_COLUMN+' IN ('+@AVAIABLE_TO_PIVOT+')
) piv
SELECT * FROM @RETURN_TABLE'
EXEC SP_EXECUTESQL @SQLSTRING
END
Tiếp theo chúng tôi sẽ lấy dữ liệu của chúng tôi sẵn sàng cho ví dụ. Tôi đã lấy ví dụ dữ liệu từ câu trả lời được chấp nhận với việc thêm một vài yếu tố dữ liệu để sử dụng trong bằng chứng khái niệm này để hiển thị các kết quả đầu ra khác nhau của thay đổi tổng hợp.
create table temp
(
date datetime,
category varchar(3),
amount money
)
insert into temp values ('1/1/2012', 'ABC', 1000.00)
insert into temp values ('1/1/2012', 'ABC', 2000.00) -- added
insert into temp values ('2/1/2012', 'DEF', 500.00)
insert into temp values ('2/1/2012', 'DEF', 1500.00) -- added
insert into temp values ('2/1/2012', 'GHI', 800.00)
insert into temp values ('2/10/2012', 'DEF', 700.00)
insert into temp values ('2/10/2012', 'DEF', 800.00) -- addded
insert into temp values ('3/1/2012', 'ABC', 1100.00)
Các ví dụ sau đây cho thấy các câu lệnh thực thi khác nhau hiển thị các tập hợp khác nhau như một ví dụ đơn giản. Tôi đã không chọn thay đổi các cột tĩnh, trục và giá trị để giữ cho ví dụ đơn giản. Bạn có thể chỉ cần sao chép và dán mã để bắt đầu tự làm phiền nó
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','sum'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','max'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','avg'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','min'
Việc thực hiện này trả về các tập dữ liệu sau tương ứng.