我需要能够根据标志更改内连接的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
答案 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
。
然后调整select
和where
子句以从两个表中获取所需内容。处理一个或另一个的隐式过滤:
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;形成。这将允许索引搜索用于此比较,这对您来说应该快得多。