我想获取过去或将来最接近特定日期的数据,无论哪个更接近该日期。但我还需要distinct
之前type
。例如:
id |type |data | date
1 |0 |1904 |2018-08-19 00:14:32
2 |0 |1904 |2018-08-19 00:24:47
3 |0 |1904 |2018-08-19 05:02:30
4 |0 |1904 |2018-08-22 00:05:58
5 |0 |1904 |2018-08-22 00:08:34
6 |4 |1903 |2018-08-19 00:14:31
7 |6 |1926 |2018-08-19 00:14:32
8 |6 |1926 |2018-08-19 04:44:10
9 |6 |1926 |2018-08-19 04:52:58
10 |6 |1926 |2018-08-19 04:59:23
11 |6 |1926 |2018-08-22 00:05:58
12 |6 |1926 |2018-08-22 00:07:52
13 |6 |1926 |2018-08-22 00:08:34
14 |7 |1564 |2018-08-19 00:14:32
15 |8 |1900 |2018-08-19 00:14:32
如果我指定日期时间:2018-08-19 00:00:00
。我应该得到以下结果:
id | type
1 | 0
6 | 4
7 | 6
14 | 7
15 | 8
或者,如果我指定日期时间:2018-09-03 00:00:00
。我希望:
id | type
5 | 0
6 | 4
13 | 6
14 | 7
15 | 8
或者最后:2018-08-22 00:05:58
。
id | type
4 | 0
6 | 4
11 | 6
14 | 7
15 | 8
我尝试了一些没有实际意义的查询...
SELECT *
FROM history
WHERE (ABS(TIMESTAMPDIFF(DAY, date, "2018-08-19 00:08:34")) < 4) AND user_id = 1299
GROUP BY type
ORDER BY date
无论如何,仅通过MySQL查询就能做到吗?我是否需要使用一些应用程序逻辑来实现这一目标?我该如何查询?
答案 0 :(得分:2)
这采用标准查询模式来为每种类型查找具有极值的行。在这种情况下, extreme 表示最接近目标值。
首先,您需要一个聚合子查询来获取极值:每种类型的行与目标日期之间的最小增量时间。 (http://sqlfiddle.com/#!9/b51a7a/26/1)
SET @target := '2018-08-20 00:00:00';
SELECT type, MIN(ABS(TIMESTAMPDIFF(MINUTE, date, @target))) delta
FROM history
GROUP BY type
然后,使用ON
子句将其与原始表连接,以同时匹配类型和增量时间。全部放在一起(http://sqlfiddle.com/#!9/b51a7a/27/1)
SET @target := '2018-08-20 00:00:00';
SELECT history.*
FROM history
JOIN (
SELECT type, MIN(ABS(TIMESTAMPDIFF(MINUTE, date, @target))) delta
FROM history
GROUP BY type
) delta ON history.type=delta.type
AND ABS(TIMESTAMPDIFF(MINUTE, date, @target)) = delta
修改,可以轻松获取日期中最接近的将来或过去的日期。子查询(最近的查询)是
SELECT type, MAX(date) date
FROM history
WHERE date <= @target
GROUP BY date
则整个查询为
SELECT history.*
FROM history
JOIN (
SELECT type, MAX(date) date
FROM history
WHERE date <= @target
GROUP BY date
) m ON history.type = m.type AND history.date = m.date
答案 1 :(得分:0)
您可以在子查询中使用内部联接来实现最小差异
select
h.id, h.type
from
history
inner join
(select
type, min(TIMESTAMPDIFF(SECOND, date, '2012-06-06 15:20:18')) min_diff
from
history
where
(abs(TIMESTAMPDIFF(DAY, date, "2018-08-19 00:08:34")) < 4)
and user_id = 1299
group by
type) t on t.type = h.type
and TIMESTAMPDIFF(SECOND, h.date, '2012-06-06 15:20:18') = t.min_diff
答案 2 :(得分:0)
您可以通过row_number()
模仿其他RDBMS排序中的abs(timestampdiff(second, date, @dt))
功能:
select @rn := 0, @dt := cast('2018-08-19 04:52:00' as datetime);
select id, type from (
select id,
type,
data,
date,
@rn := @rn + 1 rn
from history
order by abs(timestampdiff(second, date, @dt))
) a where rn = 1;
答案 3 :(得分:0)
这应该可以解决问题。
create table test2 as
select c.id,c.type from(
select a.*,b.min
from test as a
left join
(select id, min(abs(date-"2018-09-01 00:00:00"dt)) as min from test
group by type ) as b
on a.id = b.id
) as c
where min = abs(date-"2018-09-01 00:00:00"dt)
order by id;
我们将id上的join回到最小原始日期差异,然后选择所需的记录。