基于变量的Sql Server中的条件连接

时间:2014-12-01 14:13:55

标签: sql sql-server sql-server-2008

当且仅当某些条件为真时,我才想接受连接。 实施例 -

Table Employee
emp_no
emp_name
dept_no

Table Departnemt
dept_no
dept_name

declare @takeJoin BIT

select * from Employee e
if @takeJoin then
inner join Department d on e.dept_no=d.dept_no

如果@takeJoin为1,则只应进行内部联接,否则应按原样返回Employee中的所有记录。

我们可以写一般if if语句吗? 这只是一个示例,实际查询非常普遍

If @takeJoin =1
begin
end
else
begin

end

将不是一个合适的解决方案。

这样的事情可能吗?

3 个答案:

答案 0 :(得分:4)

使用Left Join始终获取Employee记录并在WHERE子句中过滤掉它们。当@TakeJoin = 0时,我们在SELECT中使用DISTINCT来防止Employee和Department之间潜在的一对多关系(即使这可能是一对零/一)。只想展示一对多更复杂场景的技术。

SELECT DISTINCT e.emp_no,
   e.emp_name,
   e.dept_no,
   CASE WHEN @TakeJoin = 1 THEN d.dept_no ELSE NULL END AS dept_dept_no
   CASE WHEN @TakeJoin = 1 THEN d.dept_name ELSE NULL END AS dept_name
FROM Employee e
   LEFT OUTER JOIN Department d ON e.dept_no = d.dept_no
--If @TakeJoin = 1/True, then make sure d.dept_no is not null to filter out Employee
--who have no department.
WHERE
--Mimic INNER JOIN on @TakeJoin = 1
((@TakeJoin = 1 AND d.dept_no IS NOT NULL) OR
--"Ignore" the Join and take all records
@TakeJoin = 0)

答案 1 :(得分:1)

最简单的方法是使用if

if @TakeJOin = 'Yes'
    select *
    from Employee e inner join
         Department d
         on e.dept_no = d.dept_no;
else
    select *
    from Employee e;
end;

使用SQL中的条件逻辑,这应该有效:

你可以这样做:

select e.*
from Employee e left join
     Department d
     on e.dept_no = d.dept_no and @TakeJoin = 'Yes'
where (@TakeJoin = 'Yes' and d.dept_no is not null) or
      (@TakeJoin <> 'Yes')

请注意,您无法更改要返回的列数。如果你这样做:

select *
from Employee e left join
     Department d
     on e.dept_no = d.dept_no and @TakeJoin = 'Yes'
where (@TakeJoin = 'Yes' and d.dept_no is not null) or
      (@TakeJoin <> 'Yes')

然后,您将获得Department的所有列,但当NULL为false时,它们将具有@TakeJoin个值(无论您如何表示)。

答案 2 :(得分:1)

是的, 可以,但是您应该使用选项重新编译:

DECLARE @doJoin BIT = 0

SELECT *
FROM A
LEFT JOIN B on A.x = B.y and @doJoin = 1
 option (recompile)

不重新编译选项,SQL Server将创建(并缓存)一个更通用的执行计划,该计划始终包括左联接,即使在您的特定情况下不需要它。使用此选项,您将在执行计划中看到对表A的聚集索引扫描,而没有对“ B”的任何访问。