Storing Hierarchical Data (MySQL) for Referral Marketing

后端 未结 4 826
长发绾君心
长发绾君心 2021-01-12 23:20

I need to have a 5 levels hierarchy for the users registered to a website. Every user is invited by another, and I need to know all descendants for a user. And also ancestor

4条回答
  •  生来不讨喜
    2021-01-12 23:43

    Delimited String of Ancestors

    If you're strongly considering the 5-level relationship table, it may simplify things to use a delimited string of ancestors instead of 5 separate columns.

    user_id  depth   ancestors
    10       7       9,7,4,3,2,1
    9        6       7,4,3,2,1
    ...
    2        2       1
    1        1       (empty string)
    

    Here are some SQL commands you'd use with this model:

    To add user 11, referred by user 10

    insert into ancestors_table (user_id, depth, ancestors)
    select 11, depth+1, concat(10,',',ancestors)
    from ancestors_table
    where user_id=10;
    

    To find all users referred by user 3. (Note that this query can't use an index.)

    select user_id
    from ancestors_table
    where ancestors like '%,3,%' or ancestors like '3,%' or ancestors like '%,3';
    

    To find the ancestors of user 10. You need to break up the string in your client program. In Ruby, the code would be ancestorscolumn.split(",").map{|x| x.to_i}. There's no good way to break up the string in SQL.

    select ancestors from ancestors_table where user_id=10;
    

    To find the number of users at each level, referred by user 3:

    select
       depth-(select depth from ancestors_table where user_id=3),
       count(*)
    from ancestors_table
    where ancestors like '%,3,%' or ancestors like '3,%' or ancestors like '%,3'
    group by depth;
    

    You can avoid SQL injection attacks in the like '%,3,%' parts of these queries by using like concat('%,', ?, ',%') instead and binding the an integer for the user number to the placeholder.

提交回复
热议问题