在 MySQL 中,您可以在检索数据时在 SELECT 语句中分配变量。此功能有助于解决许多“通常”使用窗口函数(MySQL 没有)的问题。它也可以帮助你。这是我最终得到的解决方案:
SET @startdate = CAST(NULL AS datetime);
SET @granularity = 60; /* minutes */
SET @minduration = 180; /* minutes */
SET @minvalue = 10;
SELECT
t.Date,
t.Value
FROM (
SELECT
StartDate,
MAX(Date) AS EndDate
FROM (
SELECT
Date,
Value,
CASE
WHEN Value > @minvalue OR @startdate IS NOT NULL
THEN IFNULL(@startdate, Date)
END AS StartDate,
@startdate := CASE
WHEN Value > @minvalue
THEN IFNULL(@startdate, Date)
END AS s
FROM (
SELECT Date, Value FROM YourTable
UNION ALL
SELECT MAX(Date) + INTERVAL @granularity MINUTE, @minvalue FROM YourTable
) s
ORDER BY Date
) s
WHERE StartDate IS NOT NULL
GROUP BY StartDate
) s
INNER JOIN YourTable t ON t.Date >= s.StartDate AND t.Date < s.EndDate
WHERE s.EndDate >= s.StartDate + INTERVAL @minduration MINUTE
;
这里使用的四个变量中的三个仅仅是脚本参数,只有一个,@startdate
实际上在查询中被赋值和检查。
基本上,查询遍历行,标记那些值大于特定最小值 ( @minvalue
) 的行,最终生成值匹配条件的时间范围列表。实际上,为了正确计算结束边界,紧跟在匹配行后面的非匹配行也包含在各个组中。正因为如此,一个额外的行被添加到原始数据集中,其中Date
计算出最新的Date
加上@granularity
表中指定的时间戳,并且Value
只是@minvalue
.
获得后,范围列表将连接回原始表,以检索位于范围边界之间的详细信息行,并在此过程@minduration
中过滤掉不够长的范围(由 指定)。
如果您在 SQL Fiddle 上运行此解决方案,您将看到以下输出:
DATE VALUE
------------------------------ -----
January, 01 2000 03:00:00-0800 11
January, 01 2000 04:00:00-0800 11
January, 01 2000 05:00:00-0800 11
据我所知,这是您所期望的。