Krátké a jednoduché otázky mají tendenci získat více pozornosti než ty dlouhé/složité. Není to proto, že bychom nedokázali odpovědět, ale s tolika otázkami a tak malým dobrovolným časem, který můžeme věnovat, je těžké ospravedlnit čas na čtení velkých otázek.
Myslím si však, že váš základní požadavek není tak složitý. Chcete způsob, jak načíst řádky, které spadají do časového rozsahu, NEBO pokud nejsou v tomto rozsahu, poskytnout řádky nejbližší tomuto rozsahu.
V databázích, které podporují ROW_NUMBER() OVER() je to docela snadné (a MySQL 8.x je plánováno to podporovat), ale do té doby můžete k emulaci row_number() používat proměnné a uspořádaný poddotaz.
Toto řešení si můžete vyzkoušet zde na SQL Fiddle
Nastavení schématu 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);
Dotaz :
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)
Takže to, co to udělá, je vypočítat "RowNumber", které začíná na 1 pro nejnovější řádek pro každou zdrojovou tabulku. Poté je tato odvozená tabulka filtrována buď podle časového rozsahu, nebo podle čísla řádku, pokud není v časovém rozsahu.
Všimněte si také, že NEPOUŽÍVÁM UNION
ale místo toho použili UNION ALL
. Existuje velký rozdíl ve výkonu a měli byste se naučit používat každý podle potřeby. Pokud používáte UNION
nepoužívejte také select distinct
protože jen plýtváte úsilím.
Výsledky :
| 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 |