很难说出这一个的标题.
我有一个数据表,每个发票包含一行.例如:
| Invoice ID | Customer Key | Date | Value | Something |
| ---------- | ------------ | ---------- | ------| --------- |
| 1 | A | 08/02/2019 | 100 | 1 |
| 2 | B | 07/02/2019 | 14 | 0 |
| 3 | A | 06/02/2019 | 234 | 1 |
| 4 | A | 05/02/2019 | 74 | 1 |
| 5 | B | 04/02/2019 | 11 | 1 |
| 6 | A | 03/02/2019 | 12 | 0 |
Run Code Online (Sandbox Code Playgroud)
我需要添加另一列来计算每个CustomerKey的前一行数,但仅当"Something"等于1时才会这样,以便它返回:
| Invoice ID | Customer Key | Date | Value | Something | Count |
| ---------- | ------------ | ---------- | ------| --------- | ----- |
| 1 | A | 08/02/2019 | 100 | 1 | 2 |
| 2 | B | 07/02/2019 | 14 | 0 | 1 |
| 3 | A | 06/02/2019 | 234 | 1 | 1 |
| 4 | A | 05/02/2019 | 74 | 1 | 0 |
| 5 | B | 04/02/2019 | 11 | 1 | 0 |
| 6 | A | 03/02/2019 | 12 | 0 | 0 |
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用这样的CTE来做到这一点......
(
select
count(*)
from table
where
[Customer Key] = t.[Customer Key]
and [Date] < t.[Date]
and Something = 1
)
Run Code Online (Sandbox Code Playgroud)
但是我有很多数据,这很慢.我知道我也可以使用交叉应用来实现同样的目的,但据我所知,这并不比仅仅使用CTE更好.
所以; 是否有更有效的方法来实现这一目标,还是我只是吮吸它?
编辑:我最初发布这个没有要求只Something = 1
计算行数.Mea culpa - 我赶紧问它.不幸的是,我认为这意味着我无法使用row_number() over (partition by [Customer Key])
假设您使用的是 SQL Server 2012+,您可以使用窗口函数:
COUNT(CASE WHEN Something = 1 THEN CustomerKey END) OVER (PARTITION BY CustomerKey ORDER BY [Date]
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) -1 AS [Count]
Run Code Online (Sandbox Code Playgroud)
新的所需逻辑之前的旧答案:
COUNT(CustomerKey) OVER (PARTITION BY CustomerKey ORDER BY [Date]
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) -1 AS [Count]
Run Code Online (Sandbox Code Playgroud)
如果您没有使用2012,则替代方法是使用ROW_NUMBER
ROW_NUMBER() OVER (PARTITION BY CustomerKey ORDER BY [Date]) - 1 AS Count
Run Code Online (Sandbox Code Playgroud)