Kurze und einfache Fragen erhalten tendenziell mehr Aufmerksamkeit als lange/komplexe. Das liegt nicht daran, dass wir sie nicht beantworten können, aber bei so vielen Fragen und so wenig ehrenamtlicher Zeit ist es schwer, die Zeit zum Lesen großer Fragen zu rechtfertigen.
Ich denke jedoch, dass Ihre Grundanforderung nicht so komplex ist. Sie möchten eine Möglichkeit, Zeilen abzurufen, die in einen Zeitbereich fallen, ODER, wenn sie nicht in diesem Bereich liegen, die diesem Bereich am nächsten liegenden Zeilen bereitzustellen.
In Datenbanken, die ROW_NUMBER() OVER() unterstützen, ist dies recht einfach (und MySQL 8.x soll dies unterstützen), aber bis dahin können Sie zur Emulation von row_number() Variablen und eine geordnete Unterabfrage verwenden.
Sie können diese Lösung hier unter SQL Fiddle testen
MySQL 5.6-Schema-Setup :
CREATE TABLE `ponumber` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));
INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 10:47:55',0);
INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',1217911);
INSERT INTO `PONumber` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:24:18',1217906);
CREATE TABLE `batch_number` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:18',5522);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:25:33',5521);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 11:44:45',5520);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:05',5519);
INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:22:58',5518);
CREATE TABLE `batchweight` (
`TimeStr` datetime NOT NULL,
`Value` int(11) NOT NULL,
UNIQUE KEY `uk_Times` (`TimeStr`));
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:19',38985);
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',38985);
INSERT INTO `batchweight` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:23:03',31002);
Abfrage :
SET @bStartTime := '2017-09-29 11:10:00'
SET @bEndTime := '2017-09-29 12:48:00'
SELECT
SrcTable, TimeStr, Value
FROM (
SELECT
@row_num :=IF( @prev_value=u.SrcTable, @row_num + 1 ,1) AS RowNumber
, u.*
, @prev_value := u.SrcTable
FROM (
select 'ponumber' SrcTable , TimeStr, `Value`
from ponumber
union all
select 'batch_number' SrcTable , TimeStr, `Value`
from batch_number
union all
select 'batchweight' SrcTable , TimeStr, `Value`
from batchweight
) u
CROSS JOIN (SELECT @row_num := 1, @prev_value :='') vars
ORDER BY SrcTable, TimeStr DESC
) d
WHERE (d.TimeStr between @bStartTime and @bEndTime)
OR (TimeStr < @bStartTime AND RowNumber = 1)
Dies berechnet also eine "RowNumber", die bei 1 für die neueste Zeile für jede Quelltabelle beginnt. Dann wird diese abgeleitete Tabelle entweder nach dem Zeitbereich oder nach der Zeilennummer gefiltert, wenn sie nicht innerhalb des Zeitbereichs liegt.
Beachten Sie auch, dass ich NICHT verwendet habe UNION
sondern haben stattdessen UNION ALL
verwendet . Es gibt einen großen Unterschied in der Leistung und Sie sollten lernen, jeden nach Bedarf zu verwenden. Bei Verwendung von UNION
verwenden Sie nicht auch select distinct
weil Sie nur Mühe verschwenden.
| SrcTable | TimeStr | Value |
|--------------|----------------------|-------|
| batchweight | 2017-09-29T12:46:19Z | 38985 |
| batch_number | 2017-09-29T12:46:18Z | 5522 |
| batch_number | 2017-09-29T12:25:33Z | 5521 |
| batch_number | 2017-09-29T11:44:45Z | 5520 |
| ponumber | 2017-09-28T10:47:55Z | 0 |