СREATE TABLE tb_users (
id int unsigned not null primary key,
username varchar(20),
id_referer unsigned int
);
CREATE INDEX fk_tree_tree ON tb_users (id_referer);
ALTER TABLE ADD CONSTRAINT al_tree fk_tree_tree
FOREIGN KEY (id_referer) REFERENCES tb_users (id) ON UPDATE CASCADE ON DELETE CASCADE;
with recursive cte (id, id_referer, lvl) as (
select id,
id_referer,
1 lvl
from tb_users
where id_referer = 1
union DISTINCT
select p.id
p.id_referer,
lvl + 1
from tb_users p
inner join cte
on p.id_referer = cte.id
where lvl < 3
)
select * from cte
select * from cte
select COUNT(CASE WHEN `lvl` = 1 THEN 1 END) `lvl_1`, COUNT(CASE WHEN `lvl` = 2 THEN 1 END) `lvl_2`, COUNT(CASE WHEN `lvl` = 3 THEN 1 END) `lvl_3` from cte
with recursive cte (main_id, id, id_referer, lvl) as (
select id,
id
id_referer,
1 lvl
from tb_users
where id_referer is null
union all
select main_id,
p.id
p.id_referer,
lvl + 1
from tb_users p
inner join cte
on p.id_referer = cte.id
where lvl < 3
)
select main_id,
count(case lvl when 1 then 1 end) cnt_lvl1,
count(case lvl when 2 then 1 end) cnt_lvl2,
count(case lvl when 3 then 1 end) cnt_lvl3
from cte
group by main_id
Find more questions by tags MySQL
1. Not clear in your query to count referrals specifically for one user.
2. id_referer is null is not correct, because I want to count even the man who id_referer is not null.
3. cnt_lvl1 displays always 1, cnt_lvl2 count the number of referrals level 1 and level 2 cnt_lvl3. - alene commented on April 19th 20 at 12:29
1. The first query you need to do by id or chemuto more clear ... if You do not think it is the first level, then drop it to zero. But it's a starting point and he is taken to the name and the beginning of a chain. Here's an option with the given name and level 0
2. Read about recursion, id_referer is null this is the starting point, in this example it is id = 1, but this limits the query to a single chain. If we put id_referer is null then query the cte table will display all the chains startmovie id_referer of the fields is null.
3. It is Your right to decide how the numbering of the levels, because You're the architect ;-)
PS if you come, change the start id = 1 for id_referer is null and see what happens - naomie_Metz commented on April 19th 20 at 12:32
c where id = 1 considers correctly for one user, but if I replace id_referer is null, users with id_referer is not null there, but I also want them to be.
I understand that it is necessary to rely in the request, so for example the end node which id_referer is null, but if so it is not null, and the levels of referrals also needs to be calculated.
It's just not logical, from a where id = 1 considers referrals for the user with id = 1 and if id_referer is null bet that this user is not there, because he id_referer is not null.
I have such a request.
Do EXPLAIN format=json
It runs much faster, but he read_cost "query_cost": "111412.05", and your "query_cost": "5.65".
And t5 in the join table, it says "data_read_per_join": "3G" as these figures to understand is not entirely clear.
And on cte table "data_read_per_join": "111K"
I mean I have some not matchmaking, your request is done quickly but a little slower and the query cost is incredible low and my left joins tries is more expensive, but runs a little faster.
And what in this case to use a better option ? - alene commented on April 19th 20 at 12:35
My where condition lvl <= 3, but if only 3 then you have to lvl where < 3
As for speed, it is necessary for the data to look at, my versatile and LVL it in a variable, consider Your private event.
In General, optimization is a separate skyluke and наlо to see and better understand the data =) - naomie_Metz commented on April 19th 20 at 12:38