性能比较:完全外连接与 Union、Union All
我的表名为:
mktActualsales (SaleID, EmployeeID, PeriodID,PositionID)
mktActualSalesItems(SaleItemID, saleID, Item, Quantity)
mktSalesTargets(TargetID, EmployeeID, PeriodID,PositionID)
mktSalesTargetItems(TargetITemID, TargetID,ItemID, Quantity )
sysPeriods(PeriodID, StartDate, EndDate)
上面的表 sale 和 saleDetails 通过 SaleID 关联,Target 和 TargetDetail 通过 TargetID 关联,关系很明显。我想显示的是所有时期的员工销售额和目标。在某些时期,销售会缺失,而在其他时期,目标可能会缺失。
我的计划(到目前为止)是在一个子查询中采用 sale 和 saleDetail 的内部联接,在另一个子查询中采用 target 和 targetDetail 的内部联接,然后在两个子查询上进行完整的外部联接以获得我需要的数据。但结果却非常慢。我能做些什么来提高性能。我在谷歌上搜索了完整外连接和联合所有之间的性能比较,但没有任何运气。目前我不知道使用 Union/Union All 是否可以实现我想要的结果。
编辑
这是我到目前为止的查询。也编辑了表格
SELECT sale.ActualSaleID,
COALESCE (sale.EmployeeID, saleTarget.EmployeeID) AS EmployeeID,
COALESCE (sale.PositionID, saleTarget.PositionID) AS PositionID,
COALESCE (sale.PeriodID, saleTarget.PeriodID) AS PeriodID,
COALESCE (sale.SKUID, saleTarget.SKUID) AS SKUID,
COALESCE (sale.SalesQuantity, 0) AS SalesQuantity,
saleTarget.SalesTargetID,
COALESCE (saleTarget.TargetQuantity, 0) AS TargetQuantity,
saleTarget.SalesTargetItemID,
sale.ActualSaleItemID,
p.StartDate,
p.EndDate
FROM (
SELECT s.ActualSaleID,
s.EmployeeID,
s.PeriodID,
s.PositionID,
si.ActualSaleItemID,
si.SKUID,
si.SalesQuantity
FROM dbo.mktActualSaleItems AS si
INNER JOIN dbo.mktActualSales AS s
ON si.ActualSaleID = s.ActualSaleID
) AS sale
FULL OUTER JOIN
(
SELECT t.EmployeeID,
t.PeriodID,
t.PositionID,
t.SalesTargetID,
ti.SKUID,
ti.TargetQuantity,
ti.SalesTargetItemID
FROM dbo.mktSalesTargetItems AS ti
INNER JOIN dbo.mktSalesTargets AS t
ON t.SalesTargetID = ti.SalesTargetID
) AS saleTarget
ON sale.PeriodID = saleTarget.PeriodID
AND sale.PositionID = saleTarget.PositionID
AND sale.SKUID = saleTarget.SKUID
INNER JOIN dbo.sysPeriods AS p
ON p.PeriodID = COALESCE (sale.PeriodID, saleTarget.PeriodID)
I have tables named:
mktActualsales (SaleID, EmployeeID, PeriodID,PositionID)
mktActualSalesItems(SaleItemID, saleID, Item, Quantity)
mktSalesTargets(TargetID, EmployeeID, PeriodID,PositionID)
mktSalesTargetItems(TargetITemID, TargetID,ItemID, Quantity )
sysPeriods(PeriodID, StartDate, EndDate)
The relationships are obvious among above tables sale and saleDetails are related through SaleID and Target and TargetDetail are related through TargetID. What I want to display is Employees sales and targets in all periods. There are periods where sale is missing and in other periods targets might be missing.
My plan of doing it (so far) is to take inner join of sale and saleDetail in one subquery, target and targetDetail in another subquery and then full outer join on both subqueries get me the data I need. But the result is awfully slow. what i can do to speed up performance. I have Googled around for performance comparison between full outer join and union all but did not have any luck. At the moment I have no idea if result I want can be achieved using Union/Union All.
Edit
This is the query that I have so far. Edited the tables as well
SELECT sale.ActualSaleID,
COALESCE (sale.EmployeeID, saleTarget.EmployeeID) AS EmployeeID,
COALESCE (sale.PositionID, saleTarget.PositionID) AS PositionID,
COALESCE (sale.PeriodID, saleTarget.PeriodID) AS PeriodID,
COALESCE (sale.SKUID, saleTarget.SKUID) AS SKUID,
COALESCE (sale.SalesQuantity, 0) AS SalesQuantity,
saleTarget.SalesTargetID,
COALESCE (saleTarget.TargetQuantity, 0) AS TargetQuantity,
saleTarget.SalesTargetItemID,
sale.ActualSaleItemID,
p.StartDate,
p.EndDate
FROM (
SELECT s.ActualSaleID,
s.EmployeeID,
s.PeriodID,
s.PositionID,
si.ActualSaleItemID,
si.SKUID,
si.SalesQuantity
FROM dbo.mktActualSaleItems AS si
INNER JOIN dbo.mktActualSales AS s
ON si.ActualSaleID = s.ActualSaleID
) AS sale
FULL OUTER JOIN
(
SELECT t.EmployeeID,
t.PeriodID,
t.PositionID,
t.SalesTargetID,
ti.SKUID,
ti.TargetQuantity,
ti.SalesTargetItemID
FROM dbo.mktSalesTargetItems AS ti
INNER JOIN dbo.mktSalesTargets AS t
ON t.SalesTargetID = ti.SalesTargetID
) AS saleTarget
ON sale.PeriodID = saleTarget.PeriodID
AND sale.PositionID = saleTarget.PositionID
AND sale.SKUID = saleTarget.SKUID
INNER JOIN dbo.sysPeriods AS p
ON p.PeriodID = COALESCE (sale.PeriodID, saleTarget.PeriodID)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您的查询中有一个错误 - SALE 和 SALETARGET 之间的联接不包括 employeeID 列。 COALESCE 隐藏了这一点,但我认为您获得的行数远远超出了您的需要......
但是,加快查询速度的方法是首先找出它们为何缓慢的原因;执行计划是要走的路。使用查询分析器告诉您发生了什么 - 您是否达到了所有连接的索引?仅当您已用尽当前实现上的所有选项时,才重写查询以使用 union 语句。
作为风格问题,我认为没有必要在您加入的列上使用 COALESCE - 它们从一开始就不可能为空,而且它往往会隐藏错误。
I think you have a bug in the query - your join between SALE and SALETARGET doesn't include the employeeID column. The COALESCE hides that, but I think you're getting far more rows than you need...
However, the way to speed up queries is to work out why they're slow in the first place; the execution plan is the way to go. Use Query Analyzer to tell you what's going on - are you hitting indices for all joins? Only rewrite the query to use union statements if you've exhausted all the options on the current implementation.
As a matter of style, I don't think it should be necessary to use COALESCE on columns you join on - they can never be null in the first place, and it tends to hide bugs.
我不认为你需要子查询,你可以在一个查询中做同样的事情
我不确定命名字段,但你明白了。
这可能会加快查询速度。
不要忘记检查索引!
I don't think you need subquery, you can do the same thing in one query
I'm not sure about naming fields, but you get the idea.
This may speed up the query.
Don't forget to check indexes too !!