【问题标题】:SQL find record that matches in any of three tablesSQL 查找三个表中任意一个匹配的记录
【发布时间】:2012-12-05 05:25:11
【问题描述】:

我有以下架构:

user -- user_id | first_name
full_time_job -- ft_job_id | user_id
part_time_job -- pt_job_id | user_id
internship -- internship_id | user_id

我想编写一个查询,返回存在于三个作业表中的任何一个中的所有用户。最好的方法是什么?如果可能的话,我更喜欢在 WHERE EXISTS 上使用 LEFT JOINS,但会对最佳工作解决方案感到满意。

我不想返回存在于三个作业表中的任何一个中的任何用户。

【问题讨论】:

    标签: sql sql-server-2008 join left-join


    【解决方案1】:

    使用LEFT JOINs,您只需在至少一个表中验证user_idNOT NULL

    SELECT
      [user].user_id
    FROM
      [user]
      /* LEFT JOIN against each of the 3 tables */
      LEFT JOIN full_time_job ft ON [user].user_id = ft.user_id
      LEFT JOIN part_time_job pt ON [user].user_id = pt.user_id
      LEFT JOIN internship intern ON [user].user_id = intern.user_id
    WHERE
      /* And check that *any* of them has a non-null user_id */
      ft.user_id IS NOT NULL
      OR pt.user_id IS NOT NULL
      OR intern.user_id IS NOT NULL
    

    如果可能,最好修复架构...

    不过,从长远来看,如果可能的话,这些都应该合并到一个单个表中,其中有一列指示作业类型,而不是 3 个类似的表。

    示例: http://sqlfiddle.com/#!2/2cd2c/1

    在上面的示例中,用户 5,6 不存在于 3 个表中。

    【讨论】:

    • 我确实喜欢这个答案,但它返回的结果太多了。一些用户可能在一个或多个工作表中有匹配项。但无论如何,这运行缓慢并返回超过一百万个结果。它应该更接近 750。我确实添加了 distinct,这使数字下降到 4000 左右。
    • @AdamLevitt 你的实现是什么?如果连接 ON 条件正确,您应该不会获得比预期更多的行。如果您缺少任何 ON 子句,您将获得笛卡尔积,这导致您需要 DISTINCT
    • 我实际上剪切并粘贴了您的确切代码,我只是将表名换成了我实际架构中的表名。
    • @AdamLevitt user.user_id 是唯一的/PK?仔细检查表名,尤其是在 ON 子句中,因为如果用户是唯一的,这将无法返回更多或重复的用户。
    • 是的,这绝对是用户表的唯一PK。奇怪,我知道……但绝对是独一无二的。同样为了完整性,也许您应该将 [user] 作为用户表,以避免人们的任何反对意见。我已经看到它发生了。
    【解决方案2】:

    你可以这样做:

    SELECT DISTINCT *
    FROM "user" 
    WHERE user_id
    IN
    (
        SELECT user_id
        FROM
        (
           SELECT user_id FROM full_time_job
           UNION ALL
           SELECT user_id FROM part_time_job
           UNION ALL
           SELECT user_id FROM internship 
       ) t 
       WHERE user_id IS NOT NULL
    )
    

    或者:使用 CTE,你可以这样写:

    ;WITH AllUsers
    AS
    (
        SELECT user_id FROM full_time_job
        UNION ALL
        SELECT user_id FROM part_time_job
        UNION ALL
        SELECT user_id FROM internship 
    )
    SELECT *
    FROM "user"
    WHERE user_id IN ( SELECT user_id 
                       FROM AllUsers 
                       WHERE user_id IS NOT NULL);
    

    SQL Fiddle Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 2018-07-19
      相关资源
      最近更新 更多