2014-12-02 66 views
2

我的輸入是一個具有以下行的視圖:TSQL - 行值列標題包括進一步列的值

DOCID DATE ROWNUMBER COLUMN1  COLUMN2  COLUMN3  COLUMN4  COLUMN5 
ABC00-04-11 1 approval project name ABC  (null)  (null) 

COLUMN2需要的記錄,成爲列標題要麼 COLUMN3或COLUMN4的值。如果COLUMN3爲空或爲空,則使用COLUMN4。 目前COLUMN5是完全空的,因此您可以忽略此列。

的事情是,不是每個的DocID包含COLUMN2,要建立的標題所需要的所有值。

所以我認爲在視圖的所有條目上使用類似「SELECT DISTINCT column2 AS headings」的東西,然後使用透視功能可以讓我在某個地方。 但我無法讓它工作。

我還需要能夠僅選擇關於COLUMN2的特定列標題。一旦我有了一個可以選擇所有列並從中創建新視圖的視圖,這可能會更容易。

看一看這個樣本 Fiddle

我使用MSSQL 2012

我很樂意爲一些示例代碼。

謝謝。

+1

列標題是固定的,不能依賴於數據,除非您使用動態SQL。 – 2014-12-02 14:32:42

+0

你可以在sql小提琴中使用減價輸出來包含你的問題中的所有sql?另外,您是否可以根據該數據集顯示所需的輸出(如果需要,可以修剪)? – Tanner 2014-12-02 14:33:22

回答

2

看來您需要首先取消轉移列Column3,Column4Column5才能返回非空行,然後將Column2項目轉爲列。如果您不知道列名,則需要在存儲過程中使用動態SQL。

在使用動態sql之前,我首先編寫查詢的靜態版本以獲取正確的邏輯。由於使用的是SQL Server 2012中,你可以使用CROSS APPLY和值unpivot的數據:

select 
    m.docId, 
    m.Date, 
    m.column1, 
    m.column2, 
    c.value 
from dbo.mappingTest m 
cross apply 
(
    values 
    ('Column3', Column3), 
    ('Column4', Column4), 
    ('Column5', convert(varchar(10), Column5, 120)) 
) c (Col, Value) 
where c.value is not null 

Demo。您的數據現在看起來是這樣:

|  DOCID |  DATE | COLUMN1 |  COLUMN2 | VALUE | 
|------------|------------|----------|--------------|---------| 
| ABC00| 2014-04-11 | approval | project name |  ABC | 
| ABC00| 2014-04-11 | approval | article name | Art 01 | 
| ABC00| 2014-04-11 | approval |  customer | ACME | 
| ABC00| 2014-04-11 | approval | department | Dept. A | 
| ABC00| 2014-04-11 | approval |  plant | Europe | 
| ABC00| 2014-04-11 | approval | sop month |  10 | 

你必須爲每個DocID與最終你還是會希望在一列的Column2項目下的數值多行。現在您可以應用PIVOT功能:

select 
    DocID, 
    Date, 
    Column1, 
    [project name], [article name], [customer], 
    [department], [plant], [sop month], 
    [sop year], [eop month], [eop year], [budget], [savings] 
from 
(
    select 
    m.docId, 
    m.Date, 
    m.column1, 
    m.column2, 
    c.value 
    from dbo.mappingTest m 
    cross apply 
    (
    values 
     ('Column3', Column3), 
     ('Column4', Column4), 
     ('Column5', convert(varchar(10), Column5, 120)) 
) c (Col, Value) 
    where c.value is not null 
) d 
pivot 
(
    max(value) 
    for column2 in ([project name], [article name], [customer], 
        [department], [plant], [sop month], 
        [sop year], [eop month], [eop year], [budget], [savings]) 
) p 

請參閱SQL Fiddle with Demo。我已經包含了所有列名稱,但在PIVOT IN中,您只包含您想要作爲新列的值。

現在,如果你想使用動態SQL,你會調整代碼爲:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(COLUMN2) 
        from dbo.mappingTest 
        group by COLUMN2 
        order by COLUMN2 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query 
    = 'SELECT 
     DocID, 
     Date, 
     Column1,' + @cols + ' 
     from 
     (
     select 
      m.docId, 
      m.Date, 
      m.column1, 
      m.column2, 
      c.value 
     from dbo.mappingTest m 
     cross apply 
     (
      values 
      (''Column3'', Column3), 
      (''Column4'', Column4), 
      (''Column5'', convert(varchar(10), Column5, 120)) 
     ) c (Col, Value) 
     where c.value is not null 
    ) d 
     pivot 
     (
     min(value) 
     for column2 in (' + @cols + ') 
    ) p ' 

exec sp_executesql @query 

SQL Fiddle with Demo。兩種版本都會給出以下結果:

|  DOCID |  DATE | COLUMN1 | ARTICLE NAME | BUDGET | CUSTOMER | DEPARTMENT | EOP MONTH | EOP YEAR | PLANT | PROJECT NAME | SAVINGS | SOP MONTH | SOP YEAR | 
|------------|------------|----------|--------------|--------|----------|------------|-----------|----------|--------|--------------|---------|-----------|----------| 
| ABC00| 2014-04-11 | approval |  Art 01 | 17890 |  ACME | Dept. A |   0 | 21019 | Europe |   ABC | (null) |  10 |  2014 | 
| ABC00| 2014-04-11 | project |  (null) | (null) | (null) |  (null) | (null) | (null) | (null) |  (null) | -0,020 | (null) | (null) | 
| DEF00| 2014-05-11 | approval |  Art 02 | (null) | (null) |  (null) | (null) | (null) | (null) |   DEF | (null) | (null) | (null) | 
+0

太棒了@bluefeet非常感謝你的代碼和詳細的解釋 - 這工作完美。 – 2014-12-03 09:02:18

0

如果你知道所有的值,你可以這樣做。然後你可以寫一個數據透視查詢。我傾向於使用條件聚合的樞軸:

create view v_table as 
    select docid, date, 
      max(case when column2 = 'project name' then column3 end) as ProjectName, 
      . . . 
    from table t 
    group by docid, date; 

這是你想要的結構(每個文檔和日期一行)的猜測。

您將不得不修改添加新列名稱的視圖。