如何在两个表都有where子句的情况下执行左外连接?

时间:2010-03-31 21:11:13

标签: sql sql-server tsql outer-join

以下是该方案:

我有两张桌子:

CREATE TABLE dbo.API_User
    (
    id int NOT NULL,
    name nvarchar(255) NOT NULL,
    authorization_key varchar(255) NOT NULL,
    is_active bit NOT NULL
    )  ON [PRIMARY]

CREATE TABLE dbo.Single_Sign_On_User
    (
    id int NOT NULL IDENTITY (1, 1),
    API_User_id int NOT NULL,
    external_id varchar(255) NOT NULL,
    user_id int NULL
    )  ON [PRIMARY]

我想要返回的内容如下:

    对于给定的authorization_key ,
  1. is_active
  2. Single_Sign_On_User.id与external_id / API_User_id对匹配(如果存在)或NULL(如果没有这样的对)
  3. 当我尝试此查询时:

    SELECT Single_Sign_On_User.id, API_User.is_active
    FROM API_User LEFT OUTER JOIN
        Single_Sign_On_User ON Single_Sign_On_User.API_User_id = API_User.id
    WHERE     
        Single_Sign_On_User.external_id = 'test_ext_id' AND 
        API_User.authorization_key = 'test'
    

    其中“test”API_User记录存在,但“test_ext_id”记录没有,并且在任何一个表中都没有其他值,我没有返回任何记录。

    当我使用时:

    SELECT Single_Sign_On_User.id, API_User.is_active
    FROM API_User LEFT OUTER JOIN
        Single_Sign_On_User ON Single_Sign_On_User.API_User_id = API_User.id
    WHERE     
        API_User.authorization_key = 'test'
    

    我得到了我期望的结果(NULL,1),但是该查询不允许我找到“test_ext_id”记录(如果它存在)但会给我所有与“test”API_User记录相关联的记录。

    如何获得我追求的结果?

2 个答案:

答案 0 :(得分:3)

在“外部”表上过滤“将联接更改为INNER。

4个选项,其中前2个是最佳

  • 派生表

在派生表内部进行过滤

SELECT SSOU.id, API_User.is_active
FROM
    API_User
    LEFT OUTER JOIN
    (
    SELECT id FROM Single_Sign_On_User WHERE external_id = 'test_ext_id'
    ) SSOU  ON SSOU.API_User_id = API_User.id
WHERE     
    API_User.authorization_key = 'test'
  • SQL Server 2005 +的CTE(代替派生表)

  • 在JOIN中过滤

由此;

SELECT Single_Sign_On_User.id, API_User.is_active
FROM API_User LEFT OUTER JOIN
    Single_Sign_On_User ON Single_Sign_On_User.API_User_id = API_User.id

    AND Single_Sign_On_User.external_id = 'test_ext_id'

WHERE     
    API_User.authorization_key = 'test'
  • OR条款

因此:

SELECT Single_Sign_On_User.id, API_User.is_active
FROM API_User LEFT OUTER JOIN
    Single_Sign_On_User ON Single_Sign_On_User.API_User_id = API_User.id
WHERE     
    (Single_Sign_On_User.external_id = 'test_ext_id' OR Single_Sign_On_User.external_id IS NULL)
    AND
    API_User.authorization_key = 'test'

答案 1 :(得分:0)

我在LEFT JOIN中使用gbn的例子,但这也等同于OR,有时可以更好地生成代码(没有用于跟踪OR的讨厌括号):

SELECT Single_Sign_On_User.id
       ,API_User.is_active
FROM API_User
LEFT OUTER JOIN Single_Sign_On_User
    ON Single_Sign_On_User.API_User_id = API_User.id
WHERE COALESCE(Single_Sign_On_User.external_id, 'test_ext_id') = 'test_ext_id'
    AND API_User.authorization_key = 'test'