2012-07-05 12 views
0

簡而言之, 我有這些表。最好的SQL代碼來得到這個輸出

Planning: 
    Date | Machine | Product | PlanningParts 

OKParts: 
    Date | Machine | Product | OKParts 

Scrap: 
    Date | Machine | Product | ScrapParts 

Trials: 
    Date | Machine | Product | TrialParts 

Breakdowns: 
    Date | Machine | Product | Minutes 

這些表可以有兩個或更多記錄爲相同的[日期|機器|產品],它們不是唯一的專欄。 獲取此輸出的最佳SQL代碼(SQLite或SQL Server)是什麼?

Output: 
    Date | Machine | Product | Planning | OKParts | ScrapParts | TrialParts | Minutes 

編輯: 在輸出中,我需要每[日期,機器,產品]一行和列的其餘部分必須是SUM (我不會說英語,對不起)

Eidted: 例子: (我不會把表「審判」,使之短)

Planning: 
    Date | Machine | Product | PlanningParts 
    1/6/12 | Blower | A001 | 100 
    2/6/12 | Blower | A002 | 100 
    2/6/12 | Assembly| B001 | 50 

OKParts: 
    Date | Machine | Product | OKParts 
    1/6/12 | Blower | A001  | 50 
    1/6/12 | Blower | A001  | 20 
    1/6/12 | Blower | A002  | 100 

Scrap: 
    Date | Machine | Product | ScrapParts | Reason 
    1/6/12 | Blower | A001  | 5   | Low Weight 
    1/6/12 | Blower | A001  | 3   | High Weight 
    2/6/12 | Assembly| B001  | 4   | Bad Cut 

Breakdowns 
    Date | Machine | Product | Minutes | Reason 
    1/6/12 | Blower | A001  | 100  | Manteinance 
    1/6/12 | Blower | A001  | 20   | Manteinance 
    2/6/12 | Assembly| B001  | 100  | Quality approval 


    OUTPUT: 
     Date | Machine | Product | Planning | OKParts | ScrapParts | Breakdowns 
     1/6/12 | Blower | A001  | 100  | 70  | 8   | 120 
     1/6/12 | Blower | A002  | 100  | 100  | 0   | 0 
     2/6/12 | Assembly| B001  | 50  | 0  | 4   | 100 
+0

請顯示樣本數據(包括幾行,其中有多個值有助於單個SUM)和期望的結果。這樣,我們就不必再詢問關於結果的15個後續問題,或者猜測您需要的查詢。如果您顯示樣本數據和期望的結果,我們可以在*顯示給您之前測試並驗證解決方案*,並且由於您的要求不明確而拒絕他們。 – 2012-07-05 22:38:01

+0

如果在一張表中有記錄,相同的{日期,機器,產品} *總是*在所有其他表中至少有*一條記錄?或者他們有時可能有0條記錄用於{Date,Machine,Product}?並且/或者是否有一個表格*總是*具有*至少*該日期,機器,產品的一個記錄? – MatBailie 2012-07-05 22:39:18

+0

請閱讀:http://dba.blogoverflow.com/2012/06/help-us-help-you/ – 2012-07-05 23:03:21

回答

3

創建CTE unioning所有表成一個,然後用SUM aggrigate功能,添加了專欄ch日期,機器,產品組。像這樣的位(未測試):

WITH AllParts AS (
SELECT Date, Machine, Product, PlanningParts, NULL AS OKParts, NULL AS ScrapParts, NULL AS TrialParts, NULL AS Breakdowns 
FROM Planning 
UNION ALL 
SELECT Date, Machine, Product,NULL AS PlanningParts, OKParts, NULL AS ScrapParts, NULL AS TrialParts, NULL AS Breakdowns 
FROM OKParts 
UNION ALL 
SELECT Date, Machine, Product,NULL AS PlanningParts, NULL AS OKParts, ScrapParts, NULL AS TrialParts, NULL AS Breakdowns 
FROM Scrap 
UNION ALL 
SELECT Date, Machine, Product,NULL AS PlanningParts, NULL AS OKParts, NULL AS ScrapParts, TrialParts, NULL AS Breakdowns 
FROM Trials 
UNION ALL 
SELECT Date, Machine, Product,NULL AS PlanningParts, NULL AS OKParts, NULL AS ScrapParts, TrialParts, Breakdowns 
FROM BreakDowns 
) 
SELECT 
Date, Machine, Product, SUM(OKParts) AS OKParts, SUM(ScrapParts) AS ScrapParts, SUM(TrialParts) AS TrialParts, SUM(BreakDowns) AS Breakdowns 
FROM AllParts 
GROUP BY Date, Machine, Product 
+0

不是最簡單的閱讀,但肯定有效。並沒有重複導致JOIN版本的問題。 – MatBailie 2012-07-05 22:41:14

+0

這就是我已經,但我看到的代碼,它看起來很骯髒。必須有一個更有效的方式 – leinho 2012-07-05 22:43:28

+0

顯然,所有工會都不需要別名(只有最上面的那個),但是我這樣寫就是爲了更清楚地說明發生了什麼。刪除不必要的別名會使它更容易閱讀!這是我能想到的最有效的方式,因爲'UNION ALL'只需要很少的工作。 – jaypeagi 2012-07-05 22:43:56

