sql - SQL Server:变量窗口函数
问题描述
使用 SQL Server 2016,我有两个这样的表:
T1
-----------------------
User | Y | M | V
---- ------------------
US1 | 2011 | 1 | 87.5
US1 | 2011 | 2 | 76.4
... | ... | ..| ...
US1 | 2018 | 7 | 4.7
US1 | 2018 | 8 | 7.7
US1 | 2018 | 9 | 16.3
US1 | 2018 | 10| 11.1
US1 | 2018 | 11| 98.8
US1 | 2018 | 12| 65.7
US2 | 2011 | 1 | 44.5
US2 | 2011 | 2 | 34.7
... | ... |...| ...
US2 | 2018 | 6 | 18.7
US2 | 2018 | 7 | 5.1
US2 | 2018 | 8 | 1.0
US2 | 2018 | 9 | 4.4
US2 | 2018 | 10| 22.6
US2 | 2018 | 11| 66.5
US2 | 2018 | 12| 23.7
T2
----------
User | S |
---- -----
US1 | 3 |
US2 | 5 |
我想得到一个这样的运行总和
SELECT t1.Y
,t1.M
,t1.User
,SUM(t1.V) OVER (PARTITION BY t1.User ORDER BY t1.Y,t1.M ROWS BETWEEN t2.S PRECEDING AND CURRENT ROW)
FROM t1
JOIN t2 ON t1.User = t2.User
所以我过去 2 个月的预期输出是
US1 | 2018 | 11| 133,9 (98.8+11.1+16.3+7.7)
US1 | 2018 | 12| 191.9 (65.7+98.8+11.1+16.3)
US2 | 2018 | 11| 118.3 (66.5+22.6+4.4+1.0+5.1+18.7)
US2 | 2018 | 12| 123.3 (23.7+66.5+22.6+4.4+1.0+5.1)
但我不能在窗口函数中使用 t2.S 作为变量。
有没有办法使用 Window Funcitons 来做到这一点?
解决方案
我认为窗框规范不允许使用表达式。您可以使用以下方法执行此操作apply
:
SELECT t1.Y, t1.M, t1.User, t2.sum_v
FROM t1 CROSS APPLY
(SELECT SUM(t.v) as sum_v
FROM (SELECT tt1.v, tt2.S
ROW_NUMBER() OVER (ORDER BY tt1.Y DESC, tt1.M DESC) as seqnum
FROM t1 tt1 JOIN
t2 tt2
ON tt1.User = tt2.User
WHERE tt1.User = t1.User
) t
WHERE seqnum <= S
) t2
编辑:
以上不起作用,因为顺序直接错误。在任何情况下,它都相当于一个自连接,而且是相当昂贵的。
这可以用窗口函数来完成吗?
我认为答案是“是”:
with t1 as (
select t1.*, t2.s,
sum(v) over (partition by user order by y, m) as running_v
from t1 join
t2
on t1.user = t2.user
) t
select t.*,
(running_v - running_v_s)
from (select t.*,
lag(running_v, s) over (partition by user order by y, m) as running_v_s
from t
) t;
虽然您不能将表达式用于窗框,但您可以将它们用于lag()
. 我认为这种方法可能是性能最好的方法。
推荐阅读
- android - 如何在 Android 的 XML 中绘制这个形状?
- c - C链表;列表中的最大频率节点
- php - PHP函数根据输入获得相同的输出
- javascript - 如何从 Javascript 呈现的索引中抓取 onclick 中的链接?
- android - 为什么我在使用改造的 android 上没有网络连接时收到 503 状态码?
- rest - Meteor 上的 REST API 与 OAuth2.0 身份验证
- bash - 配置文件应该在注释行之前允许空格吗?
- javascript - 如何使用 laravel 在 vue js 的另一个组件中添加 header.vue 和 footer.vue?
- ruby-on-rails - 在开发服务器上找不到 wkhtmltopdf-binary
- kotlin - 将两张地图合二为一