2010-08-27 81 views
1

我有以下表格佈局。每一行值都將是唯一的。永遠不會有多個同一個Id,Name和Line的實例。TSQL錶轉換字段=>列

Id Name Line 
1 A Z 
2 B Y 
3 C X 
3 C W 
4 D W 

我想查詢數據,以便行字段成爲一列。如果該值存在,則在場數據中應用1,否則爲0。

Id Name Z Y X W 
1 A 1 0 0 0 
2 B 0 1 0 0 
3 C 0 0 1 1 
4 D 0 0 0 1 

字段名W,X,Y,Z都只是字段值的例子,所以我不能申請一個運營商明確檢查,例如,「X」,「Y」,或「Z 」。這些可能隨時發生變化,並不侷限於最終的價值觀。結果集中的列名稱應將唯一字段值反映爲列。

任何想法我可以做到這一點?

+0

'Z Y X W'是固定的嗎? – 2010-08-27 18:01:12

+0

是的,在結果他們將是列的名稱 - 他們可以被稱爲任何東西。 – 2010-08-27 18:02:30

+0

「如果該值存在,則在字段數據中應用1」 - 是否意味着1表示該值的至少一個實例,或者該數字是否應反映與該組關聯的值的計數? – 2010-08-27 18:20:11

回答

6

這是一個標準的主要查詢。

如果1表示一個布爾指示符 - 使用:

SELECT t.id, 
     t.name, 
     MAX(CASE WHEN t.line = 'Z' THEN 1 ELSE 0 END) AS Z, 
     MAX(CASE WHEN t.line = 'Y' THEN 1 ELSE 0 END) AS Y, 
     MAX(CASE WHEN t.line = 'X' THEN 1 ELSE 0 END) AS X, 
     MAX(CASE WHEN t.line = 'W' THEN 1 ELSE 0 END) AS W 
    FROM TABLE t 
GROUP BY t.id, t.name 

如果1表示記錄有用於組,利用該值的數目:

SELECT t.id, 
     t.name, 
     SUM(CASE WHEN t.line = 'Z' THEN 1 ELSE 0 END) AS Z, 
     SUM(CASE WHEN t.line = 'Y' THEN 1 ELSE 0 END) AS Y, 
     SUM(CASE WHEN t.line = 'X' THEN 1 ELSE 0 END) AS X, 
     SUM(CASE WHEN t.line = 'W' THEN 1 ELSE 0 END) AS W 
    FROM TABLE t 
GROUP BY t.id, t.name 
+0

MAX爲什麼需要? – flayto 2010-08-27 18:06:43

+1

@flato:爲了獲得該組中該列的最高值 - 這是允許結果集「變平」的MAX,就像您在預期輸出中看到的一樣。否則,您會看到每個「id」和「name」對的每列比較結果。 – 2010-08-27 18:10:04

+0

+1與我稍有不同的方法讓我暫時感到困惑,因此您可能已經看到了稍縱即逝的評論! – 2010-08-27 18:13:52

2

編輯以下所討論的更新

SQL Server不支持動態透視。

要做到這一點,你可以使用動態SQL來生成一個查詢沿着以下幾行。

SELECT 
     Id ,Name, 
     ISNULL(MAX(CASE WHEN Line='Z' THEN 1 END),0) AS Z, 
     ISNULL(MAX(CASE WHEN Line='Y' THEN 1 END),0) AS Y, 
     ISNULL(MAX(CASE WHEN Line='X' THEN 1 END),0) AS X, 
     ISNULL(MAX(CASE WHEN Line='W' THEN 1 END),0) AS W 
FROM T 
GROUP BY Id ,Name 

或我看了一下,但沒有真正嘗試過的另一種方法是利用通過在SQL Server表指向一個鏈接表建立一個Access數據庫的訪問Transform功能,那麼查詢從SQL Server Access數據庫!

1

假設你有行,你可以枚舉值的數量有限:

declare @MyTable table (
    Id int, 
    Name char(1), 
    Line char(1) 
) 

insert into @MyTable 
    (Id, Name, Line) 
    select 1,'A','Z' 
    union all 
    select 2,'B','Y' 
    union all 
    select 3,'C','X' 
    union all 
    select 3,'C','W' 
    union all 
    select 4,'D','W' 

