根据标志更改INNER JOIN的AND条件?

时间:2014-10-01 18:27:18

标签: sql sql-server-2008 tsql case inner-join

我需要能够根据标志更改内连接的AND条件。我尝试了基于this SO answer的以下内容,当它编译时,当你运行时它永远不会完成。有什么想法吗?

SELECT Stuff, ...
FROM Table t1
    INNER JOIN ...
    INNER JOIN ...
    ...
    INNER JOIN OTHER_TABLE t2 ON 
        CASE
            WHEN @ParticipantsFlag = 'S' AND t1.ID = t2.ID AND t2.STUDENT_ID IS NOT NULL THEN 1
            WHEN @ParticipantsFlag = 'A' AND t1.ID = t2.ID AND t2.ADULT_ID IS NOT NULL THEN 1
            ELSE 0
        END = 1

3 个答案:

答案 0 :(得分:2)

连接中的

or条件可能非常昂贵。我建议你加入桌子两次:<​​/ p>

LEFT JOIN
OTHER_TABLE t2s
ON @ParticipantsFlag = 'S' and
   t1.ID = t2.ID AND
   t2.STUDENT_ID IS NOT NULL LEFT JOIN
OTHER_TABLE t2a
ON  @ParticipantsFlag = 'A' AND
    t1.ID = t2.ID AND
    t2.ADULT_ID IS NOT NULL 

请注意使用left join代替inner join

然后调整selectwhere子句以从两个表中获取所需内容。处理一个或另一个的隐式过滤:

where (t2s.id is not null or t2a.id is not null)

要合并选择中的值,请使用coalesce()

select coalesce(t2s.name, t2a.name) as name

答案 1 :(得分:2)

SELECT Stuff, ...
FROM Table t1
    INNER JOIN ...
    INNER JOIN ...
    ...
    INNER JOIN OTHER_TABLE t2 
       ON t1.ID = t2.ID 
      AND ( ( @ParticipantsFlag = 'S' 
              AND t2.STUDENT_ID IS NOT NULL )
            or
            ( @ParticipantsFlag = 'A' 
              AND t2.ADULT_ID IS NOT NULL )
          )

+1来linoff,但我这可能是更有效的两个连接方法

 LEFT JOIN OTHER_TABLE t2s 
        ON t1.ID = t2s.ID 
       AND @ParticipantsFlag = 'S' 
 LEFT JOIN OTHER_TABLE t2a 
        ON t1.ID = t2a.ID 
       AND @ParticipantsFlag = 'A' 
WHERE t2s.STUDENT_ID IS NOT NULL 
   or t2a.ADULT_ID IS NOT NULL

答案 2 :(得分:0)

虽然您可以执行此操作,但您已为此联接创建了一个不可预测的谓词。

通过这个,我的意思是你的标准无法使用索引查找来评估 - 系统需要为CASE中的每个潜在行评估JOIN语句,这几乎肯定是非常的慢。

可能有帮助的重构可能会有所帮助,因为t1.ID = t2.ID的两个分支的CASE条件相同:

SELECT Stuff, ...
FROM Table t1
    INNER JOIN ...
    INNER JOIN ...
    ...
    INNER JOIN OTHER_TABLE t2 ON 
        t1.ID = t2.ID AND
        CASE
            WHEN @ParticipantsFlag = 'S' AND t2.STUDENT_ID IS NOT NULL THEN 1
            WHEN @ParticipantsFlag = 'A' AND t2.ADULT_ID IS NOT NULL THEN 1
            ELSE 0
        END = 1

请注意,我们已将主要ID关系拉出为&#34;标准&#34;形成。这将允许索引搜索用于此比较,这对您来说应该快得多。