用LEFT JOIN替换NOT IN

时间:2016-11-22 15:02:09

标签: sql postgresql

我有这样的表结构

[condition]
    condition_id, (pk)
    question_id (fk)

[option]
    condition_id, (fk)
    ext_id (fk)

[external]
    ext_id, (pk)
    inst_id (fk)

[instance]
    inst_id, (pk)
    keeper_id (fk)

[keeper]
    keeper_id, (pk)
    org_id

[question]
    question_id (pk)
    org_id

[localization]
    question_id (fk, pk),
    org_id (pk),
    language (pk)
    label

我需要从question表中获取所有带有本地化(来自localization表)的问题,这些问题在condition表中不存在于某些ext_id

我的查询是

SELECT
    q.question_id as q_id,
    l.label as q_value
FROM question q
    INNER JOIN localization l
        ON l.question_id = q.question_id
    INNER JOIN external ex
        ON ex.ext_id = 'EXTERNAL_ID'
    INNER JOIN instance i
        ON i.inst_id = ex.inst_id
    INNER JOIN keeper k
        ON k.keeper_id = i.keeper_id
WHERE q.org_id IN ('*', k.org_id)
    AND l.org_id = '*'
    AND l.language = 'EN'
    AND q.question_id NOT IN (
        SELECT
            question_id
        FROM condition c
            INNER JOIN option o
                ON o.condition_id = c.condition_id
        WHERE o.ext_id = 'EXTERNAL_ID'
    )

但是如何用LEFT JOIN替换子查询?

1 个答案:

答案 0 :(得分:1)

这是一种方式

SELECT p.question_id AS q_id,
       l.label       AS q_value
FROM   question q
       INNER JOIN localization l
               ON l.question_id = q.question_id
       INNER JOIN EXTERNAL ex
               ON ex.ext_id = 'EXTERNAL_ID'
       INNER JOIN instance i
               ON i.inst_id = ex.inst_id
       INNER JOIN keeper k
               ON k.keeper_id = i.keeper_id
       LEFT JOIN (select distinct c.question_id 
             from  condition c
              JOIN option o
              ON o.condition_id = c.condition_id
                 AND o.ext_id = 'EXTERNAL_ID' ) c 
              ON c.question_id = q.question_id
WHERE  q.org_id IN ( '*', k.org_id )
       AND l.org_id = '*'
       AND l.language = 'EN'
       AND c.question_id IS NULL 

我不是Postgres的专家,但我更喜欢NOT EXISTS来做这个

SELECT p.question_id AS q_id,
       l.label       AS q_value
FROM   question q
       INNER JOIN localization l
               ON l.question_id = q.question_id
       INNER JOIN EXTERNAL ex
               ON ex.ext_id = 'EXTERNAL_ID'
       INNER JOIN instance i
               ON i.inst_id = ex.inst_id
       INNER JOIN keeper k
               ON k.keeper_id = i.keeper_id
WHERE  q.org_id IN ( '*', k.org_id )
       AND l.org_id = '*'
       AND l.language = 'EN'
       AND NOT EXISTS (SELECT 1
                       FROM   condition c
                              INNER JOIN option o
                                      ON o.condition_id = c.condition_id
                       WHERE  o.ext_id = 'EXTERNAL_ID'
                              AND q.question_id = c.question_id)