2015-11-18 78 views
2

我有一個存儲過程,它連接多個表以生成一個大的結果集,然後將其返回到我的應用程序。應用程序依次循環遍歷結果,並結合特定ID上的行,並選擇每行數據以包含在新對象中。這也許是最簡單的使用一個例子來解釋:許多SQL行合併爲一個

Inspection, Desc,   Value 
1,   Description1, 3  
1,   Description2, 2 
1,   Description3, 5 

這在代碼變成

Inspection, Description1, Description2, Description3 
1,   3,   2,   5 

這樣做的關鍵是具有每檢查項目一行與項目描述爲報頭和值作爲檢查行和標題的單元格值。然後將其導出到Excel。

現在的問題是:如何在SQL Server中執行此操作,例如擴展我的SP以返回更少但「更寬」的行,列數更多?

另一個複雜因素是一個檢測可能有另一個缺少的行,在這種情況下,解決方案是添加一個空值或' - '。

P.S.這是使用Sql Server 2012.

+1

使用'pivot',它會完成這項工作 – Shaharyar

回答

0

如果您希望動態做到這一點,而不必知道所有的在Desc值,你可以建立自己的支點查詢,並使用Exec()Execute sp_executesql

DECLARE @Columns NVARCHAR(MAX), 
     @Sql NVARCHAR(MAX) 

--Build your column headers based on Distinct Desc values 
SELECT @Columns = COALESCE(@Columns + ',', '') + QUOTENAME([Desc]) 
FROM (SELECT DISTINCT [Desc] FROM tbl) t 
ORDER BY [Desc] 

--Build your pivot query 
SET @Sql = ' 
    SELECT 
     * 
    FROM 
     tbl 
    PIVOT 
    (
     MAX([Value]) 
     FOR [Desc] IN (' + @Columns + ') 
    ) p 
' 
EXEC(@Sql) 

如果你想-爲空值,你需要創建另一個變量來保存轉換腳本s爲您的sql的Select部分。

DECLARE @Columns NVARCHAR(MAX), 
     @Sql NVARCHAR(MAX), 
     @ColumnAliases NVARCHAR(MAX) 

--Build your pivot columns based on Distinct Desc values 
SELECT @Columns = COALESCE(@Columns + ',', '') + QUOTENAME([Desc]) 
FROM (SELECT DISTINCT [Desc] FROM tbl) t 
ORDER BY [Desc] 

--Build your column headers, replacing NULL with - 
SELECT @ColumnAliases = COALESCE(@ColumnAliases + ',', '') 
      + 'COALESCE(CONVERT(VARCHAR,' + QUOTENAME([Desc]) + '),''-'') AS ' + QUOTENAME([Desc]) 
FROM (SELECT DISTINCT [Desc] FROM tbl) t 
ORDER BY [Desc] 


--Build your pivot query 
SET @Sql = ' 
    SELECT 
     Inspection,' 
     + @ColumnAliases + ' 
    FROM 
     tbl 
    PIVOT 
    (
     MAX([Value]) 
     FOR [Desc] IN (' + @Columns + ') 
    ) p 
' 
EXEC(@Sql) 
+0

謝謝。這個提供了最能夠解決我的問題的提示,並將其標記爲接受的答案。 –

1

您應該使用Sql Server Pivot。它將行轉換爲列。你可以從this example開始。

+1

這就像一個答案一樣草率。你應該提供一個完整的答案,而不僅僅是「放棄」一個功能/關鍵字/機制並完成它。 – Amit

+0

@Amit我肯定會做,如果有任何代碼或我可以解釋的東西。這是最好的,我可以回答這個**得到一個建議**類型的問題。 – Shaharyar

+1

我想你可以提供一個最簡單的例子來說明如何在問題中提供樣本數據,或者我會對問題本身發表評論,解釋爲什麼這樣的問題不適合SO(因爲它們會導致像你一樣的答案) ),甚至可能會投票結束。但這只是我的意見...... :-)(PS請參閱@ Arion的答案) – Amit

2

如果您使用的是mssql 2005+。您可以使用一個支點是這樣的:

測試數據

DECLARE @tbl TABLE(Inspection INT, [Desc] VARCHAR(100),Value INT) 
INSERT INTO @tbl 
VALUES 
(1,'Description1', 3),  
(1,'Description2', 2), 
(1,'Description3', 5) 

查詢

SELECT 
    * 
FROM 
(
SELECT 
    tbl.Inspection, 
    tbl.[Desc], 
    tbl.Value 
FROM 
    @tbl AS tbl 
) AS tbl 
PIVOT 
(
    SUM(Value) 
    FOR [Desc] IN ([Description1],[Description2],[Description3]) 
)AS pvt 

結果:

Inspection, Description1, Description2, Description3 
1   3    2    5 

編輯

由於juharr在評論說:

得到的列名(值的表格)是建立查詢時。這可能需要另一個初始查詢。如果你不使用MSSQL得到

編輯2

2005+。或者想要有和交替的解釋。請看下面的查詢:

SELECT 
    tbl.Inspection, 
    SUM(CASE WHEN [Desc]='Description1' THEN tbl.Value ELSE 0 END) AS Description1, 
    SUM(CASE WHEN [Desc]='Description2' THEN tbl.Value ELSE 0 END) AS Description2, 
    SUM(CASE WHEN [Desc]='Description3' THEN tbl.Value ELSE 0 END) AS Description3 
FROM 
    @tbl AS tbl 
GROUP BY 
    tbl.Inspection 

這不requiere樞軸,並且可以在大多數關係數據庫管理系統的使用在那裏

+0

應該注意,這需要OP知道構建查詢時生成的列名(表中的值)是什麼。這可能需要另一個初始查詢才能獲得。 – juharr

+0

@juharr:更新了答案 – Arion