2012-07-05 49 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

相关问题