简体   繁体   中英

SQL Server query to find records between pivoted tables where there is no association

I am trying to write a query that returns a list of records from two tables where either the tables have no record tied to each or a flag is found saying not to tie a record.

Eg:

Houses

╔════╦══════════════╦
║ 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     ║
╚════╩══════════════╩═════════════╩════════════════╝

I am trying to write a SQL query to find 'Empty' Houses. Eg houses that have no occupants or occupants who left. The end result would be:

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

Notice how House 1 is not on this list because even though the occupant left he came back in.

The query I have so far (which is very off) looks like:

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)

How can I fix the following query to return the proper dataset?

Your query has several issues:

  • the subquery in not exists is not correlated with the outer query

  • even if it was, it would return houses whose occupant left, but not houses that never had an occupant: those are eliminated by the INNER JOIN . Note that the ORD ed condition is a no-op since, again, the INNER JOIN eliminates houses that never had an occupant

I would just use not exists to filter on houses for which no record exists in houseOccupant with a leftOn that is null :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM