Erweitern Sie die Abfrage darüber hinaus angegeben, die in der WHERE-Klausel
-
22-07-2019 - |
Frage
Es muss einen besseren Weg Abfrage geschrieben wird.
Ich möchte Sie alle Daten zwischen zwei Datumsangaben.Im Idealfall werden die ersten und letzten Zeilen der Ergebnismenge möchten, werden diese angegeben, die in der WHERE-Klausel.Wenn diese Zeilen nicht vorhanden sind, möchte ich die Zeilen vorausgehenden und folgenden der angeforderte Bereich.
Ein Beispiel:
Wenn meine Daten:
...
135321, 20090311 10:15:00
135321, 20090311 10:45:00
135321, 20090311 11:00:00
135321, 20090311 11:15:00
135321, 20090311 11:30:00
135321, 20090311 12:30:00
...
Und die Abfrage ist:
SELECT *
FROM data_bahf
WHERE param_id = 135321
AND datetime >= '20090311 10:30:00'
AND datetime <= '20090311 12:00:00'
Ich möchte die zurückgegebenen Daten umfassen die Zeile bei 10:15 und von 12:30 Uhr.Nicht nur diejenigen, streng erfüllen die WHERE-Klausel.
Dies ist die beste, die ich mir ausgedacht habe.
SELECT * FROM (
SELECT *
FROM data_bahf
WHERE param_id = 135321
AND datetime > '20090311 10:30:00'
AND datetime < '20090311 12:00:00'
UNION
(
SELECT * FROM data_bahf
WHERE param_id = 135321
AND datetime <= '20090311 10:30:00'
ORDER BY datetime desc
LIMIT 1
)
UNION
(
SELECT * FROM data_bahf
WHERE param_id = 135321
AND datetime >= '20090311 12:00:00'
ORDER BY datetime asc
LIMIT 1
)
)
AS A
ORDER BY datetime
(Ignorieren Sie die Verwendung von SELECT * für jetzt)
EDIT:Ich habe Indizes für param_id, datetime, und (param_id, datetime)
Lösung
Erstens, stellen Sie sicher, dass Sie ein composite index (param_id, datetime)
Zweite, eine Abfrage wie diese:
SELECT *
FROM data_bahf
WHERE param_id = 135321
AND datetime BETWEEN
COALESCE(
(
SELECT MAX(datetime)
FROM data_bahf
WHERE param_id = 135321
AND datetime <= '2009-01-01 00:00:00'
), '0001-01-01')
AND
COALESCE(
(
SELECT MIN(datetime)
FROM data_bahf
WHERE param_id = 135321
AND datetime >= '2009-01-02 00:00:00'
), '9999-01-01')
Gerade nachgeschaut, es läuft in 1.215 ms
für eine Beispieltabelle 200,000
Zeilen
Andere Tipps
Ich würde sagen:
SELECT
o.*
FROM
data_bahf o
WHERE
o.param_id = 135321
AND o.datetime BETWEEN
ISNULL(
(
SELECT MAX(datetime)
FROM data_bahf i
WHERE i.param_id = 135321 AND i.datetime <= '20090311 10:30:00'
),
'0001-01-01 00:00:00'
)
AND
ISNULL(
(
SELECT MIN(datetime)
FROM data_bahf i
WHERE i.param_id = 135321 AND i.datetime >= '20090311 12:00:00'
),
'9999-12-31 23:59:59'
)
EDIT:Fallback Hinzugefügt.
Wenn es keine Zeile passend zu den sub-Abfrage, es wird Ergebnis in eine NULL
Wert, die gefangen werden müssen, indem ISNULL()
oder BETWEEN
Betreiber fehl, und der Haupt Abfrage keine Zeilen.