2009-11-03 129 views
1

我有以下數據的SQL視圖:SQL數據透視表

ID ClassName Description Flags 
1 Class1   Desc1  F1 
2 Class1   Desc1  F2 
3 Class1   Desc1  F3 
4 Class1   Desc1  F4 
5 Class2   Desc2  F2 
6 Class2   Desc2  F6 
7 Class3   Desc3  F1 
8 Class4   Desc4  F8 

我想結果是這樣的:

ClassName Description F1 F2 F3 F4 F6 F8 
Class1   Desc1   T T T T F F 
Class2   Desc2   F T F F T F 
Class3   Desc3   T F F F F F 
Class4   Desc4   F F F F F T 

我試圖來查找樞紐的例子,但所有的人都用於SUM或其他聚合函數。不知道是否會有任何工作,因爲我沒有做。

+0

什麼版本的SQL Server,你試過了什麼? – 2009-11-03 19:32:03

回答

0

當flags ='F1'然後'T'else'F'結束F1時,case flags when'F2'then'T'else'F'end F2,...

0

我相信MS SQL Server支持樞軸表,但我不確定如何去做。當我必須在MySQL中傳輸數據時,我使用Sum和Case。但是,只有當你知道你的列名將會提前時纔有效。以下是我可以做到這一點:

Select 
X.ClassName, 
X.Description, 
Case When X.F1 = 1 Then 'T' Else 'F' End As `F1`, 
Case When X.F2 = 1 Then 'T' Else 'F' End As `F2` 
/* etc. for the rest of your Flags*/ 
FROM (
    Select 
    ClassName, 
    Description, 
    Sum(Case When Flags = 'F1' Then 1 Else 0 End) As `F1`, 
    Sum(Case When Flags = 'F2' Then 1 Else 0 End) As `F2` 
    /* etc. for the rest of your Flags*/ 
    From 
    ClassTable 
    Group By 
    ClassTable.ClassName 
    ) X 

在上面的代碼中,子查詢會產生輸出像你想要的東西,但你會得到1和0(假設你永不重複標誌的一類)。聲明頂部的「主要」查詢只是將1和0轉換爲T和F。

同樣,這需要你知道你的列名是什麼,但這是我知道如何在沒有將「PIVOT」內置到你正在使用的SQL語言中的唯一途徑。 MS SQL可能有一個內置的PIVOT,所以你可能想挖掘一下。

+0

我不知道我的標誌是什麼,因爲最終用戶有能力添加,更新或刪除標誌並與他們想要的任何類進行關聯(例如,用戶可以添加新標誌,如F101或將現有標誌F1重命名爲F01)。我使用的是SQL Express 2005 – Deepak 2009-11-03 19:59:47

+0

下面是一個令人討厭的黑客:如果您有能力在運行時生成SQL,則可以在表中查詢所有可用的標誌名稱,然後使用列生成SQL語句(Sum(Case When Flags ...)會自動從代碼中生成,這讓我覺得自己很骯髒,但是如果你有代碼可以工作,它就會工作。 – 2009-11-03 20:06:46

1

Henry Fao走在正確的軌道上 - 但是你必須用一組來平整行。

 
select ClassName as ClassName, Description as Description 
    , coalesce(max(F1), 'F') as F1 
    , coalesce(max(F2), 'F') as F2 
    , etc 
from (
     select classname, description 
      , case when flags = 'F1' then 'T' else null end as F1 
      , case when flags = 'F2' then 'T' else null end as F2 
      etc. 
     from tbl 
     ) as t 
    group by ClassName, Description 

在每個組的F1列中應該只有一個'T'。其他行將在T1列中爲空。 max()函數忽略空值並返回'T' - 如果有的話。

0

這不是很漂亮,我通常不喜歡動態創建的SQL,但有一個未知的標誌列表,我不確定你會怎麼做。此外,你是正確的,因爲PIVOT命令期望一個聚合,所以我只用MAX。是的,這是一種黑客行爲,但它確實完成了工作,並且會隨着新標誌的添加而擴展。我認爲這應該適用於2005/2008版SQL-SERVER。我不知道2003年,因爲我不知道它是否有XML PATH命令。

Declare @ColumnsIn varchar(max) 
Declare @ColumnsIsNull varchar(max) 
Declare @sql varchar(max) 

Select @ColumnsIn = Stuff((Select Distinct ',[' + Flags + ']' From Classes For XML PATH('')),1,1,'') 
Select @ColumnsIsNull = Stuff((Select Distinct ', IsNull([' + Flags + '], ''F'') as [' + Flags + ']' From Classes For XML PATH('')),1,1,'') 

Set @sql = ' 
    Select 
     ClassName, 
     Description, 
     ' + @ColumnsIsNull + ' 
    FROM 
    (
     Select 
      Classes.ClassName, 
      Classes.Description, 
      Classes.Flags, 
      ''T'' as HasFlag 
     From 
      Classes 
    ) as Sub1 
    Pivot (Max(HasFlag) For Flags in (' + @ColumnsIn + ')) as Sub2' 

Execute(@sql)