2012-12-18 65 views
0

我正在寻找方法来优化以下SQL查询。我正在使用MS SQL Server 2008.我想如果有任何方法来整合外部连接,它会加快速度......如果任何人有任何输入,它将不胜感激。谢谢查询中使用多个外连接的查询优化

SELECT employee.employee_id, 
    coalesce (room.ship_id, ship.ship_id) AS ship_id, 
    SUBSTRING (employee.service_id, 0, 6) AS cost_code, 
    employee_station.room_cat AS nws_room_cat 
FROM employee 
    LEFT OUTER JOIN room 
     ON  employee.ship_id = room.ship_id 
     AND employee.floor_id = room.floor_id 
     AND employee.room_id = room.room_id 
    LEFT OUTER JOIN ship 
     ON employee.ship_id = ship.ship_id 
    LEFT OUTER JOIN employee_station 
     ON COALESCE (ship.property_type, '') = 
      COALESCE (employee_station.property_type, '') 
     AND COALESCE (room.work_center_id, '') = COALESCE (employee_station.work_center_id, '') 
     AND COALESCE (employee.pay_plan, '') = 
       COALESCE (employee_station.pay_plan, '') 
     AND COALESCE (employee.employee_type, '') = 
       COALESCE (employee_station.employee_type, '') 
     AND COALESCE (SUBSTRING (employee.service_id, 0, 6), '') = 
       COALESCE (employee_station.cost_code, '') 
    LEFT OUTER JOIN roomtype 
     ON room.room_type = roomtype.room_type 
    LEFT OUTER JOIN dp 
     ON employee.service_id = dp.service_id 

注意:为了清晰起见,我特意在这里省略了SELECT语句中的很多字段。因此,roomtype和dp表格实际上正在使用...

+1

为什么LEFT JOIN的对表'roomtype'和'dp'?他们在这里没有做任何事情。 – BellevueBob

+0

@BobDuell:很好,我正想问同样的问题。 – Kaf

+0

哦,实际上有更多的字段是SELECT的一部分..不过我为了清晰的目的而将它们排除在外......只是使它更简洁。所以这些表格实际上是需要的,因为数据正在被他们从中拉出......我只是没有在这里包括实际的字段。 – dido

回答

1

OUTER JOINs不是问题。问题在于包装函数内的列。

ON COALESCE (ship.property_type, '') = COALESCE (employee_station.property_type, '') 

这类建筑的阻止优化们进行有效的查询计划 - 它不知道该函数的值是什么,直到运行时间,因此它无法使用,他们应该存在索引。

重写没有函数的查询,优化器将能够做出更好的决策。

+0

你如何建议我重写没有COALESCE函数的查询?我想我会得到非常不同的结果,如果我删除这些功能... – dido

+0

问题是,你为什么认为他们是必要的?我自己并不使用sql-server,但是您要加入的表格实际上是否有值表示为''的行? – BellevueBob

+1

@dido'ON ship.property_type = employee_station.property_type OR(ship.property_type IS NULL AND employee_station.property_type IS NULL)'或'ON EXISTS(SELECT employee_station.property_type INTERSECT SELECT ship.property_type)'see [Untocumented Query Plans:Equality比较](http://sqlblog.com/blogs/paul_white/archive/2011/06/22/undocumented-query-plans-equality-comparisons.aspx) –

0

你可以尝试加入的校验 - 从我的经验,往往给人较复杂条件更好的性能:

SELECT 
--columns you need 
FROM employee 
LEFT OUTER JOIN room 
ON CHECKSUM(employee.ship_id, employee.floor_id, employee.room_id) 
= CHECKSUM(room.ship_id, room.floor_id, room.room_id) 
LEFT OUTER JOIN ship 
ON employee.ship_id = ship.ship_id 
LEFT OUTER JOIN employee_station 
ON CHECKSUM(ship.property_type, room.work_center_id, employee.pay_plan, employee.employee_type, SUBSTRING (employee.service_id, 0, 6)) 
= CHECKSUM(employee_station.property_type, employee_station.work_center_id, employee_station.pay_plan, employee_station.employee_type, employee_station.cost_code) 
LEFT OUTER JOIN roomtype 
ON room.room_type = roomtype.room_type 
LEFT OUTER JOIN dp 
ON employee.service_id = dp.service_id 
+0

的查询成本(相对于批处理)时,查询似乎运行速度较慢......最后但并非最不重要:为什么room或employee_station表没有employee_id参考? - 它会让你的查询变得更简单更快 – pkmiec

+0

除了这个已被弃用的事实之外,它也无法工作。[“SET ANSI_NULLS ON只有在比较操作数的其中一个是NULL变量或NULL时才会影响比较结果。如果比较的两边都是列或复合表达式,则该设置不会影响比较。” ](http://msdn.microsoft.com/en-us/library/ms188048.aspx) –

+0

哦..好点,我会编辑 – pkmiec