请建议如何更改连接条件。需要在JOIN中替换OR条件

时间:2017-03-27 08:21:05

标签: sql sql-server tsql

此OR加入需要时间。我需要避免这种加入请建议。

 Select * from [A] a
 LEFT JOIN [B] b
 ON A.ID = b.ID OR a.ID = b.ID_REF     

2 个答案:

答案 0 :(得分:2)

您的查询可以使用UNION重新编写。你得到第一个条件的结果,然后是第二个条件的结果,然后合并两个。

SELECT * FROM [A] a LEFT JOIN [B] b ON a.ID = b.ID
UNION
SELECT * FROM [A] a LEFT JOIN [B] b ON a.ID = b.ID_REF;

然而,由于消除重复的任务,这可能比原始查询

如果没有重复项(即b.ID永远不等于b.ID_REF),或者您只是不在乎是否得到了重复项,那么您可以使用UNION ALL代替。这只是粘合两个结果而不删除重复项,因此这实际上可能比您的查询更快。您应该在A(ID)B(ID)B(ID_REF)上建立索引。

SELECT * FROM [A] a LEFT JOIN [B] b ON a.ID = b.ID
UNION ALL
SELECT * FROM [A] a LEFT JOIN [B] b ON a.ID = b.ID_REF;

答案 1 :(得分:0)

如果没有关于您的表格,索引等的任何信息,这自然会是一个不完整的答案。在警告过你之后,我会说你可以想象将它分成两个独立的JOIN条件,然后改变你的WHERE条款以反映ID字段的重要性/相关性,像这样:

SELECT *
FROM TableA A
LEFT JOIN TableB B1
    ON A.ID = B1.ID
LEFT JOIN TableB B2
    ON A.ID = B2.ID_REF
WHERE COALESCE(B1.ID,B2.ID_REF) = A.ID
;

当然,这有可能返回重复行的缺点,甚至可能比原始查询工作更慢,这取决于您的索引/键 - 但如上所述,我们将很难给出一个关于您正在使用的架构的信息很少,这是一个很好的答案。

只需使用一些超简单的虚拟数据来向您展示其工作原理:

DECLARE @TABLEA TABLE
    (
        ID INT
    );
DECLARE @TABLEB TABLE
    (
         ID INT
        ,ID_REF INT
    );

INSERT INTO @TABLEA
SELECT 1
    UNION ALL
SELECT 2
    UNION ALL
SELECT 3
    UNION ALL
SELECT 4
    UNION ALL
SELECT 5
    UNION ALL
SELECT 6
;

INSERT INTO @TABLEB (ID, ID_REF)
SELECT 1,NULL
    UNION ALL
SELECT NULL,2
    UNION ALL
SELECT 3,3
    UNION ALL
SELECT 4,NULL
    UNION ALL
SELECT NULL,5
    UNION ALL
SELECT 6,NULL
;

SELECT 
     A.ID AS [A_ID]
    ,COALESCE(B1.ID,B2.ID_Ref) AS [B_Final_ID]
FROM @TABLEA A
LEFT JOIN @TABLEB B1
    ON A.ID = B1.ID
LEFT JOIN @TABLEB B2
    ON A.ID = B2.ID_REF
WHERE COALESCE(B1.ID,B2.ID_REF) = A.ID
;

返回:

A_ID | B_Final_ID
-----+-----------
 1   |  1
 2   |  2
 3   |  3
 4   |  4
 5   |  5
 6   |  6

我会认真地建议您考虑提供一些虚拟数据,除了表格结构之外,这些数据不会对您的实际数据库产生任何影响。在我看来,这是你能够获得更好答案的唯一方式。