如何根据引用表中是否包含来自不同列的另一个 ID 的至少一个实例来选择该 ID 的所有实例?

jda5

我认为我的问题最好通过下面的示例类似地提出。

假设我有下表,其中包含有关学校班级和学生的信息。

班级号 学生卡
1 3
1 6
1 2
1 6
2 4
2 7
3 6
3 3
3 2
3 5
3 1

我想检索包含 ID 为 3 和 6 的学生的所有学生和班级,即我的结果是:

班级号 学生卡
1 3
1 6
1 2
1 6
3 6
3 3
3 2
3 5
3 1

这可以通过以下查询来实现...

SELECT 
    *
FROM
    table_name
WHERE
    class_id IN (SELECT 
            class_id
        FROM
            table_name
        WHERE
            student_id IN (3 , 6)
        GROUP BY class_id
        HAVING COUNT(DISTINCT student_id) = 2);

我想知道是否可以在不使用子查询的情况下实现上述目标?速度是最重要的,所以我想尽量减少这个选择查询的持续时间。

MatBailie

试图避免子查询可能会导致您走上错误的道路。您确实可以使用子查询编写错误的查询,但您也可以在没有它们的情况下编写错误的查询,以及使用它们编写非常好的查询。

在您的情况下,子查询被用作单独的范围来查找感兴趣的类列表。在获得这些班级学生的相同范围内这样做可能会很混乱且效率低下。

例如,使用的替代方法IN()仍然需要子查询...

SELECT 
  student.*
FROM
  table_name   AS student
INNER JOIN
(
  SELECT 
    class_id
  FROM
    table_name
  WHERE
    student_id IN (3 , 6)
  GROUP BY
    class_id
  HAVING
    COUNT(DISTINCT student_id) = 2
)
  AS class
    ON class.class_id = student.class_id

但是,这可能会产生与您已有的查询相似(甚至相同)的计划。

最接近“没有子查询”的方法是使用嵌套查询,您可以说它仍然是子查询,但优化器更容易扩展。

(使用 MySQL 8+)

SELECT
  *
FROM
(
  SELECT
    *,
    SUM(CASE WHEN student_id IN (3,6) THEN 1 END)
      OVER (PARTITION BY class_id)
        AS target_member_count
  FROM
    table_name
)
  scanned
WHERE
  target_member_count = 2

在大多数班级不包含学生 3 和/或 6 的情况下,我希望这会慢一些。但你可以尝试一下。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章