Question

Say I have a table:

user_id    parent_id    lev1    lev2   lev3    lev4
1          0            0       0      0       0
2          1            1       0      0       0
3          1            1       0      0       0
4          2            2       1      0       0
5          4            4       2      1       0
6          4            4       2      1       0
7          5            5       4      2       1

Basically, this is to keep track of parent-children hierarchy and I want to get how many children does a parent have. Below is the output I want:

parent_id     children
1             5
2             4
3             0
4             3
5             1
6             0
7             0

I'd like to COUNT the combined lev1, lev2, lev3 and lev4 fields to count how many IDs all in all in those fields.

I read about UNION ALL but I can't seem to figure out how it operates. I'm thinking of a UNION ALL with a self JOIN?

Was it helpful?

Solution

You need a LEFT JOIN against a subquery for each levN column, which returns the distinct level, and count for that column. They all then get added up and joined to user_id.

SELECT
  DISTINCT
  user_id,
  /* COALESCE() is needed so NULLs don't ruin the calculation */
  COALESCE(l1count, 0) +
  COALESCE(l2count, 0) +
  COALESCE(l3count, 0) +
  COALESCE(l4count, 0) AS children
FROM
  yourtable
  /* a left join individually against each of the `levN` columns to get the count per value of each */
  LEFT JOIN (SELECT lev1, COUNT(*) AS l1count FROM yourtable GROUP BY lev1) l1 ON yourtable.user_id = l1.lev1
  LEFT JOIN (SELECT lev2, COUNT(*) AS l2count FROM yourtable GROUP BY lev2) l2 ON yourtable.user_id = l2.lev2
  LEFT JOIN (SELECT lev3, COUNT(*) AS l3count FROM yourtable GROUP BY lev3) l3 ON yourtable.user_id = l3.lev3
  LEFT JOIN (SELECT lev4, COUNT(*) AS l4count FROM yourtable GROUP BY lev4) l4 ON yourtable.user_id = l4.lev4

http://sqlfiddle.com/#!2/214a8/16

OTHER TIPS

I can get you partially there, except that I'm not showing anything with a count of zero. (Also, as @Raphaël Althaus pointed out, parent 1 has count 6 not count 5 in your data).

sqlite> .schema
CREATE TABLE tmp (
user int,
parent int,
l1 int,
l2 int,
l3 int,
l4 int
);
sqlite> select * from tmp;
1,0,0,0,0,0
2,1,1,0,0,0
3,1,1,0,0,0
4,2,2,1,0,0
5,4,4,2,1,0
6,4,4,2,1,0
7,5,5,4,2,1
sqlite> select who,count(who) from
   ...>   (select l1 as who from tmp union all
   ...>    select l2 as who from tmp union all
   ...>    select l3 as who from tmp union all
   ...>    select l4 as who from tmp)
   ...> where who <> 0
   ...> group by who;
1,6
2,4
4,3
5,1
sqlite>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top