I have 2 tables: items and items_purchased. The tag name and other descriptive information is in the items table and the # of purchases for each item is saved in the items_purchased table. The tables are JOINed on item_id.
Here’s my query so far:
(select *, sum(purchaseyesno) as tots from items join items_purchased on items.item_id=items_purchased.item_id where tag = 'History' and deleted!=1 and pub_priv!=1 order by tots desc limit 1)
UNION ALL
(select *, sum(purchaseyesno) as tots from items join items_purchased on items.item_id=items_purchased.item_id where tag = 'Medicine' and deleted!=1 and pub_priv!=1 order by tots desc limit 1)
UNION ALL
(select *, sum(purchaseyesno) as tots from items join items_purchased on items.item_id=items_purchased.item_id where tag = 'Biology' and deleted!=1 and pub_priv!=1 order by tots desc limit 1)
//... more tags (20 in all) would follow
The problem is that items with certain tags haven’t been purchased yet so the query throws an error of Column "item_id" cannot be null.
here’s the sample tables:
items | items_purchased |
item_id tag title | item_id purchaseyesno|
1 Biology DNA is cool | 1 1 |
2 Medicine Doctors | 2 1 |
3 Law Laws are cool| 4 1 |
4 Biology DNA NOT cool | 1 1 |
Sample results:
item_id tag title tots
1 Biology DNA is cool 2
2 Medicine Doctors 1
3 Law Laws are cool 0
2 questions:
- How can I exclude one of these
SELECTstatements if the results of it will beNULL? - Is there a better way to do this query rather than 20 select statements joined by 19
UNION ALLs?
You simply want to group your results—nothing more complicated than that (no
UNIONin sight!):UPDATE
Following the comments beneath and the update to the OP’s question, it’s clear that the problem is more complicated than first thought: it is, in fact, a special case of the group-wise maximum problem.
However, the column over which the maximum must be taken is itself the result of another group-wise aggregation (the summation of
purchaseyesno).Therefore, one’s query becomes rather inelegant with subqueries:
See it on sqlfiddle.
What’s happening here is that (using an outer join to include records such as
Lawthat have no references in theitems_purchasedtable), we take the sum of purchases for each item (materialised tableu) and then determine the maximum number of purchases for items with the same tag name.We then join the result (materialised table
v) back with the first table (u, materialised again as tablet) on both tag name and number of purchases.Finally we group the results again by
tagto ensure that, if multiple items having the same tag have the same number of maximal purchases, only one of them is returned indeterminately.