Krótkie i proste pytania przyciągają więcej uwagi niż te długie/złożone. Nie dzieje się tak dlatego, że nie możemy odpowiedzieć, ale przy tak wielu pytaniach i tak małej ilości czasu wolontariusza, który można poświęcić, trudno jest usprawiedliwić czas na przeczytanie ważnych pytań.
Myślę jednak, że twoje podstawowe wymagania nie są aż tak skomplikowane. Potrzebujesz sposobu na pobieranie wierszy, które mieszczą się w zakresie czasu LUB, jeśli nie w tym zakresie, podaj wiersze najbliższe temu zakresowi.
W bazach danych, które obsługują ROW_NUMBER() OVER() jest to dość łatwe (a MySQL 8.x ma to obsługiwać), ale do tego czasu do emulacji row_number() można używać zmiennych i uporządkowanego podzapytania.
Możesz wypróbować to rozwiązanie tutaj pod adresem SQL Fiddle
Konfiguracja schematu MySQL 5.6 :
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);
Zapytanie :
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)
Zatem to, co robi, to obliczanie „RowNumber”, który zaczyna się od 1 dla najnowszego wiersza dla każdej tabeli źródłowej. Następnie ta pochodna tabela jest filtrowana według zakresu czasu lub numeru wiersza, jeśli nie mieści się w zakresie czasu.
Pamiętaj też, że NIE używałem UNION
ale zamiast tego użyłem UNION ALL
. Istnieje duża różnica w wydajności i należy nauczyć się korzystać z każdego w zależności od potrzeb. Jeśli używasz UNION
nie używaj również select distinct
ponieważ po prostu marnujesz wysiłek.
Wyniki :
| 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 |