SQL Server,找到任意值的序列

Rus*_*een 2 sql sql-server-2008

我们假设我们有一个维护表

Customer LastLogin ActionType
1        12/1/2007 2
1        12/2/2007 2
etc.
Run Code Online (Sandbox Code Playgroud)

我们想要一个列表,其中列出了在给定年份内的任何时间点都有一个或多个不间断序列,长达14天,以行动类型2登录的所有客户.

我当然可以使用代码轻松完成此操作,甚至可以在小集合上快速完成.在SQL中是否有非游标方式来执行此操作?

Qua*_*noi 5

这将选择具有至少两个相同类型的连续动作的所有客户.

WITH    rows AS 
        (
        SELECT  customer, action,
                ROW_NUMBER() OVER (PARTITION BY customer ORDER BY lastlogin) AS rn
        FROM    mytable
        )
SELECT  DISTINCT customer
FROM    rows rp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    rows rl
        WHERE   rl.customer = rp.customer
                AND rl.rn = rp.rn + 1
                AND rl.action = rp.action
        )
Run Code Online (Sandbox Code Playgroud)

这是对行动更有效的查询2:

WITH    rows AS 
        (
        SELECT  customer, ROW_NUMBER() OVER (PARTITION BY customer ORDER BY lastlogin) AS rn
        FROM    mytable
        WHERE   action = 2
        )
SELECT  DISTINCT customer
FROM    rows rp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    rows rl
        WHERE   rl.customer = rp.customer
                AND rl.rn = rp.rn + 1
        )
Run Code Online (Sandbox Code Playgroud)

更新2:

要选择不间断的范围:

WITH    rows AS 
        (
        SELECT  customer, action, lastlogin
                ROW_NUMBER() OVER (PARTITION BY customer ORDER BY lastlogin) AS rn
                ROW_NUMBER() OVER (PARTITION BY customer, action ORDER BY lastlogin) AS series
        FROM    mytable
        )
SELECT  DISTINCT customer
FROM    (
        SELECT  customer
        FROM    rows rp
        WHERE   action
        GROUP BY
                customer, actioncode, series - rn
        HAVING
                DETEDIFF(day, MIN(lastlogin), MAX(lastlogin)) >= 14
        ) q
Run Code Online (Sandbox Code Playgroud)

此查询计算两个系列:一个返回连续ORDER BY lastlogin,另一个另外分区action:

action  logindate rn  series diff = rn - series
1       Jan 01    1   1      0
1       Jan 02    2   2      0
2       Jan 03    3   1      2
2       Jan 04    4   2      2
1       Jan 05    5   3      2
1       Jan 06    6   4      2
Run Code Online (Sandbox Code Playgroud)

只要两种方案之间的差异相同,该系列就不会中断.每次中断都会打破这个系列.

这意味着(action, diff)的组合定义了不间断的组.

我们可以分组action, diff,查找MAXMIN组内并过滤它们.

如果您需要选择14行而不是14连续几天,只需过滤COUNT(*)而不是DATEDIFF.