首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带扭曲的条件窗口函数--最多包括前面的X行,但排除某些行

带扭曲的条件窗口函数--最多包括前面的X行,但排除某些行
EN

Database Administration用户
提问于 2020-05-01 02:21:07
回答 2查看 536关注 0票数 2

询问使用SQL Server并行仓库的朋友。

他们™有一张每周销售金额表,如下(请原谅不恰当的专栏说明):

代码语言:javascript
复制
+-------+------------+
| week  |  amount    |
+-------+------------+
|    1  | 100.00     |
|    2  | 100.00     |
|    3  | 100.00     |
|    4  | 100.00     |
|    5  | 100000.00  |
|    6  | 100.00     |
|    7  | 50000.00   |
|    8  | 50000.00   |
|    9  | 50000.00   |
|   10  | 100.00     |
+-------+------------+

还有一份“坏”周的清单,例如。

代码语言:javascript
复制
+------+
| week |
+------+
|    5 |
|    7 |
|    8 |
|    9 |
+------+

他们需要为每周选择“坏”周,包括“坏”周,前四个并不是“坏”的周的销售额之和,即尽可能追溯,跳过“坏”的周记录,才能加起来最多四笔销售额。因此,预期结果将是:

代码语言:javascript
复制
+-------+------------+
| week  | sum_not_bad|
+-------+------------+
|    1  | null       |
|    2  | 100.00     |
|    3  | 200.00     |
|    4  | 300.00     |
|    5  | 400.00     |
|    6  | 400.00     |
|    7  | 400.00     |
|    8  | 400.00     |
|    9  | 400.00     |
|   10  | 400.00     |
+-------+------------+

我有一个小提琴,我认为这是朝着正确方向迈出的一步,但我不知道下一步是什么(S)。

有人有洞察力吗?

EN

回答 2

Database Administration用户

回答已采纳

发布于 2020-05-01 03:32:53

这里有一种方法,它使用PARTITION将所有的好周组合在一起,并获得前4个好周的累积良好计数。然后,按照使用级联的解决方案2的思路,采用一种方法来解决对LAST_VALUE缺乏支持的问题,忽略了NULL,并降低了以前的“好”值。

它记录了两个累积的总和。一个包括当前行(如果“下一个”行是坏的,则由下一行使用)和一个不包含当前行的行。

代码语言:javascript
复制
WITH T
     AS (SELECT d.week,
                d.amount,
                CASE WHEN b.week IS NULL THEN 0 ELSE 1 END AS is_bad_week,
                SUM(CASE WHEN b.week IS NULL THEN d.amount END)
                  OVER ( PARTITION BY CASE WHEN b.week IS NULL THEN 0 ELSE 1 END ORDER BY d.week rows BETWEEN 4 PRECEDING AND 1 PRECEDING) cume_sum_prev4toprev1,
                SUM(CASE WHEN b.week IS NULL THEN d.amount END)
                  OVER ( PARTITION BY CASE WHEN b.week IS NULL THEN 0 ELSE 1 END ORDER BY d.week rows BETWEEN 3 PRECEDING AND CURRENT ROW) cume_sum_prev3tocurrent
         FROM   data d
                LEFT JOIN bad_weeks b
                       ON d.week = b.week)
SELECT week,
       CASE WHEN is_bad_week = 1 THEN 
       CAST(SUBSTRING(MAX(RIGHT(CONCAT('0000000000', week), 10) + CAST(cume_sum_prev3tocurrent AS VARCHAR(20))) OVER (ORDER BY week), 11, 20) AS DECIMAL(20, 2)) 
       ELSE
       CAST(SUBSTRING(MAX(RIGHT(CONCAT('0000000000', week), 10) + CAST(cume_sum_prev4toprev1 AS VARCHAR(20))) OVER (ORDER BY week), 11, 20) AS DECIMAL(20, 2))
       END AS sum_not_bad
FROM   T
ORDER  BY week 
票数 3
EN

Database Administration用户

发布于 2020-05-01 05:45:02

代码语言:javascript
复制
SELECT * 
FROM data as d
  OUTER APPLY
  (
      SELECT SUM(prev_amount) as sum_not_bad
      FROM
          (SELECT TOP(4) (p.amount)as prev_amount
           FROM data as p
               LEFT JOIN bad_weeks as b
                    ON p.week = b.week
           WHERE p.week < d.week
                AND b.week is null
           ORDER BY p.week DESC
          )a
  )oa

输出

代码语言:javascript
复制
week        amount                                  sum_not_bad
1           100.00                                  NULL
2           100.00                                  100.00
3           100.00                                  200.00
4           100.00                                  300.00
5           100000.00                               400.00
6           100.00                                  400.00
7           50000.00                                400.00
8           50000.00                                400.00
9           50000.00                                400.00
10          100.00                                  400.00

[医]小提琴

票数 4
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/266242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档