2009-06-03 32 views
14

Tôi đang làm việc với một bảng có nhiều hàng mà tôi cần được xoay quanh các cột. Vì vậy, trục là giải pháp hoàn hảo cho điều này và hoạt động tốt khi tất cả những gì tôi cần là một trường. Tôi cần phải trả về một số trường dựa trên trục. Dưới đây là mã giả với các chi tiết cụ thể bị loại bỏ:Nhiều Cột Xoay trong T-SQL

SELECT 
    field1, 
    [1], [2], [3], [4] 
FROM 
    (
    SELECT 
    field1, 
    field2, 
    (ROW_NUMBER() OVER(PARTITION BY field1 ORDER BY field2)) RowID 
    FROM tblname 
) AS SourceTable 
PIVOT 
    (
    MAX(field2) 
    FOR RowID IN ([1], [2], [3], [4]) 
) AS PivotTable; 

Cú pháp trên hoạt động rất tốt, nhưng tôi phải làm gì khi cần thêm thông tin trong trường 3, field4 ....?

+2

Chính xác bạn cần có gì? –

+0

Đã thử, làm việc tốt cho tôi (cách tiếp cận thứ 3 trong blog). http://dba.stackexchange.com/questions/65786/query-pivot-multiple-columns-variable-number-of-rows – JayaPrakash

Trả lời

11

Rewrite sử dụng MAX (CASE ...) và GROUP BY:

select 
    field1 
, [1] = max(case when RowID = 1 then field2 end) 
, [2] = max(case when RowID = 2 then field2 end) 
, [3] = max(case when RowID = 3 then field2 end) 
, [4] = max(case when RowID = 4 then field2 end) 
from (
    select 
    field1 
    , field2 
    , RowID = row_number() over (partition by field1 order by field2) 
    from tblname 
) SourceTable 
group by 
    field1 

Từ đó bạn có thể thêm vào field3, Field4 vv

+0

Điều tôi đã làm là sử dụng các câu lệnh CASe trong một CTE để điền vào bảng dẫn xuất này, mà tôi đã kết hợp với các tiêu chí bổ sung. Đây là CTE: – websch01ar

+0

Với cteSec như ( \t CHỌN \t vSec.ID, \t --Secretary 1 ----------------------- - \t MAX ( \t \t TRƯỜNG HỢP vSec.RowID \t \t KHI 1 THEN vSec.field1 \t \t ELSE '' \t \t END \t) [SEC_OfficePhone1], \t MAX ( \t \t TRƯỜNG HỢP vSec.RowID \t \t WHEN 1 THEN vSec.field2 \t \t ELSE '' \t \t END \t) [SEC_OfficeFax1], \t \t TỪ \t ( \t --THIS sẽ là INNER QUERY (nó gán hàng để thư ký) \t CHỌN TOP 100 PERCENT \t \t field1, field2, ID \t \t (ROW_NUMBER() OVER (PARTITION BY vs.ID ORDER BY vs.ID2)) RowID \t FROM tblname vs \t ORDER BY vs.ID, ID2 \t) vSec \t GROUP BY \t vSec.ID ) – websch01ar

+0

Vì vậy, thông qua phương pháp này, tôi đã hardcoded số cột Tôi đang mong đợi. Tôi thường muốn làm điều này một cách năng động, như là ràng buộc của nó để thay đổi. Nhưng với tư cách là một công ty, chúng tôi đang tập trung vào việc giảm chi phí, vì vậy tôi không thấy cần nhiều hơn bốn thư ký cho mỗi ông chủ ... Tôi cho bạn tín dụng bởi vì bài đăng của bạn đã dẫn tôi xuống đường viết 20 trường hợp các câu lệnh. Điều này hoạt động giống như một sự quyến rũ với một phản ứng phụ thứ hai. – websch01ar

1

Tôi không chắc liệu bạn có đang sử dụng MS SQL Server hay không, nhưng nếu bạn ... Bạn có thể muốn xem xét chức năng CROSS APPLY của động cơ. Về cơ bản nó sẽ cho phép bạn áp dụng các kết quả của một UDF có giá trị bảng cho một tập hợp kết quả. Điều này sẽ yêu cầu bạn đặt truy vấn pivot của bạn vào một tập kết quả có giá trị bảng.

http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/sql-server-cross-apply.aspx

+0

-1 Không thể thấy mối quan hệ với câu hỏi – Andomar

+0

Câu hỏi được gắn thẻ & có tiêu đề là T-SQL . Đó là phương ngữ MS .... – RolandTumble

+0

Nó cũng là phương ngữ Sybase. –

1

quấn tuyên bố sql của bạn với một cái gì đó như:

select a.segment, sum(field2), sum(field3) 
from (original select with case arguments) a 
group by a.segment 

Nó sẽ thu gọn kết quả của bạn thành một hàng, được nhóm lại trên trường1.

1

Bí quyết để làm nhiều trụ trên một row_number là để sửa đổi mà chuỗi số liên tiếp để lưu trữ tất cả các chuỗi và số lĩnh vực. Đây là một ví dụ thực hiện những gì bạn muốn với nhiều câu lệnh PIVOT.

-- populate some test data 
if object_id('tempdb..#tmp') is not null drop table #tmp 
create table #tmp (
    ID int identity(1,1) not null, 
    MainField varchar(100), 
    ThatField int, 
    ThatOtherField datetime 
) 

insert into #tmp (MainField, ThatField, ThatOtherField) 
select 'A', 10, '1/1/2000' union all 
select 'A', 20, '2/1/2000' union all 
select 'A', 30, '3/1/2000' union all 
select 'B', 10, '1/1/2001' union all 
select 'B', 20, '2/1/2001' union all 
select 'B', 30, '3/1/2001' union all 
select 'B', 40, '4/1/2001' union all 
select 'C', 10, '1/1/2002' union all 
select 'D', 10, '1/1/2000' union all 
select 'D', 20, '2/1/2000' --union all 

-- pivot over multiple columns using the 1.1, 1.2, 2.1, 2.2 sequence trick 
select 
    MainField, 
    max([1.1]) as ThatField1, 
    max([1.2]) as ThatOtherField1, 
    max([2.1]) as ThatField2, 
    max([2.2]) as ThatOtherField2, 
    max([3.1]) as ThatField3, 
    max([3.2]) as ThatOtherField3, 
    max([4.1]) as ThatField4, 
    max([4.2]) as ThatOtherField4 
from 
    (
     select x.*, 
      cast(row_number() over (partition by MainField order by ThatField) as varchar(2)) + '.1' as ThatFieldSequence, 
      cast(row_number() over (partition by MainField order by ThatField) as varchar(2)) + '.2' as ThatOtherFieldSequence 
     from #tmp x 
    ) a 
    pivot (
     max(ThatField) for ThatFieldSequence in ([1.1], [2.1], [3.1], [4.1]) 
    ) p1 
    pivot (
     max(ThatOtherField) for ThatOtherFieldSequence in ([1.2], [2.2], [3.2], [4.2]) 
    ) p2 
group by 
    MainField 
Các vấn đề liên quan