如果满足条件,则SQL Server左联接

时间:2019-06-10 07:26:02

标签: sql-server

我的查询有问题。仅在条件为真时,我才需要进行左外部联接。如果条件为假,则执行另一个左外部联接。

我尝试过但没有成功:

select 
    * 
from 
    works with(nolock) 
if work.type = 1 
begin
    left outer join 
        users with(nolock) on users.id = work.owner
else
    left outer join 
        groups with(nolock) on groups.id = work.owner
end

我该如何解决这个问题?

4 个答案:

答案 0 :(得分:3)

您应该尝试将它们都左联接,但是在选择的内容中,根据用例采取您想要的东西。

SELECT
  *, 
  CASE work.type WHEN '1' THEN 'a.owner' ELSE 'b.owner' END AS owner
FROM
  blahblah
  left join users on blahblah.user_id = users.id as a,
  left join groups as blahblah.groups_id = groups.id as b

答案 1 :(得分:0)

您可以尝试以下查询。

第一种方法:

select
    works.*, isnull(users.id, groups.id)
from 
    works with(nolock)
left outer join 
    users with(nolock) on users.id = works.owner and work.type = 1
left outer join 
    groups with(nolock) on groups.id = works.owner

第二种方法:

if exists (select 1 from works with (nolock) where works.type = 1)
    select *
    from works with(nolock)
    left outer join users with(nolock) on users.id = works.owner
else
    select *
    from works with(nolock)
    left outer join groups with(nolock) on groups.id = works.owner

第三种方法:使用动态SQL在运行时建立查询。

答案 2 :(得分:0)

考虑要显示所有列(*),则可以通过检查work.type作为联接条件,有条件地联接两个表:

select 
    * 
from 
    works 
    left join users on 
        users.id = work.owner and 
        work.type = 1
    left join groups on 
        groups.id = work.owner and 
        (work.type <> 1 OR work.type IS NULL)

works表中的特定行只能具有type的特定值,因此它将与usersgroups联接,但不能同时联接。此解决方案的问题是显示的列,因为我们要同时针对两个表进行连接,所以现在您必须统一groupsusers列。

您可以用一堆ISNULL来做到这一点:

select 
    works.*,
    Column1 = ISNULL(users.Column1, groups.Column1), 
    Column2 = ISNULL(users.Column2, groups.Column2)
from 
    works 
    left join users on 
        users.id = work.owner and 
        work.type = 1
    left join groups on 
        groups.id = work.owner and 
        (work.type <> 1 OR work.type IS NULL)

如果需要重复使用同一选择,则可以创建一个表值函数将其包装起来,这样就不必每次都对其进行编码。我将使用表格示例显示另一个替代方法,即使用UNION ALL

CREATE FUNCTION dbo.GetWorkData (@owner INT) -- assuming its a INT
RETURNS TABLE
AS
RETURN

    SELECT
        -- Your wanted columns here
    FROM
        works AS W
        INNER JOIN users AS U ON W.owner = U.owner
    WHERE
        W.owner = @owner AND
        W.type = 1

    UNION ALL

    SELECT
        -- Your wanted columns here (must be same data type and order of previous SELECT)
    FROM
        works AS W
        INNER JOIN groups AS U ON W.owner = U.owner
    WHERE
        W.owner = @owner AND
        (W.type <> 1 OR W.type IS NULL)

您可以将功能与APPLY一起使用:

SELECT
    D.*
FROM
    works AS W
    CROSS APPLY dbo.GetWorkData(W.owner) AS D -- User "OUTER APPLY" if you want works that have no users or groups

答案 3 :(得分:-1)

您可以研究动态SQL。主要思想是在运行时构造和编译SQL语句。

您可以从这里开始: Link 1 - MSSQL tips.

或此处:Link 2 - official microsoft documentation.