Yesterday, I was working on SQL query which at first look should be very simple and easy to come with. But I was not able to write the solution withouth the help of my more experienced colleague.

I have 2 entity tables (I omit all fields as they are irrevelant to the problem):
bills

bill_id
1
2
3
4
5
6

meters

meter_id
1
2
3

and a mapping table bills_meters

bill_id meter_id
1 1
2 2
2 3
3 1
4 1
4 2
4 3
5 3
6 1
6 3

As you can see from above a bill can have 1…n meters, and I need to write a query to find all bills which are linked to the given meters, e.g.

find all bills for meters with ids 2,3

which should return only bill with id 2 (and not bill 4 as it also linked to meter with id 3 or bill 6 which have meter 3 but not 2).

My current SQL query is a combination of 2 SELECT statement with grouping. It starts with filtering out bills without the required number of meters:

SELECT 
   bm.bill_id 
FROM 
   bills_meters AS bm 
GROUP BY 
   bm.bill_id 
HAVING 
   COUNT (bm.bill_id) = 2;

then filter result for only bills with required meters

SELECT 
   bm1.bill_id 
FROM 
   bills_meters
AS 
   bm1 
WHERE 
   bm1.meter_id IN (2, 3) 
AND bm1.bill_id IN 
   (SELECT 
      bm.bill_id 
   FROM 
      bills_meters AS bm 
   GROUP BY 
      bm.bill_id 
   HAVING 
      COUNT (bm.bill_id) = 2)
GROUP BY bm1.bill_id 

this will return bills 2 and 6 as both have linked 2 meters and at least one meter from the given collection (IN (2, 3)).

And finally, get only bills which have only both meters

SELECT 
   bm1.bill_id 
FROM 
   bills_meters
AS 
   bm1 
WHERE 
   bm1.meter_id IN (2, 3) 
AND bm1.bill_id IN 
   (SELECT 
      bm.bill_id 
   FROM 
      bills_meters AS bm 
   GROUP BY 
      bm.bill_id 
   HAVING 
      COUNT (bm.bill_id) = 2)
GROUP BY bm1.bill_id 
HAVING COUNT(bm1.bill_id) = 2;

The query works, I’ve tested it against a larger set of entries, but somehow I think that there might be a better solution to this problem.