选择日期少于指定日期的每个组的最新行

时间:2018-09-15 13:52:27

标签: mysql sql date group-by

这有点棘手,但是我有一张看起来像这样的表:

Time                  Meter   Value
2018-09-15 11:00:00   IU       0.105
2018-09-15 11:00:00   GD       1.648
2018-09-10 10:00:00   OU      -0.018
2018-09-10 10:00:00   GD       1.659
2018-09-01 19:00:00   OU       0.003
2018-09-01 19:00:00   OD       2.188
2018-09-01 19:00:00   IU       0.096
2018-09-01 19:00:00   GD       1.670

对于任何给定的时间,我想获取每个不同仪表的最接近的先前值:例如:对于时间“ 2018-09-14 12:00:00”,我想获取:

2018-09-10 10:00:00 OU  -0.018
2018-09-10 10:00:00 GD  1.659
2018-09-10 04:15:00 KD  0.737
2018-09-01 19:00:00 IU  0.096

我最初认为此查询可能有效:

SELECT `meter`, max(`time`) time, `value` 
FROM `data` 
WHERE `time`<= '2018-09-15 12:00:00' 
GROUP BY `meter`;

它给出了预期的时间,但是值不同。

然后我认为最好的方法是使用此查询作为基础,然后使用输出运行另一个查询:

SELECT `meter`, max(`time`) time 
FROM `data` 
WHERE `time`<= '2018-09-15 12:00:00' 
GROUP BY `meter`;

输出:

2018-09-10 10:00:00 OU
2018-09-10 10:00:00 GD
2018-09-10 04:15:00 KD
2018-09-01 19:00:00 IU

然后在每一行上运行:

SELECT `value` 
FROM `data` 
where `time` = '...' AND `meter` - '...';

然后的问题是,如何将它滚动到一个查询中,以便为每行添加第三列,其中包含第二个查询的结果?

2 个答案:

答案 0 :(得分:3)

我认为最简单的方法是相关子查询:

lag()

当然,除非您使用的是MySQL 8.0。在这种情况下,select d.*, lag(value) over (partition by meter order by time) as prev_value from data d; 是最佳解决方案:

for x in thisdict:
   print(thisdict[x])

答案 1 :(得分:0)

您正在使用的查询可以进行如下修改:

SELECT testdata.*
FROM testdata
INNER JOIN (
    SELECT Meter, MAX(Time) AS MaxTime
    FROM testdata
    WHERE Time <= '2018-09-14 12:00:00'
    GROUP BY Meter
) AS sq ON testdata.Meter = sq.Meter AND testdata.Time = sq.MaxTime

但是您可以使用NOT EXISTS来获得乐趣:

SELECT *
FROM testdata
WHERE Time <= '2018-09-14 12:00:00'
AND NOT EXISTS (
    SELECT 1
    FROM testdata AS row_between_targettime_and_outerrowtime
    WHERE Meter = testdata.Meter
    AND Time <= '2018-09-14 12:00:00'
    AND Time > testdata.Time
)