2017-05-29 65 views
3

我是一个SQL启动器。我有一个对我来说非常棘手的问题,故事很长。添加自动增量的SQL递归方法

  • 第1张表是存储用户信息的用户表。
  • 第二个表是存储用户事务的事务表。
create table nl_users 
(
    userid  int not null primary key, 
    datejoin datetime not null, 
    referrer int not null, 
    pointsbal float not null default 0 
) 

create table nl_loyaltrans 
(
    loyaltransid  varchar(15) not null primary key, 
    userid    int not null, 
    datetran   datetime not null, 
    loyalprogid   varchar(20) not null, 
    loyalruleid   varchar(20) not null, 
    trantype   char(1) not null, 
    trandescp   varchar(100) null, 
    points    int not null, 
) 

insert into nl_users values (79, GETDATE(), 0, 0) 
insert into nl_users values (80, GETDATE(), 77, 0) 
insert into nl_users values (77, GETDATE(), 5, 0) 
insert into nl_users values (5, GETDATE(), 0, 0) 

insert into nl_loyaltrans values ('2017052300001', 79, GETDATE(), 'SOCINVEST', 'POSTMSG', 'E', 'Earned Points', 5) 
insert into nl_loyaltrans values ('2017052300003', 80, GETDATE(), 'SOCINVEST', 'POSTMSG', 'E', 'Earned Points', 5) 

我想实现的操作,我会给点到用户谁“后味精”和他所有的各自引荐。对于每个引用者而言,每个引用的点都会比前一个要少。

例如: --user 5> 77> 80

如果用户80获得5分,
用户77将获得4个点和
用户5将获得3分

我确实我期望的结果的递归输出,但我不能让它知道引用链接到他们的孩子。

分配给每个TIER的引用者和直接人员的点由另一个表维护。该表具有忠诚,忠诚和规则等级的关键,从而知道分配给引荐者的点数是否由他们的孩子获得。

create table nl_loyalruledet 
(
    loyalprogid  varchar(20) not null, 
    loyalruleid  varchar(20) not null, 
    rulelevel  int not null, 
    methodtype  char(1) not null, 
    flat   float not null default 0 
) 

这里是我的查询:

;WITH parents 
AS (
    SELECT u.userid 
     ,u.referrer 
     ,lt.loyalprogid 
     ,lt.loyalruleid 
     ,cast(1 AS INT) AS rulelevel 
    FROM nl_loyaltrans lt 
    LEFT JOIN nl_users u ON lt.userid = u.userid 

    UNION ALL 

    SELECT c.userid 
     ,c.referrer 
     ,CAST(loyalprogid AS VARCHAR(20)) 
     ,CAST(loyalruleid AS VARCHAR(20)) 
     ,cast((
       row_number() OVER (
        ORDER BY c.userid 
        ) + 1 
       ) AS INT) AS rulelevel 
    FROM nl_users c 
    INNER JOIN parents p ON p.referrer = c.userid -- this is the recursion 
    ) 
SELECT * 
FROM parents 

所需的输出 - >

userid referrer loyalprogid loyalruleid rulelevel points 
79  0  SOCINVEST POSTMSG  1   5 
80  77  SOCINVEST POSTMSG  1   5 
77  5  SOCINVEST POSTMSG  2   4 
5  0  SOCINVEST POSTMSG  3   3 

我实际上可以从加入nl_loyalruledet到结果集得到

我不能得到规则级别的权利,因为它的递归方法我认为。

+1

请请只DBMS您使用 – Sami

+1

'mysql'不支持的CTE所以它最有可能' SQL-server'。但没有任何假设。请使用特定的标签。 – niksofteng

回答

2

试试下面..我已经使用dateran列进行排序。

对于复杂性,我在nl_loyaltrans中插入了一条记录。

insert into nl_loyaltrans 
values ('2017052300004', 77, GETDATE(), 'SOCINVEST', 'POSTMSG', 'E', 'Earned Points', 6) 

现在点击下面的查询

;WITH parents 
AS (
    SELECT u.userid 
     ,u.referrer 
     ,lt.loyalprogid 
     ,lt.loyalruleid 
     ,cast(1 AS INT) AS rulelevel 
     ,lt.datetran 
     ,LT.points 
    FROM nl_loyaltrans lt 
    LEFT JOIN nl_users u ON lt.userid = u.userid 

    UNION ALL 

    SELECT c.userid 
     ,c.referrer 
     ,CAST(loyalprogid AS VARCHAR(20)) 
     ,CAST(loyalruleid AS VARCHAR(20)) 
     , P.rulelevel +1 
     ,P.datetran 
     ,p.points-1 
    FROM nl_users c 
    INNER JOIN parents p ON p.referrer = c.userid -- this is the recursion 
    ) 
SELECT userid,referrer,loyalprogid,loyalruleid,rulelevel,points 
FROM parents 
ORDER BY datetran , rulelevel 

结果:

+--------+----------+-------------+-------------+-----------+--------+ 
| userid | referrer | loyalprogid | loyalruleid | rulelevel | points | 
+--------+----------+-------------+-------------+-----------+--------+ 
|  79 |  0 | SOCINVEST | POSTMSG  |   1 |  5 | 
|  80 |  77 | SOCINVEST | POSTMSG  |   1 |  5 | 
|  77 |  5 | SOCINVEST | POSTMSG  |   2 |  4 | 
|  5 |  0 | SOCINVEST | POSTMSG  |   3 |  3 | 
|  77 |  5 | SOCINVEST | POSTMSG  |   1 |  6 | 
|  5 |  0 | SOCINVEST | POSTMSG  |   2 |  5 | 
+--------+----------+-------------+-------------+-----------+--------+ 
+1

p.rulelevel + 1救我的屁股....谢谢..... omg ....你怎么在cte专家?是任何网站你可以学习cte?我发现并没有很多网站教会像那些教SQL更多的cte。 – SicaYoumi

+1

谢谢..我从stackoverflow本身了解到它.. :) –