Reputation: 25
I have boxes, and items that can be contained in the boxes. Both boxes and items have a status. Boxes statuses are for example packed, unpacked, sent, received etc - an integer. Items statuses are scanned, not scanned and unknown (null) - a Boolean.
Or as tables:
So, a box can have many items, but an item can only be contained in one box.
As a start, I want to be able to find all boxes with status = 0 that contains either no items at all or only items with status false and/or null. In the end, I want to change the status of all the matching boxes to 1.
Sample data and expected data:
boxes [pk] int id, int status, character(20) test_text
0;0;"(no items)"
1;0;"(items with false)"
2;0;"(items with null)"
3;0;"(items with null and false)"
4;0;"(items with true)"
5;0;"(items with true and false)"
6;0;"(items with true and null)"
7;0;"(items with true and false and null)"
8;1;"(no items)"
9;1;"(items with false)"
10;1;"(items with null)"
11;1;"(items with true)"
items [pk] int id, int box_id, boolean status
0;1;false
1;2;null
2;3;false
3;3;null
4;4;true
5;5;true
6;5;false
7;6;true
8;6;null
9;7;true
10;7;false
11;7;null
12;9;false
13;10;null
14;11;true
expected - boxes [pk] int id, int status, character(20) test_text
0;0;"(no items)"
1;0;"(items with false)"
2;0;"(items with null)"
3;0;"(items with null and false)"
I can't quite figure out how to write the proper code to do this. I'm using postgresql.
Any help is appreciated!
Upvotes: 0
Views: 169
Reputation: 95072
all boxes with status = 0
where boxes.status = 0
either no items at all or only items with status false and/or null.
i.e. boxes that don't contain any item with status true
where boxes.id not in (select box_id from items where status = true)
The complete query:
select *
from boxes
where status = 0
and id not in (select box_id from items where status = true);
(The NOT IN
clause can be replaced by a NOT EXISTS
clause, if you prefer this. I prefer NOT IN
for its simplicity.)
Upvotes: 1
Reputation: 1623
Something like this:
select bb.id
from boxes bb
left join items ii on ii.box_id = bb.id
where bb.status = 0
group by bb.id
having sum(case when ii.status = true then 1 else 0 end) = 0
Upvotes: 2