use*_*586 12 sql-server lag lead
我有一个这样的表:
Number Price Type Date Time
------ ----- ---- ---------- ---------
23456 0,665 SV 2014/02/02 08:00:02
23457 1,3 EC 2014/02/02 07:50:45
23460 0,668 SV 2014/02/02 07:36:34
Run Code Online (Sandbox Code Playgroud)
对于每个EC,我需要上一个/下一个SV价格.在这种情况下,查询很简单.
Select Lag(price, 1, price) over (order by date desc, time desc),
Lead(price, 1, price) over (order by date desc, time desc)
from ITEMS
Run Code Online (Sandbox Code Playgroud)
但是,有一些特殊情况,其中两行或更多行是EC类型:
Number Price Type Date Time
------ ----- ---- ---------- ---------
23456 0,665 SV 2014/02/02 08:00:02
23457 1,3 EC 2014/02/02 07:50:45
23658 2,4 EC 2014/02/02 07:50:45
23660 2,4 EC 2014/02/02 07:50:48
23465 0,668 SV 2014/02/02 07:36:34
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我可以使用线索/滞后吗?如果没有,我是否必须使用子查询?
And*_*mar 10
你的问题(和Anon的优秀答案)是岛屿和差距的SQL的一部分.在这个答案中,我将尝试详细检查"row_number()magic".
我根据球赛中的事件做了一个简单的例子.对于每个活动,我们都要打印上一季度和下一季度相关的消息:
create table TestTable (id int identity, event varchar(64));
insert TestTable values
('Start of Q1'),
('Free kick'),
('Goal'),
('End of Q1'),
('Start of Q2'),
('Penalty'),
('Miss'),
('Yellow card'),
('End of Q2');
Run Code Online (Sandbox Code Playgroud)
这是一个显示"row_number()magic"方法的查询:
; with grouped as
(
select *
, row_number() over (order by id) as rn1
, row_number() over (
partition by case when event like '%of Q[1-4]' then 1 end
order by id) as rn2
from TestTable
)
, order_in_group as
(
select *
, rn1-rn2 as group_nr
, row_number() over (partition by rn1-rn2 order by id) as rank_asc
, row_number() over (partition by rn1-rn2 order by id desc)
as rank_desc
from grouped
)
select *
, lag(event, rank_asc) over (order by id) as last_event_of_prev_group
, lead(event, rank_desc) over (order by id) as first_event_of_next_group
from order_in_group
order by
id
Run Code Online (Sandbox Code Playgroud)
row_number()
s.第一个是1 2 3
表格中的每一行.第二个row_number()
位置在一个列表中暂停通知,在第二个列表中暂停其他事件.两者之间的差异rn1 - rn2
对于游戏的每个部分都是独一无二的.检查示例输出中的差异很有帮助:它位于group_nr
列中.你会看到每个值对应游戏的一个部分.1 2 3
升序和3 2 1
降序.lag()
和lead()
跳多远.我们必须滞后rank_asc
行才能找到上一节的最后一行.要查找下一部分的第一行,我们必须引导rank_desc
行.希望这有助于澄清峡谷和群岛的"魔力". 这是SQL Fiddle的一个工作示例.
是的,您可以使用LEAD/LAG.你只需要用一点ROW_NUMBER()魔法预先计算跳跃的距离.
DECLARE @a TABLE ( number int, price money, type varchar(2),
date date, time time)
INSERT @a VALUES
(23456,0.665,'SV','2014/02/02','08:00:02'),
(23457,1.3 ,'EC','2014/02/02','07:50:45'),
(23658,2.4 ,'EC','2014/02/02','07:50:45'),
(23660,2.4 ,'EC','2014/02/02','07:50:48'),
(23465,0.668,'SV','2014/02/02','07:36:34');
; WITH a AS (
SELECT *,
ROW_NUMBER() OVER(ORDER BY [date] DESC, [time] DESC) x,
ROW_NUMBER() OVER(PARTITION BY
CASE [type] WHEN 'SV' THEN 1 ELSE 0 END
ORDER BY [date] DESC, [time] DESC) y
FROM @a)
, b AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY x-y ORDER BY x ASC) z1,
ROW_NUMBER() OVER(PARTITION BY x-y ORDER BY x DESC) z2
FROM a)
SELECT *,
CASE [type] WHEN 'SV' THEN
LAG(price,z1,price) OVER(PARTITION BY [type] ORDER BY x)
ELSE LAG(price,z1,price) OVER(ORDER BY x)
END,
CASE [type] WHEN 'SV' THEN
LEAD(price,z2,price) OVER(PARTITION BY [type] ORDER BY x)
ELSE LEAD(price,z2,price) OVER(ORDER BY x)
END
FROM b
ORDER BY x
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14660 次 |
最近记录: |