Mysql запрос соединения, не исключая строки с одинаковым идентификатором, если одна строка не соответствует условию соединения - PullRequest
0 голосов
/ 24 апреля 2020

Таблица A имеет значения

+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
+----+

Таблица B имеет значения

+----+-----------+----------+
| id | parent_id |  status  |
+----+-----------+----------+
|  1 |         1 |  started |
|  2 |         2 |  stopped |
|  3 |         1 |  stopped |
|  4 |         1 |  stopped |
+----+-----------+----------+

Отношение B равно 1: N

Как я могу получить только эти идентификаторы из таблица A, статус которой не запущен.

SELECT 
   id 
FROM A 
JOIN B ON A.id=B.parent_id and B.status <> 'started';

Когда я запускаю вышеупомянутый запрос, я получаю этот результат

+----+
| id |
+----+
|  1 |
|  2 |
+----+

Вместо отображения только значения 2, оно также отображает 1. Что не так с запросом, который я написал?

Ответы [ 4 ]

1 голос
/ 24 апреля 2020

Дисплей, статус которого не запущен.

SELECT A.id FROM A JOIN B ON A.id=B.parent_id and B.status != 'started'

Выход:

+----+
| id |
+----+
|  2 |
|  1 |
|  1 |
+----+
0 голосов
/ 24 апреля 2020

Часть «не запущена» в таблице фильтров ваших запросов B, вплоть до следующего:

+----+-----------+----------+
| id | parent_id |  status  |
+----+-----------+----------+
|  2 |         2 |  stopped |
|  3 |         1 |  stopped |
|  4 |         1 |  stopped |
+----+-----------+----------+

Затем ваше объединение ищет строки, в которых идентификатор из таблицы А совпадает с родительским идентификатором таблицы B, что и является возвращается правильно (но не считая 1 дважды)

Если вы хотите, чтобы первая половина вернулась:

+----+-----------+----------+
| id | parent_id |  status  |
+----+-----------+----------+
|  2 |         2 |  stopped |
+----+-----------+----------+

 PLUS the rows from table A not referred to in table B....

Тогда ответ GMB выше верен -

select a.id
from a
where not exists (select 1 from b where b.parent_id = a.id and b.status = 'started')

Вот скрипка https://sqltest.net/#1005425

Однако, как и предполагалось, в таблице B вы, скорее всего, столкнетесь с большим количеством ненужного дублирования - многие строки будут начинаться и останавливаться, необязательно в хронологическом порядке (например, - первая запись для A.id = 1 предполагала, что она была начата, 3-я и 4-я записи (предположительно введенные впоследствии) остановили ее, но вы исключили бы эту запись для запуска.

Почему бы не изменить свою таблицу структура для обновления одной строки?

0 голосов
/ 24 апреля 2020

Я бы использовал not exists:

select a.id
from a
where not exists (select 1 from b where b.parent_id = a.id and b.status = 'started')

Это отфильтровывает строки из a, для которых любая дочерняя запись в b имеет начатый статус.

0 голосов
/ 24 апреля 2020

В вашем запросе parent_id 2 возвращается, потому что он также остановлен. Вы можете попытаться использовать подзапрос not in with для указанного

SELECT   id 
FROM A 
JOIN B ON A.id=B.parent_id 
WHERE B.parent_id NOT IN  ( 
    select parent_id
    from B
    B.status = 'started'
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...