Sql-server – List of IDs that have an assignement to ALL other Ids in another table

sql servert-sql

I need help with the following task (giving up after some hours)

CREATE TABLE #cities (cityId INT, city VARCHAR(100));
INSERT INTO #cities (cityId, city) 
VALUES (1, 'Metropolis A'),
       (2, 'Town B'),
       (3, 'Village C');

CREATE TABLE #assignements (assignmentID INT, cityId INT, desciption VARCHAR(100));
INSERT INTO #assignements (assignmentID, cityId, desciption)
VALUES (1, 1, 'Test Alpha Metropol'),
       (1, 2, 'Test Alpha Town'),
       (1, 3, 'Test Alpha Village'),
       (2, 1, 'Test Beta Metropol');

INSERT INTO #assignements (assignmentID, cityId, desciption)
VALUES (2, 3, 'Test Beta Village');  

I need a query, that returns me all assignmentIDs joined to the #cities (easy :-)), but list only those cities, that are used in ALL assignmentID.

In the example above it should me return after the first INSERT only

assignmentID  city
1             'Metropolis A'
2             'Metropolis A'

since the Town and the village are only used once (but there exists two different assignmentIDs)

After the second INSERT it should return

assignmentID  city
1             'Metropolis A'
2             'Metropolis A'
1             'Village C'
2             'Village C'

because Village C is now assigned to both assignmentIDs too.

When I would

INSERT INTO #assignements (assignmentID, cityId, desciption)
VALUES (3, 2, 'Test Gamma Town');  

the query should return no row, because there is no city, which is assigned to all three assignmentIDs (Alpha, Beta and Gamma).

Of course this example is simplified, in reality there could be any number of cities which are assigned to (currently) up to 11 assignmentIDs

Best Answer

You can try something like:

select a.assignmentID, c.city
from #cities c
join #assignements a on a.cityId = c.cityId
where c.cityId in ( select c.cityId
                    from #cities c
                    left join #assignements a on a.cityId = c.cityId
                    group by c.cityId
                    having count(*) = (select count(distinct assignmentID) 
                                       from #assignements)
                  )