I've got a few tables in a Postgres 12.3 database.
The first one is named category
:
id|template_id|name |entry_count|is_base_template|can_rename|can_delete|section|userId|parentCategoryId|
--|-----------|---------------|-----------|----------------|----------|----------|-------|------|----------------|
1| |Notes | 0|true |true |true |A | | |
2| |ToDo | 0|true |true |true |A | | |
3| 1|Notes | 0|false |true |true |A | 1| |
4| 2|ToDo | 0|false |true |true |A | 1| |
5| |Must Do | 0|false | | |A | | 4|
6| |Important notes| 0|false | | |A | | 3|
The second table is called entry
- which has no bearing on the question at hand.
And there is the link table category_entries_entry
:
categoryId|entryId|
----------|-------|
4| 1|
5| 5|
5| 6|
4| 7|
3| 8|
6| 9|
A category can possess children, if parentCategoryId
is not NULL then we're dealing with a child. For instance, the category with id = 5
is a subcategory of id = 4
. Children can't have their own children, so only one level of nesting.
I need to count the number of entries for each category including subcategories.
This request does what I need, mostly. But it does not take into account the user:
SELECT COALESCE(c."parentCategoryId" , c.id) as cat_id , COUNT(*) as entries_in_cat
FROM category c JOIN
category_entries_entry r
ON c.id = r."categoryId"
WHERE c.is_base_template = false
GROUP BY cat_id;
Returns:
cat_id|entries_in_cat|
------|--------------|
4| 4|
3| 2|
The category
table has also userId
and the count should only be executed for a given user. Notably, only root categories have entries for userId
.
And I want to list subcategories with their counts additionally. So the desired output with userId = 1
for the given sample is:
cat_id|entries_in_cat|
------|--------------|
5| 2|
4| 4|
6| 1|
3| 2|
Here's a break down:
1) Category number 6 is a subcategory of the 3rd category it has 1 entry, so the result is correct.
2) Category number 3 is a category (that's to say, it does not have a parent), it contains 1 entry and another one should come from the 6th subcategory, that's 2 in total. Your script returns 1 which is wrong.
3) Category number 5 is a subcategory of the 4th category, it contains 2 entries. Your script returns also 2 which is right.
4) category number 4 is a category, it has 2 entries of its own and another two come from the 5th subcategory, that's 4 in total. Your script returns 2 which is wrong. It should return 4.
How can I achieve that?