如何在mssql中执行条件连接?

时间:2014-01-23 20:40:33

标签: sql-server

我希望根据数据将表连接到两个可能的表中的一个。这是一个不起作用的尝试,但我希望能够实现这个想法。此外,这是一个可能不太现实的模拟示例,因此不要过于依赖这个代表真实学生和课程的想法。

SELECT *
FROM
student
INNER JOIN class ON class.student_id = student.student_id
CASE
    WHEN class.complete=0
    THEN RIGHT OUTER JOIN report ON report.label_id = inprogress.class_id
    WHEN class.complete=1
    THEN RIGHT OUTER JOIN report ON report.label_id = completed.class_id
END

有什么想法吗?

3 个答案:

答案 0 :(得分:9)

你有两个连接条件,如果其中一个是真的你想提交一个连接 - 这是一个布尔OR操作。

您只需要:

RIGHT OUTER JOIN report ON (CONDITION1) OR (CONDITION2)

让我们解开那一刻,条件1是什么,条件2是什么?

WHEN class.complete=0
THEN RIGHT OUTER JOIN report ON report.label_id = inprogress.class_id
WHEN class.complete=1
THEN RIGHT OUTER JOIN report ON report.label_id = completed.class_id

在这里,您在每个条件1和2上汇总了两个条件,因此您的条件1是:

class.complete = 0 AND report.label_id = inprogress.class_id

你的条件2是

class.complete = 1 AND report.label_id = completed.class_id

所以完成的SQL应该是这样的(并且这是我未经测试的)

RIGHT OUTER JOIN report ON (
  class.complete = 0 AND report.label_id = inprogress.class_id
) OR (
  class.complete = 1 AND report.label_id = completed.class_id
)

值得一提..

我没有运行上面的连接,但我从经验中知道,执行计划绝对是恶名,如果性能不重要或者数据集很小则无关紧要但是,如果性能很重要,我强烈建议您在这里发布更广泛的内容,我们可以讨论一种更好的方法来获取不会如此糟糕的特定数据集。我个人只会作为最后的手段写一个像上面这样的联接,或者如果我正在攻击真正无关紧要的东西。

答案 1 :(得分:0)

试试这个(未经测试) -

SELECT *
FROM student S
    INNER JOIN class c ON c.student_id = S.student_id
    left outer join report ir on ir.label_id = inprogress.class_id AND c.complete=0
    left outer join report cr on cr.label_id = completed.class_id AND c.complete=1

答案 2 :(得分:0)

如果要以合理的性能加入2个表中的任何一个,请为每个路径写一个存储过程(一个将表1连接到表A,一个将表1连接到表B)。创建调用1-A存储过程或1-B存储过程的第三个存储过程。这样就可以在每种情况下执行有效的查询计划,而无需在每次调用时重新编译或生成奇怪的查询计划。

在您的情况下,您实际上需要来自您可能加入的表的两个的一些记录。在这种情况下,您希望将结果合并在一起而不是选择其中一个(如果您愿意,可以将它们组合在一个sproc中,它不应该损害查询计划)。如果您确定两个查询之间的记录不会重复(看起来他们不会),那么像往常一样使用UNION ALL来提高性能。