连接两个MySQL表,然后对其中一个表执行基本过滤

问题描述

我有两个表,它们的外观大致如下:

类别:

+----+-----------+--------+----------------+
| id | entity_id | set_id |      type      |
+----+-----------+--------+----------------+
|  1 |        49 |      1 | signup         |
|  2 |        57 |      1 | signup         |
|  3 |        65 |      1 | signup         |
|  4 |        69 |      1 | recommendation |
|  5 |        73 |      1 | signup         |
|  6 |        77 |      1 | recommendation |
|  7 |        23 |      2 | comment        |
|  8 |        45 |      2 | recommendation |
|  9 |        56 |      2 | signup         |
|  10|        76 |      2 | signup         |
+----+-----------+--------+----------------+

步骤:

+----+--------+----------+--------+
| id | set_id | start_id | end_id |
+----+--------+----------+--------+
|  1 |      1 |       49 |     57 |
|  2 |      1 |       57 |     65 |
|  3 |      1 |       65 |     69 |
|  4 |      1 |       69 |     73 |
|  5 |      1 |       77 |     57 |
|  6 |      2 |       23 |     45 |
|  7 |      2 |       45 |     56 |
|  8 |      2 |       56 |     76 |
+----+--------+----------+--------+

我需要从set_id中选择给定categories的行,但前提是必须在entity_id列的steps中找到start_id的行,但不是end_id列。

因此在此示例中,这些是我希望返回的两条记录:

+----+-----------+--------+----------------+
| id | entity_id | set_id |      type      |
+----+-----------+--------+----------------+
|  1 |        49 |      1 | signup         |
|  6 |        77 |      1 | recommendation |
+----+--------+----------+-----------------+

我知道如何在set_id上执行基本联接,但是我不确定如何从set_id搜索steps的所有记录,并排除那些具有{ entity_id

中出现的{1}}

类似的东西:

end_id

该逻辑应如何正确形成?

解决方法

现有逻辑在这里运作良好,也很简单:

SELECT c.*
FROM categories c
WHERE
    EXISTS (SELECT 1 FROM steps s WHERE s.set_id = c.set_id AND c.entity_id = s.start_id)
    AND
    NOT EXISTS (SELECT 1 FROM steps s WHERE s.set_id = c.set_id AND c.entity_id = s.end_id);

上面的查询用普通英语阅读,它表示要查找所有类别记录,以便在steps中有一个匹配记录,其中entity_idstart_id匹配,但是确实有 not 在steps中还存在一条记录,其中entity_id出现在end_id中。