2014-10-01 146 views
2

我有一個表SQL樞軸

CREATE TABLE [dbo].[newTable](
    [EBELN] [nvarchar](20) NOT NULL, 
    [EBELP] [nvarchar](10) NOT NULL, 
    [VGABE] [nvarchar](2) NOT NULL, 
    [MENGE] [numeric](15, 3) NULL, 
    [DMBTR] [numeric](15, 2) NULL 

) 

它有這些記錄

insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000004', '0001', '1', 1 , 27.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000004', '0001', '2', 1 , 27.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000004', '0002', '1', 1 , 10.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000004', '0002', '2', 1 , 10.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000010', '0001', '1', 1 , 22.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000010', '0001', '2', 1 , 22.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000010', '0002', '1', 1 , 32.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('3000000010', '0002', '2', 1 , 32.95) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('4151516119', '0001', '1', 1 , 400.00) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('4151516119', '0001', '1', 1 , 400.00) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('4151516119', '0001', '2', 1 , 400.00) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('4151516119', '0002', '1', 1 , 200.00) 
Go 
insert into dbo.newTable(EBELN, EBELP, VGABE, MENGE , DMBTR) values('4151516119', '0002', '2', 1 , 200.00) 
Go 

多數民衆贊成在SELECT *

EBELN    EBELP  VGABE MENGE         DMBTR 
-------------------- ---------- ----- -------------- --------------------------------------- 
3000000004   0001  1  1.000         27.95 
3000000004   0001  2  1.000         27.95 
3000000004   0002  1  1.000         10.95 
3000000004   0002  2  1.000         10.95 
3000000010   0001  1  1.000         22.95 
3000000010   0001  2  1.000         22.95 
3000000010   0002  1  1.000         32.95 
3000000010   0002  2  1.000         32.95 
4151516119   0001  1  1.000         400.00 
4151516119   0001  1  1.000         400.00 
4151516119   0001  2  1.000         400.00 
4151516119   0002  1  1.000         200.00 
4151516119   0002  2  1.000         200.00 
3000000004   0001  2  1.000         27.95 
3000000004   0002  1  1.000         10.95 
3000000004   0002  2  1.000         10.95 
3000000010   0001  1  1.000         22.95 
3000000010   0001  2  1.000         22.95 
3000000010   0002  1  1.000         32.95 
3000000010   0002  2  1.000         32.95 
4151516119   0001  1  1.000         400.00 
4151516119   0001  1  1.000         400.00 
4151516119   0001  2  1.000         400.00 
4151516119   0002  1  1.000         200.00 
4151516119   0002  2  1.000         200.00 
4151516177   0002  6  1.000         111.00 
4151516177   0002  8  1.000         111.00 

我需要什麼而想要的是產生這個結果的動態支點

+------------+-------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ 
| EBELN | EBELP | c_DMBTR_1 | c_MENGE_1 | c_DMBTR_2 | c_MENGE_2 | c_DMBTR_6 | c_MENGE_6 | c_DMBTR_8 | c_MENGE_8 | 
+------------+-------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ 
| 3000000004 | 0001 | 27.95  | 1   | 27.95  | 1   | NULL  | NULL  | NULL  | NULL  | 
| 3000000004 | 0002 | 10.95  | 1   | 10.95  | 1   | NULL  | NULL  | NULL  | NULL  | 
| [...]  |  |   |   |   |   |   |   |   |   | 
| 4151516119 | 0001 | 800.00 | 1   | 400.00 | 1   | NULL  | NULL  | NULL  | NULL  | 
| 4151516177 | 0002 | NULL  | NULL  | NULL  | NULL  | 111.00 | 1   | 111.00 | 1   | 
+------------+-------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ 

我嘗試了幾個解決方案,但沒有得到我想要的結果。

我需要的是VGABE的值,它們是(1,2,6,7,8,9,P,R),要連接到字符串名稱c_DMBTRc_MENGE。但是有可能例如P或者7沒有被使用,所以我不希望有這個列。我認爲使其動態是唯一可行的方法。

VGABE的價值應該被添加到列名狀'c_MENGE_'+VGABE並且它必須是爲了,這意味着它開始從VGABE所有欄的最低值,然後下一個值,直到從vgabe每次使用的值。

如果有一個位置(EBELP)從VGABE不止一個值樣兩次1 POS 0001,你可以通過EBELN 4151516119我來總結(DMBTR)這個職位和VGABE價值看。我也和MENGE一樣。

是否可以在一個查詢或存儲過程中執行操作。我不知道如何得到這個結果,我現在被卡住了。還是有另一種我不知道的方式?

+0

即時通訊使用SQL Server 2014和MS SQL管理工作室2014年 – JollyPopper 2014-10-01 12:09:40

回答

2

爲了得到您想要的最終結果,您首先必須unpivotDMBTRMENGE列,然後應用PIVOT函數將行轉換爲列。

你沒有提到你正在使用哪個版本的SQL Server go我會猜測SQL Server 2005+。從SQL Server 2005開始,PIVOT函數已經可用,但對於UNPIVOT,您也可以使用CROSS APPLY--我認爲這會更容易一些。

在深入研究動態SQL版本之前,我總是希望編寫一個靜態版本來獲取正確的邏輯,然後將其轉換爲動態SQL。第一步是將DMBTRMENGE列轉換爲行:

select 
    t.ebeln, 
    t.ebelp, 
    new_col = c.orig_col + '_' + vgabe, 
    c.value 