SELECT Id, Name, Z, Y, X, W 
    FROM (SELECT Id, Name, Line 
      FROM @MyTable) up 
    PIVOT (count(Line) FOR Line IN (Z, Y, X, W)) AS pvt 
    ORDER BY Id 
0

當你正在使用SQL Server,你可能使用PIVOT運營商用於這一目的。

+1

是的。 [SQLMenace](http://stackoverflow.com/questions/3586909/tsql-table-transformation-fields-columns/3587015#3587015)和[I](http://stackoverflow.com/questions/3586909/tsql-table -transformation-fields-columns/3586982#3586982)都使用PIVOT提供了答案。 – 2010-08-27 18:18:57

+0

SQL Server * 2005 + *支持PIVOT; Oracle 11gR2是唯一支持'PIVOT'的其他數據庫 – 2010-08-27 18:22:52

2

這裏是動態版本

測試表

create table #test(id int,name char(1),line char(1)) 

insert #test values(1 , 'A','Z') 
insert #test values(2 , 'B','Y') 
insert #test values(3 , 'C','X') 
insert #test values(4 , 'C','W') 
insert #test values(5 , 'D','W') 
insert #test values(5 , 'D','W') 
insert #test values(5 , 'D','P') 

現在運行這個

declare @names nvarchar(4000) 

SELECT @names ='' 
    SELECT @names = @names + line +', ' 
    FROM (SELECT distinct line from #test) x 

SELECT @names = LEFT(@names,(LEN(@names) -1)) 

exec(' 
SELECT * 
FROM(
SELECT DISTINCT Id, Name,Line 
FROM #test 
    ) AS pivTemp 
PIVOT 
( COUNT(Line) 
    FOR Line IN (' + @names +') 
) AS pivTable ') 

現在添加一行到表及以上再次運行查詢,你會看到B

insert #test values(5 , 'D','B') 

注意:當然,所有使用動態SQL的問題適用,如果你可以使用sp_executesql的,但由於參數不查詢一樣使用真的是沒有一點

0

如果你這樣做了SQL服務器報告服務(SSRS)報告,或者可能會切換到使用報告服務,然後立即停止並將Matrix控件投射到您的報告中。噗!你完成了!作爲一個蛤蜊​​與你的數據pivoted。

0

這是一個頗具特色的方法(使用來自舊羅斯文數據庫的樣本數據)。它是從版本here改編的,由於DBCC RENAMECOLUMN的棄用和PIVOT作爲關鍵字的添加,該版本不再有效。

set nocount on 
create table Sales ( 
    AccountCode char(5), 
    Category varchar(10), 
    Amount decimal(8,2) 
) 
--Populate table with sample data 
insert into Sales 
select customerID, 'Emp'+CAST(EmployeeID as char), sum(Freight) 
from Northwind.dbo.orders 
group by customerID, EmployeeID 
create unique clustered index Sales_AC_C 
on Sales(AccountCode,Category) 
--Create table to hold data column names and positions 
select A.Category, 
     count(distinct B.Category) AS Position 
into #columns 
from Sales A join Sales B 
on A.Category >= B.Category 
group by A.Category 
create unique clustered index #columns_P on #columns(Position) 
create unique index #columns_C on #columns(Category) 
--Generate first column of Pivot table 
select distinct AccountCode into Pivoted from Sales 
--Find number of data columns to be added to Pivoted table 
declare @datacols int 
select @datacols = max(Position) from #columns 
--Add data columns one by one in the correct order 
declare @i int 
set @i = 0 
while @i < @datacols begin 
    set @i = @i + 1 
--Add next data column to Pivoted table 
    select P.*, isnull(( 
    select Amount 
    from Sales S join #columns C 
    on C.Position = @i 
    and C.Category = S.Category 
    where P.AccountCode = S.AccountCode),0) AS X 
    into PivotedAugmented 
    from Pivoted P 
--Name new data column correctly 
    declare @c sysname 
    select @c = Category 
    from #columns 
    where Position = @i 
    exec sp_rename '[dbo].[PivotedAugmented].[X]', @c, 'COLUMN' 
--Replace Pivoted table with new table 
    drop table Pivoted 
    select * into Pivoted from PivotedAugmented 
    drop table PivotedAugmented 
end 
select * from Pivoted 
go 
drop table Pivoted 
drop table #columns 
drop table Sales