【问题标题】:Joining using an OR operator使用 OR 运算符加入
【发布时间】:2020-03-10 17:42:02
【问题描述】:

我有两张桌子。一个 Employee 键表和一个包含其工作位置的表。

EMPID   EMPNAME
1234    James
9876    Kevin
4567    Elaine

EMPID   EMPID_OLD   LOCATION
1234                TORONTO
987610  9876        NEW YORK
4567    104567      CHICAGO

问题在于第二个表中的员工键不一致,并且分散在 EMPID 和 EMPID_OLD 列之间。

我编写了一个查询,其中涉及 LEFT JOIN 表达式中的“或”运算符。:

select empid, location
from emp m1 
left join emp_location m2
    on m2.empid = m1.empid OR m2.empid_old = m1.empid

此查询理论上有效,但运行大约需要 45 分钟。如果我删除“OR”表达式,运行只需 5 秒。

不能使用COALESCE 表达式,因为它匹配的第一个值可能不准确,因此它连接了它可以找到匹配的任何一个值,不一定是第一个。

有什么方法可以优化这个查询,而不必像下面那样分离连接?

这是我正在处理的大型查询的过度简化版本,因此显然试图避免同一个表的多个连接。

select m1.empid, coalesce(m2.location,m3.location)
from emp m1 
left join emp_location m2
    on m2.empid = m1.empid 
left join emp_location m3
    on m3.empid_old = m1.empid 

【问题讨论】:

  • 你的上一个版本是提高性能的方法。
  • " 如果我​​去掉“OR”表达式,运行只需要 5 秒。"对于 empid 和 empid_old?
  • emp_location 是否同时在 empidempid_old 上编入索引?重复的结果是可能的还是可取的? select e.empid, el.location from emp as e inner join emp_location as el on el.empid = e.empid union all select e.empid, el.location from emp as e inner join emp_location as el on el.empid_old = e.empid; 可能会产生重复。将其更改为 union 会以牺牲排序为代价删除重复项。
  • 是否有任何答案为您解决了问题?

标签: sql sql-server tsql join


【解决方案1】:

两个左连接是这里的方法。如果 COALESCE 不能为您解决问题,那么您可以使用 case when 条件来确定要使用的位置:

select m1.empid, 
       case when m2.location = 'Condition for location accuracy' then m2.location
            else m3.location end as location
from emp m1 
left join emp_location m2 on m2.empid= m1.empid 
left join emp_location m3 on m3.empid_old= m1.empid 

【讨论】:

    【解决方案2】:

    连接以及太左连接或右连接或笛卡尔连接的成本都很高。

    在第二个表中的列( EMPID, EMPID_OLD) 上有一个索引,因为在您的连接条件中通过OR 对两列进行了调节。这在一定程度上会有所帮助

    【讨论】:

      【解决方案3】:

      union all 通常在 SQL Server 可以独立优化每个连接的情况下表现更好,例如

      select m1.empid, m2.[location]
      from emp m1 
      left join emp_location m2 on m2.empid = m1.empid 
      
      union all
      
      select m1.empid, m3.[location]
      from emp m1 
      left join emp_location m3  on m3.empid_old = m1.empid 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-08
        • 2019-07-04
        • 1970-01-01
        • 2014-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-04
        相关资源
        最近更新 更多