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中是否有非游标方式来执行此操作?
这将选择具有至少两个相同类型的连续动作的所有客户.
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,查找MAX和MIN组内并过滤它们.
如果您需要选择14行而不是14连续几天,只需过滤COUNT(*)而不是DATEDIFF.
| 归档时间: |
|
| 查看次数: |
649 次 |
| 最近记录: |