Korte og enkle spørgsmål har en tendens til at få mere opmærksomhed end lange/komplekse. Det er ikke fordi vi ikke kan svare, men med så mange spørgsmål og så lidt frivillig tid at give, er det svært at retfærdiggøre tiden til at læse store spørgsmål.
Jeg tror dog, at dit grundlæggende krav ikke er så kompliceret. Du vil have en måde at hente rækker, der falder inden for et tidsinterval, ELLER, hvis de ikke er inden for det interval, angive de nærmeste rækker til dette interval.
I databaser, der understøtter ROW_NUMBER() OVER() er dette ret nemt (og MySQL 8.x er planlagt til at understøtte dette), men indtil det tidspunkt for at efterligne row_number() kan du bruge variabler og en ordnet underforespørgsel.
Du kan prøve denne løsning her på SQL Fiddle
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);
Forespørgsel :
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)
Så hvad dette gør, er at beregne et "RowNumber", som starter ved 1 for den seneste række for hver kildetabel. Derefter filtreres denne afledte tabel enten efter tidsintervallet eller efter rækkenummeret, hvis det ikke er inden for tidsintervallet.
Bemærk også, at jeg IKKE har brugt UNION
men har i stedet brugt UNION ALL
. Der er stor forskel på ydeevne og bør lære at bruge hver efter behov. Hvis du bruger UNION
brug ikke også select distinct
fordi du bare spilder kræfter.
| 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 |