2016-05-17 11 views
4

Ich versuche, die Datensätze aus einer Tabelle in meiner MySQL-Datenbank zu retrive, wobei gilt:SQL-Abfrage Datensätze abzurufen am nächsten zeitzustempeln

  • den Zeitstempel ist in der Nähe von einer Variablen I bereitzustellen; und
  • durch die Felder gruppiert Keya, KeyB, keyc und KeyD

ich die Variable hart codiert haben, wie unten dies zu testen, aber nicht bekommen kann die Abfrage zu arbeiten.

SQLFiddle

Mein aktuelles Schema ist:

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); 

und die Abfrage Ich habe zur Zeit ist:

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; 

Alles, was ich kann zu extrahieren scheint aus den Beispieldaten frühestens zwei sind Aufzeichnungen und nicht die beiden am nächsten zu der Datetime. Was ich erhalten:

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 

ich sehen erwarte:

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 

Jede mögliche Unterstützung geschätzt!

+1

Bitte stellen Sie sicher, dass die DB Sie SQL oder MySQL verwenden. Es scheint, dass Sie MYSQL verwenden. –

+0

Entschuldigung, dies ist eine MYSQL DB. – mousey3209

+0

Ich bin mir über MYSQL nicht sicher, aber in MSSQL müssen Sie zuerst das maximale Datum nach dem Tappen finden und dann self join verwenden. Vielleicht hilft es dir. –

Antwort

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; 

Diese Abfrage die Werte zurückgibt Sie wollen.

+0

Danke, das schien die Arbeit am einfachsten zu erledigen. Ich werde ein bisschen Zeit damit verbringen müssen, genau durchzugehen, was hier passiert. – mousey3209

0

Hilft das?

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, Daten Professional Madeira - Data Solutions, http://www.madeiradata.com

0

Sie erwarten hier offensichtlich etwas Magie. Sie gruppieren sich nach einigen Feldern und wählen die Spalte timestamp und ihre Differenz zur aktuellen Uhrzeit aus. Und irgendwie denkst du, du solltest jetzt die nächste Zeit bekommen. Warum? Warum sollte das passieren? Sie sagen dem DBMS nicht, das zu tun. Sie lassen es einfach einen der passenden Zeitstempel beliebig auswählen. Um einen bestimmten Wert pro Gruppe auszuwählen, benötigen Sie eine Aggregatfunktion, z. MIN um einen Mindestwert zu erhalten.

Sie benötigen zwei Schritte:

Erster Schritt: Finden Sie die minimale Differenz Zeitstempel nun pro Gruppe.

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; 

Zweiter Schritt: Mit der Abfrage aus dem ersten Schritt, finden die passenden Datensätze für jede dieser minimalen Unterschiede.

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 Geige: http://sqlfiddle.com/#!9/a6004b/10

(Ersetzen '2016-05-12 04:11:00' mit now() in Ihrem realen Abfrage.)