'SQL NOT EXISTS vs count distinct

I have three tables; Apartment (apartmentnr, floor, apartmenttype), Floor (floornr, house), House (housenr, adress)

Now, I want to show housenr and adresses of houses that have apartments of all apartmenttypes (1-4), using NOT EXISTS.

sql


Solution 1:[1]

As @onedaywhen hints, not exists is pretty ponderous for this task, and count distinct offers leaner syntax (performance issues are mentioned in the article he points to):

SELECT House.adress
FROM House
JOIN Floor ON (House.housenr=Floor.house)
JOIN Apartment ON (Floor.floornr=Apartment.floor)
GROUP BY House.housenr
HAVING COUNT(DISTINCT Apartment.apartmenttype)=4

which essentially says "show adress [[sic]] of houses with 4 different types of apartments". Only good reason to force the use of not exists would be, as others hinted, homework...

Solution 2:[2]

Ah then you want to use Chris Dates approach, rather than the one made popular Joe Celko? If you are not sure, both approaches are discussed here:

Relational Division by Joe Celko

Solution 3:[3]

If I understand your relationships properly you could something like this. Remember you could use alias's for the tables to make it slightly easier to read, I've just kept them in to make it clear what I'm doing.

Select  House.hoursenr, address
inner join Floor on House.housenr = Floor.house
inner join Apartment on Apartment.floor = Floor.floornr
where Apartment.apartmenttype in (1,2,3,4)

I would argue that some of your entity relationships are the wrong way round in your table definitions.

Solution 4:[4]

Given a structure like this:

Houses

ID Address

Floors

ID HouseID

Apartments

Id FloorId ApartmentType

I think this will do the trick:

SELECT H.ID FROM Houses H JOIN Floors F ON H.Id = F.HouseId JOIN Apartments A on F.Id = A.FloorId AND A.ApartmentType = 1 AND H.Id IN 
(SELECT H.ID FROM Houses H JOIN Floors F ON H.Id = F.HouseId JOIN Apartments A on F.Id = A.FloorId AND A.ApartmentType = 2) AND H.Id IN 
(SELECT H.ID FROM Houses H JOIN Floors F ON H.Id = F.HouseId JOIN Apartments A on F.Id = A.FloorId AND A.ApartmentType = 3) AND H.Id IN 
(SELECT H.ID FROM Houses H JOIN Floors F ON H.Id = F.HouseId JOIN Apartments A on F.Id = A.FloorId AND A.ApartmentType = 4)

In English, it means, give me the set of all houses with an apartment of type 1 that are also in the set of houses with an apartment of type 2...and so on.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alex Martelli
Solution 2 onedaywhen
Solution 3 MrEdmundo
Solution 4 Chris B. Behrens