1

我很想看看如果工會後相加作爲該查詢,總結第一次執行,以及:

WITH Vals AS (
    SELECT Date, Machine, Product, 'PlanningParts' Which, Sum(PlanningParts) Value FROM Planning GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'OKParts', Sum(OKParts) FROM OKParts GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'ScrapParts', Sum(ScrapParts) FROM Scrap GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'TrialParts', Sum(TrialParts) FROM Trials GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'Minutes', Sum(Minutes) FROM Breakdowns GROUP BY Date, Machine, Product 
) 
SELECT * 
FROM Vals 
PIVOT (Max(Value) FOR Which IN (PlanningParts, OKParts, ScrapParts, TrialParts, Minutes)) P; 

啊,這是痛苦的,但這就是你從給定的數據庫設計中得到的結果。將這5個表重構爲一張表,用視圖取代這些表具有替代觸發器可能是可行的。

注意:PIVOT適用於SQL Server 2005及更高版本。但是,你甚至都不需要PIVOT:

WITH Vals AS (
    SELECT Date, Machine, Product, 'PlanningParts' Which, Sum(PlanningParts) Value FROM Planning GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'OKParts', Sum(OKParts) FROM OKParts GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'ScrapParts', Sum(ScrapParts) FROM Scrap GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'TrialParts', Sum(TrialParts) FROM Trials GROUP BY Date, Machine, Product 
    UNION ALL SELECT Date, Machine, Product, 'Minutes', Sum(Minutes) FROM Breakdowns GROUP BY Date, Machine, Product 
) 
SELECT 
    Date, Machine, Product, 
    Sum(CASE Which WHEN 'PlanningParts' THEN Value END) PlanningParts, 
    Sum(CASE Which WHEN 'OKParts' THEN Value END) OKParts, 
    Sum(CASE Which WHEN 'ScrapParts' THEN Value END) ScrapParts, 
    Sum(CASE Which WHEN 'TrialParts' THEN Value END) TrialParts, 
    Sum(CASE Which WHEN 'Minutes' THEN Value END) Minutes 
FROM Vals; 

交換文本Which值整數可能會產生速度的提高。

關於我對有關表中具有日期,機器,產品值的清單的表的評論/問題,此查詢將提供這樣的清單。這樣做不會很好,但它應該給你這個想法。

WITH DistinctKeys AS (--wishing we had this as a real table 
    SELECT Date, Machine, Product FROM Planning 
    UNION SELECT Date, Machine, Product FROM OKParts 
    UNION SELECT Date, Machine, Product FROM Scrap 
    UNION SELECT Date, Machine, Product FROM Trials 
    UNION SELECT Date, Machine, Product FROM Breakdown 
) -- because then we could do this: 
SELECT 
    K.Date, K.Machine, K.Part, 
    (SELECT Sum(PlanningParts) FROM Planning X ON EXISTS (SELECT K.* INTERSECT SELECT X.Date, X.Machine, X.Product) PlanningParts 
    (SELECT Sum(OKParts) FROM OKParts X ON EXISTS (SELECT K.* INTERSECT SELECT X.Date, X.Machine, X.Product) OKParts 
    (SELECT Sum(ScrapParts) FROM Scrap X ON EXISTS (SELECT K.* INTERSECT SELECT X.Date, X.Machine, X.Product) Scrap 
    (SELECT Sum(TrialParts) FROM Trials X ON EXISTS (SELECT K.* INTERSECT SELECT X.Date, X.Machine, X.Product) TrialParts 
    (SELECT Sum(Minutes) FROM Breakdown X ON EXISTS (SELECT K.* INTERSECT SELECT X.Date, X.Machine, X.Product) Minutes 
FROM 
    DistinctKeys K; 

但坦率地說,這些連接都不會表現不如以前,我和@ jaypeagi的回答給工會。

還有一件事:不要假設性能將會是一個查詢。即使是專家也會檢查執行計劃並收集真實的IO和CPU統計數據以確定此信息。您擔心NULL會降低性能可能完全沒有根據。

如果你在[日期,機器,產品]上的表上有好的索引,那麼你可能會在UNION方法中獲得相當好的性能。

+0

更好!不知道關鍵字「PIVOT」。但我仍然喜歡看髒。你有任何想法如何使模型更好?我評論說,其中有幾個表格有更多的列。示例:廢料和故障表中有一列更多,「原因」,因此您可以擁有: 廢料: 1/6/12 |鼓風機|坦克| 5 |在重量下 1/6/12 |鼓風機|坦克| 3 |重量高 – leinho 2012-07-05 23:18:49

+0

如果您使用超類型/子類型模式,即表格具有不同的列,即使它們基本上表示相同類型的東西,那麼也許您的數據庫結構可以。如果列數不是真的*,那麼將所有內容放在同一個表中可能仍然是最好的,只是在不適用於項目類型時將列留空。 – ErikE 2012-07-05 23:20:34

+0

@leinho您是否擁有一張表格,其中包含可在這5個表格中找到的日期,機器和產品值的明確列表? – ErikE 2012-07-05 23:21:42

相關問題