SQL Запрос к серверу для поиска записей между сводными таблицами, где нет связи - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь написать запрос, который возвращает список записей из двух таблиц, в которых либо в таблицах нет записей, привязанных к каждой, либо найден флаг, говорящий не о ie записи.

Например:

Дома

╔════╦══════════════╦
║ Id ║  Name        ║
╠════╬══════════════╬
║  1 ║ 10 Maple     ║
║  2 ║ 20 Oak       ║
║  3 ║ 30 Drive     ║
╚════╩══════════════╩

HousesOccupants

╔════╦══════════════╦═════════════╦════════════════╗
║ Id ║  HouseId     ║ OccupentId  ║ LeftOn         ║
╠════╬══════════════╬═════════════╬════════════════╣
║  1 ║ 1            ║  1          ║ NULL           ║
║  2 ║ 1            ║  1          ║ 2019-01-01     ║
║  3 ║ 3            ║  2          ║ 2019-01-01     ║
╚════╩══════════════╩═════════════╩════════════════╝

Я пытаюсь написать SQL запрос, чтобы найти 'Пустые' дома , Например, дома, в которых нет жильцов или жильцов, которые уехали. Конечный результат будет следующим:

╔════╦══════════════╦
║ Id ║  Name        ║
╠════╬══════════════╬
║  2 ║ 20 Oak       ║
║  3 ║ 30 Drive     ║
╚════╩══════════════╩

Обратите внимание, что Дом 1 отсутствует в этом списке, потому что, несмотря на то, что оставивший его посетитель вернулся, он вернулся.

Запрос, который у меня есть ( очень выключен) выглядит так:

SELECT *
FROM Houses H
INNER JOIN HousesOccupants HO ON HO.HouseId = H.Id
WHERE NOT EXISTS (
        SELECT *
        FROM HousesOccupants
        WHERE HousesOccupants.LeftOn IS NULL
            AND HO.HouseId = H.Id
        )
    OR (HO.Id IS NULL)

Как исправить следующий запрос, чтобы получить правильный набор данных?

1 Ответ

2 голосов
/ 29 января 2020

Ваш запрос имеет несколько проблем:

  • подзапрос в not exists не коррелирует с внешним запросом

  • , даже если он был , он вернул бы дома, чьи жильцы уехали, но не дома, в которых никогда не было жильцов: они были уничтожены INNER JOIN. Обратите внимание, что условие ORD ed не разрешено, поскольку, опять же, INNER JOIN исключает дома, в которых никогда не было жильца

Я бы просто использовал not exists для фильтрации дома, для которых в houseOccupant нет записей с leftOn, то есть null:

select h.*
from houses h
where not exists (
    select 1
    from houseOccupants ho
    where ho.houseId = h.id and ho.leftOn is null
)
...