SQL查询以检索最接近时间戳的记录

时间:2016-05-17 04:54:18

标签: mysql sql database

我正在尝试从我的MySQL数据库中的表中检索记录,其中:

  • 时间戳最接近我提供的变量;和,
  • 按字段keyA,keyB,keyC和keyD
  • 分组

我已经对下面的变量进行了硬编码以测试它,但无法让查询起作用。

SQLFiddle

我目前的架构是:

CREATE TABLE dataHistory (
          timestamp datetime NOT NULL,
          keyA varchar(10) NOT NULL,
          keyB varchar(10) NOT NULL,
          keyC varchar(25) NOT NULL,
          keyD varchar(10) NOT NULL,
          value int NOT NULL,
          PRIMARY KEY (timestamp,keyA,keyB,keyC,keyD)
          );

INSERT INTO dataHistory
    (timestamp, keyA, keyB, keyC, keyD, value)
VALUES
    ('2016-05-12 04:15:00', 'value1', 'all', 'value2', 'domestic', 96921),
    ('2016-05-12 04:05:00', 'value1', 'all', 'value2', 'domestic', 96947),
    ('2016-05-12 04:20:00', 'value1', 'all', 'value2', 'domestic', 96954),
    ('2016-05-12 04:15:00', 'value1', 'all', 'value3', 'domestic', 2732),
    ('2016-05-12 04:10:00', 'value1', 'all', 'value3', 'domestic', 2819),
    ('2016-05-12 04:20:00', 'value1', 'all', 'value3', 'domestic', 2802);

我目前的查询是:

SELECT e.difference, e.timestamp, e.keyA, e.keyB, e.keyC, e.keyD, e.value
FROM (SELECT TIMESTAMPDIFF(minute, '2016-05-12 04:11:00', d.timestamp) as difference, d.timestamp, d.keyA, d.keyB, d.keyC, d.keyD, d.value
    FROM dataHistory d
    GROUP BY d.keyA, d.keyB, d.keyC, d.keyD) as e;

我似乎从样本数据中提取的是最早的两个记录,而不是最接近日期时间的两个记录。 我收到了什么:

difference  timestamp   keyA    keyB    keyC    keyD    value
-10 May, 12 2016 04:05:00   value1  all value2  domestic    96947
-5  May, 12 2016 04:10:00   value1  all value3  domestic    2819

我期待看到:

timestamp   keyA    keyB    keyC    keyD    value
May, 12 2016 04:15:00   value1  all value2  domestic    96921
May, 12 2016 04:10:00   value1  all value3  domestic    2819

任何帮助都将不胜感激!

3 个答案:

答案 0 :(得分:3)

SELECT e.difference, e.timestamp, e.keyA, e.keyB, e.keyC, e.keyD, e.value
FROM (SELECT ABS(TIMESTAMPDIFF(minute, '2016-05-12 04:11:00', d.timestamp)) as difference, d.timestamp, d.keyA, d.keyB, d.keyC, d.keyD, d.value
    FROM dataHistory d
    ORDER BY difference) as e
GROUP BY e.keyA, e.keyB, e.keyC, e.keyD;

此查询返回您想要的值。

答案 1 :(得分:0)

这有帮助吗?

SELECT
  TIMESTAMPDIFF (MINUTE , '2016-05-12 04:15:00' , MainTable.timestamp) AS Difference ,
  MainTable.timestamp ,
  MainTable.KeyA ,
  MainTable.KeyB ,
  MainTable.KeyC ,
  MainTable.KeyD ,
  MainTable.value
FROM
  dataHistory AS MainTable
LEFT OUTER JOIN
  dataHistory AS SecondaryTable
ON
  MainTable.KeyA = SecondaryTable.KeyA
AND
  MainTable.KeyB = SecondaryTable.KeyB
AND
  MainTable.KeyC = SecondaryTable.KeyC
AND
  MainTable.KeyD = SecondaryTable.KeyD
AND
  ABS (TIMESTAMPDIFF (MINUTE , '2016-05-12 04:15:00' , MainTable.timestamp)) > ABS (TIMESTAMPDIFF (MINUTE , '2016-05-12 04:15:00' , SecondaryTable.timestamp))
WHERE
  SecondaryTable.timestamp IS NULL;

Guy Glantser, 数据专业, Madeira - 数据解决方案, http://www.madeiradata.com

答案 2 :(得分:0)

你显然希望在这里发生一些魔术。您按某些字段进行分组,然后选择列timestamp及其与当前时间的差异。不知怎的,你认为你应该得到最接近的时间。为什么?为什么会这样?您没有告诉DBMS这样做。您只是让它随意选择一个匹配的时间戳。要为每个组选择一个特定值,您需要一个聚合函数,例如MIN获得最低价值。

您需要两个步骤:

第一步:查找现在每组的最小时间戳差异。

select 
  keya,
  keyb,
  keyc,
  keyd,
  min(abs(timestampdiff(minute, '2016-05-12 04:11:00', d.timestamp))) as difference
from datahistory 
group by keya, keyb, keyc, keyd;

第二步:使用第一步中的查询,找到每个最小差异的匹配记录。

select 
  best.difference, 
  dh.timestamp, 
  best.keyA, 
  best.keyB, 
  best.keyC, 
  best.keyD, 
  dh.value
from
(
  select 
    keya, keyb, keyc, keyd,
    min(abs(timestampdiff(minute, '2016-05-12 04:11:00', timestamp))) as difference
  from datahistory 
  group by keya, keyb, keyc, keyd
) best
join datahistory dh 
  on  dh.keya = best.keya and dh.keyb = best.keyb 
  and dh.keyc = best.keyc and dh.keyd = best.keyd
  and abs(timestampdiff(minute, '2016-05-12 04:11:00', dh.timestamp)) = best.difference
order by best.keyA, best.keyB, best.keyC, best.keyD;

SQL小提琴:http://sqlfiddle.com/#!9/a6004b/10

(在您的真实查询中将'2016-05-12 04:11:00'替换为now()。)