from dbo.newTable t 
cross apply 
(
    select 'c_MENGE', menge union all 
    select 'c_DMBTR', dmbtr 
) c (orig_col, value); 

SQL Fiddle with Demo。這是你的數據轉換成:

|  EBELN | EBELP | NEW_COL | VALUE | 
|------------|-------|-----------|-------| 
| 3000000004 | 0001 | c_MENGE_1 |  1 | 
| 3000000004 | 0001 | c_DMBTR_1 | 27.95 | 
| 3000000004 | 0001 | c_MENGE_2 |  1 | 
| 3000000004 | 0001 | c_DMBTR_2 | 27.95 | 
| 3000000004 | 0002 | c_MENGE_1 |  1 | 
| 3000000004 | 0002 | c_DMBTR_1 | 10.95 | 

正如你可以看到你現在有多行,用的c_MENGE_1連接值等,這將是你最後列的new_col一起。

一旦你有了這個結果,您可以將旋轉功能:

select ebeln, 
    ebelp, 
    c_DMBTR_1, c_MENGE_1, c_DMBTR_2, c_MENGE_2, 
    c_DMBTR_6, c_MENGE_6, c_DMBTR_8, c_MENGE_8 
from 
(
    select 
    t.ebeln, 
    t.ebelp, 
    new_col = c.orig_col + '_' + vgabe, 
    c.value 
    from dbo.newTable t 
    cross apply 
    (
    select 'c_MENGE', menge union all 
    select 'c_DMBTR', dmbtr 
) c (orig_col, value) 
) d 
pivot 
(
    sum(value) 
    for new_col in (c_DMBTR_1, c_MENGE_1, c_DMBTR_2, c_MENGE_2, 
        c_DMBTR_6, c_MENGE_6, c_DMBTR_8, c_MENGE_8) 
) piv 
order by ebeln, ebelp; 

SQL Fiddle with Demo

現在您已經掌握了正確的邏輯,您需要將其轉換爲動態SQL。這將從創建新列名稱的sql字符串開始。對於這一點,您將使用FOR XML PATH

select @cols = STUFF((SELECT ',' + QUOTENAME(col + '_' + vgabe) 
        from dbo.NewTable t 
        cross apply 
        (
         select 'c_DMBTR', 1 union all 
         select 'c_MENGE', 2 
        ) c (col, so) 
        group by col, so, vgabe 
        order by vgabe, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

這類似於我在靜態版本中使用的代碼。它獲取vgabe值的列表,並將其連接到您想要PIVOT的兩列的名稱(DMBTR,MENGE)。我還爲這些欄目提供了排序順序,因此您可以根據需要訂購它們。完整的動態SQL代碼將爲:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(col + '_' + vgabe) 
        from dbo.NewTable t 
        cross apply 
        (
         select 'c_DMBTR', 1 union all 
         select 'c_MENGE', 2 
        ) c (col, so) 
        group by col, so, vgabe 
        order by vgabe, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query 
    = 'SELECT ebeln, ebelp,' + @cols + N' 
    from 
    (
     select 
     t.ebeln, 
     t.ebelp, 
     new_col = c.orig_col + ''_'' + vgabe, 
     c.value 
     from dbo.newTable t 
     cross apply 
     (
     select ''c_MENGE'', menge union all 
     select ''c_DMBTR'', dmbtr 
    ) c (orig_col, value) 
    ) x 
    pivot 
    (
     sum(value) 
     for new_col in (' + @cols + N') 
    ) p 
    order by ebeln, ebelp' 

exec sp_executesql @query; 

請參閱SQL Fiddle with Demo。這給出了一個結果:

|  EBELN | EBELP | C_DMBTR_1 | C_MENGE_1 | C_DMBTR_2 | C_MENGE_2 | C_DMBTR_6 | C_MENGE_6 | C_DMBTR_8 | C_MENGE_8 | 
|------------|-------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------| 
| 3000000004 | 0001 |  27.95 |   1 |  27.95 |   1 | (null) | (null) | (null) | (null) | 
| 3000000004 | 0002 |  10.95 |   1 |  10.95 |   1 | (null) | (null) | (null) | (null) | 
| 3000000010 | 0001 |  22.95 |   1 |  22.95 |   1 | (null) | (null) | (null) | (null) | 
| 3000000010 | 0002 |  32.95 |   1 |  32.95 |   1 | (null) | (null) | (null) | (null) | 
| 4151516119 | 0001 |  800 |   2 |  400 |   1 | (null) | (null) | (null) | (null) | 
| 4151516119 | 0002 |  200 |   1 |  200 |   1 |  111 |   1 |  111 |   1 | 
+0

嘿!非常感謝您的快速和詳細的回覆!特別是爲了以靜態和動態的方式顯示邏輯!很神奇。我使用SQL Server 2014和Management Studio 2014.我可以問你另一個問題嗎? – JollyPopper 2014-10-01 12:08:39

+0

當然,問題是什麼? – Taryn 2014-10-01 12:24:40

+0

1)我需要在dbo.newTableHeader中插入一個LEFT JOIN作爲我的EBELN,EBELP主表以及dbo.newTable中的PK。 2)是否可以擴展查詢。我想添加一個名爲c_COUNT_X的列,其中X代表每個VGABE值。它計算每個EBELP的VGABE。 也許我可以做一個CTE來爲我的需要準備桌子並將其用於加入 – JollyPopper 2014-10-01 13:06:40