For example, I have a simple table books
:
author | book |
---|---|
Author-A | Book-A1 |
Author-A | Book-A2 |
Author-B | Book-B1 |
Author-C | Book-C1 |
Author-C | Book-C2 |
And I need to count books by each author, so I’ll write:
select author, count(*) from books
group by author
# Author-A = 2
# Author-B = 1
# Author-C = 2
But now I need to count books by groups of authors:
groupA = ['Author-A', 'Author-C'],
groupB = ['Author-B']
select authorGroup, count(*) from books
group by {
case author in groupA -> 'groupA'
case author in groupB -> 'groupB'
} as authorGroup
# ['Author-A', 'Author-C'] = 4
# ['Author-B'] = 1
These groups can be different and come from another module.
What’s the best way to write this requests? Maybe without union such as:
select author as 'groupA', count(*) from books
where author in { groupA }
union
select author as 'groupB', count(*) from books
where author in { groupB }
because there could be a lot of groups in request (~20-30)
The problem is that these groups can be absolutely dynamic: I can request ['Author-A', 'Author-B']
in one request as one group and ['Author-B', 'Author-C']
in another.
For example, the group is not something like author’s country or genre. It can be totally dynamic.
2
Answers
The usual way is to
JOIN
on to a mapping table, which can be an in-line-view if need be (though I recommend an actual table, which can be indexed).Similar results can be achieved with
CASE
expressions, but it doesn’t scale very well…First you need to create a new table that show in what group is the author.
Later you just count
Like this: