我有一个数据库表('map'),其中包含以下列:
我想要的是每次验证= 1时前后30个mapval的表。这61行应来自表'map'并包含所有行(即当validate = 0或1时,不仅仅是1 )。
我尝试使用lag / lead进行查询,但没有运气。
仅供参考,一旦我有了这张桌子,我就打算对数据做一些基本的事情。像平均值,中位数(带有percentile_cont)和模式(带有有序计数)。
此时我可以使用以下内容轻松地使用表格执行AVG:
SELECT [ptID],[time],[mapval],[validate],
IIF([validate]=1,
AVG(CAST ([mapval] AS decimal))
OVER(
PARTITION BY [ptID]
ORDER BY [ptID] ASC, [time] ASC
ROWS BETWEEN 30 PRECEDING AND 30 FOLLOWING
)
,NULL) AS 'sixytminavg'
但遗憾的是不能做中位数或模式。
龙卷风,但我希望它能提供所有信息。提前谢谢!
答案 0 :(得分:0)
在我的头顶,可能是以下情况?
SELECT m.ptid, m.uniid, m.time, m.mapval, m.validate
FROM map m INNER JOIN
(SELECT uniid
FROM map
WHERE validate=1) AS valids ON m.uniid BETWEEN valids.uniid-30 AND valids.uniid+30
ORDER BY m.uniid
答案 1 :(得分:0)
让我专注于此:
我想要的是一张包含前后30的表格 mapval每次验证= 1.这61行应来自 表'map'并包括所有行(即,当validate = 0或1时,不是 只是1)。
每次验证后都可以获得30行 - 假设没有其他验证 - 将行分成组。我们的想法是为每一行分配一个验证组。并且,您可以通过计算每行之前验证次数为1的次数来完成此操作。然后取前31行:
select m.*
from (select m.*, row_number() over (partition by grp order by time) as seqnum
from (select m.*, sum(validate) over (order by ptId order by time) as grp
from map m
) m
) m
where seqnum <= 31;
您可以同时为小组之前和之后执行此操作:
select m.*
from (select m.*,
row_number() over (partition by grp order by time) as seqnum_after,
row_number() over (partition by grp order by time desc) as seqnum_before
from (select m.*,
sum(validate) over (order by ptId order by time) as grp_after,
sum(validate) over (order by ptId order by time desc) as grp_before
from map m
) m
) m
where seqnum_after <= 31 or seqnum_before <= 31;
编辑:
如果验证距离太近,则使用join
方法代替:
select m.*
from (select m.*, row_number() over (partition by ptid order by time) as seqnum
from map m
where validate = 1
) v join
(select m.*, row_number() over (partition by ptid order by time) as seqnum
from map m
) m
on v.ptid = m.ptid and m.seqnum between v.seqnum - 30 and v.seqnum + 30;
答案 2 :(得分:0)
感谢@Gordon的解决方案。唯一的问题是第一个选择将row_numbers限制为那些经过验证的行,而不是对所有行进行编号并选择已验证的行。我已经添加了另一个嵌套select来实现它。不是最快的查询,但我只需要在我们的数据集上运行几次。
select q.*, n.time rowtime, n.mapval rowmapval
from ( select v.*
from (
select m.*, row_number() over (partition by ptid order by time) as seqnum
from map m
) v
where validate = 1
) q
join
(select m.*, row_number() over (partition by ptid order by time) as seqnum
from map m
) n
on q.ptid = n.ptid and n.seqnum between q.seqnum - 30 and q.seqnum + 30
ORDER by q.ptID, q.time, n.time