SQL 服务器: 查找最近连续大于 5 的记录
SQL Server : find recent consecutive records that are greater than 5
我需要编写一个查询,根据最近的 LogDate
.
显示按 FormID
细分的结果,其值大于 5
根据最近的 LogDate
,如果有一个值小于 5,它应该显示从那个点开始大于 5 的值,因为小于 5 的值是 'reset' 如果你愿意的话。
我实际上是在查看最近连续 LogDate
条大于 5 的记录。
假设我们有以下记录集:
FormID Value LogDate
--------------------------
Form2 6 10/12/19
Form2 7 10/13/19
Form1 8 10/12/19
Form1 12 10/12/19
Form1 3 10/14/19
Form1 8 10/15/19
Form1 6 10/21/19
以下将 return 以下(请注意我也想显示 row_num:
FormID Value LogDate row_num
----------------------------------
Form2 6 10/12/19 1
Form2 7 10/13/19 2
Form1 8 10/15/19 1
Form1 6 10/21/19 2
注意上面的例子,因为下面的记录最近的值小于5(值为3),所以我们需要获取大于5的记录。
另一个例子:
FormID Value LogDate
Form1 8 10/15/19
Form1 3 10/21/19
RESULT: 不会显示结果,因为最近的记录大于 5
另一个例子:
FormID Value LogDate
Form2 4 10/12/19
Form2 3 10/13/19
Form1 16 10/12/19
Form1 3 10/12/19
Form1 3 10/14/19
Form1 8 10/15/19
Form1 12 10/21/19
这里的结果是:
FormID Value LogDate row_num
Form1 8 10/15/19 1
Form1 12 10/21/19 2
另一个例子:
FormID Value LogDate
Form1 12 10/12/19
Form2 13 10/13/19
结果:
FormID Value LogDate row_num
Form1 12 10/12/19 1
Form2 13 10/13/19 2
据我了解,这可以通过 LAG 函数来完成,但不确定如何将其完全放在一起。
我们可以这样做:
DECLARE @mytable TABLE
(
FormID VARCHAR(50),
[Value] INT,
LogDate DATETIME
)
select t.*,
lag(value) over(partition by formid order by logdate) lag_value
from @mytablet
但不确定如何将它们整合在一起。
一种方法是:
select t.*,
row_number() over (partition by formid order by logdate)
from t
where t.logdate > (select coalesce(max(t.logdate), '2000-01-01')
from t t2
where t2.formid = t.formid and t.value <= 5
);
您还可以使用 window 函数:
select t.*,
row_number() over (partition by formid order by logdate)
from (select t.*,
max(case when value <= 5 then logdate end) over (partition by formid) as logdate_5
from t
) t
where logdate_5 is null or
date > logdate_5
order by formid, logdate;
如果我没听错的话,你可以用 window 函数来做到这一点:
select
from (
select t.*,
row_number() over(partition by formid order by logdate desc) rn,
sum(case when value > 5 then 1 else 0 end) over(partition by formid order by logdate desc) grp
from mytable t
) t
where rn = grp
想法是将 5
以上的值的数量与行号进行比较,从最近的值开始计算。可以保留两个值相等的行。
在 fiddle 中找到指示性答案。
reset_calendar
是重置发生的日期,用于过滤数据。
SELECT temp.*,
ROW_NUMBER() OVER (PARTITION BY temp.FormID ORDER BY temp.LogDate) AS Sequence
FROM (
SELECT t.*
FROM t
LEFT JOIN (
SELECT FormID, MAX(LogDate) AS recent_reset
FROM t
WHERE Value<6
GROUP BY FormID) AS reset_calendar
ON t.FormID = reset_calendar.FormID
WHERE t.LogDate > reset_calendar.recent_reset OR reset_calendar.recent_reset IS NULL)temp
我需要编写一个查询,根据最近的 LogDate
.
FormID
细分的结果,其值大于 5
根据最近的 LogDate
,如果有一个值小于 5,它应该显示从那个点开始大于 5 的值,因为小于 5 的值是 'reset' 如果你愿意的话。
我实际上是在查看最近连续 LogDate
条大于 5 的记录。
假设我们有以下记录集:
FormID Value LogDate
--------------------------
Form2 6 10/12/19
Form2 7 10/13/19
Form1 8 10/12/19
Form1 12 10/12/19
Form1 3 10/14/19
Form1 8 10/15/19
Form1 6 10/21/19
以下将 return 以下(请注意我也想显示 row_num:
FormID Value LogDate row_num
----------------------------------
Form2 6 10/12/19 1
Form2 7 10/13/19 2
Form1 8 10/15/19 1
Form1 6 10/21/19 2
注意上面的例子,因为下面的记录最近的值小于5(值为3),所以我们需要获取大于5的记录。
另一个例子:
FormID Value LogDate
Form1 8 10/15/19
Form1 3 10/21/19
RESULT: 不会显示结果,因为最近的记录大于 5
另一个例子:
FormID Value LogDate
Form2 4 10/12/19
Form2 3 10/13/19
Form1 16 10/12/19
Form1 3 10/12/19
Form1 3 10/14/19
Form1 8 10/15/19
Form1 12 10/21/19
这里的结果是:
FormID Value LogDate row_num
Form1 8 10/15/19 1
Form1 12 10/21/19 2
另一个例子:
FormID Value LogDate
Form1 12 10/12/19
Form2 13 10/13/19
结果:
FormID Value LogDate row_num
Form1 12 10/12/19 1
Form2 13 10/13/19 2
据我了解,这可以通过 LAG 函数来完成,但不确定如何将其完全放在一起。
我们可以这样做:
DECLARE @mytable TABLE
(
FormID VARCHAR(50),
[Value] INT,
LogDate DATETIME
)
select t.*,
lag(value) over(partition by formid order by logdate) lag_value
from @mytablet
但不确定如何将它们整合在一起。
一种方法是:
select t.*,
row_number() over (partition by formid order by logdate)
from t
where t.logdate > (select coalesce(max(t.logdate), '2000-01-01')
from t t2
where t2.formid = t.formid and t.value <= 5
);
您还可以使用 window 函数:
select t.*,
row_number() over (partition by formid order by logdate)
from (select t.*,
max(case when value <= 5 then logdate end) over (partition by formid) as logdate_5
from t
) t
where logdate_5 is null or
date > logdate_5
order by formid, logdate;
如果我没听错的话,你可以用 window 函数来做到这一点:
select
from (
select t.*,
row_number() over(partition by formid order by logdate desc) rn,
sum(case when value > 5 then 1 else 0 end) over(partition by formid order by logdate desc) grp
from mytable t
) t
where rn = grp
想法是将 5
以上的值的数量与行号进行比较,从最近的值开始计算。可以保留两个值相等的行。
在 fiddle 中找到指示性答案。
reset_calendar
是重置发生的日期,用于过滤数据。
SELECT temp.*,
ROW_NUMBER() OVER (PARTITION BY temp.FormID ORDER BY temp.LogDate) AS Sequence
FROM (
SELECT t.*
FROM t
LEFT JOIN (
SELECT FormID, MAX(LogDate) AS recent_reset
FROM t
WHERE Value<6
GROUP BY FormID) AS reset_calendar
ON t.FormID = reset_calendar.FormID
WHERE t.LogDate > reset_calendar.recent_reset OR reset_calendar.recent_reset IS NULL)temp