用于添加自动增量的SQL递归方法

时间:2017-05-29 02:53:09

标签: sql sql-server recursion common-table-expression

我是SQL的首发。我有一个问题对我来说非常棘手,故事很长。

  • 第一个表是存储用户信息的用户表。
  • 第二个表是存储用户交易的交易表。
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)

我试图实现的操作是,我将给“发布消息”和所有他自己的推荐人的用户分数。对于每个推荐人来说,获得的积分将少于前一个积分。

例如: - 用户5> 77> 80

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

我做了我想要的结果的递归输出,但是我不知道引用者是否与他们的孩子有联系。

分配给每个TIER的推荐人和直接人员的点由另一个表维护。该表具有loyalprogid,loyalruleid和rulelevel的关键字,用于了解为孩子所获得的积分分配给推荐人的点数。

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 个答案:

答案 0 :(得分: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 |
+--------+----------+-------------+-------------+-----------+--------+