Pertanyaan pendek dan sederhana cenderung mendapat perhatian lebih daripada pertanyaan panjang/kompleks. Ini bukan karena kami tidak dapat menjawab tetapi dengan begitu banyak pertanyaan, dan begitu sedikit waktu sukarela yang diberikan, sulit untuk membenarkan waktu untuk membaca pertanyaan-pertanyaan besar.
Namun saya pikir kebutuhan dasar Anda tidak terlalu rumit. Anda menginginkan cara untuk mengambil baris yang berada dalam rentang waktu ATAU jika tidak dalam rentang tersebut, berikan baris terdekat dengan rentang tersebut.
Dalam database yang mendukung ROW_NUMBER() OVER() ini cukup mudah (dan MySQL 8.x direncanakan untuk mendukung ini), tetapi sampai saat itu untuk meniru row_number() Anda dapat menggunakan variabel dan subquery yang dipesan.
Anda dapat mencoba solusi ini di SQL Fiddle
Pengaturan Skema 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);
Kueri :
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)
Jadi, yang dilakukan adalah menghitung "RowNumber" yang dimulai dari 1 untuk baris terbaru untuk setiap tabel sumber. Kemudian tabel turunan ini difilter menurut rentang waktu, atau menurut nomor baris jika tidak berada dalam rentang waktu tersebut.
Perhatikan juga bahwa saya TIDAK menggunakan UNION
tetapi sebaliknya telah menggunakan UNION ALL
. Ada perbedaan besar dalam kinerja dan harus belajar menggunakan masing-masing sesuai kebutuhan. Jika menggunakan UNION
jangan juga menggunakan select distinct
karena Anda hanya membuang-buang usaha.
Hasil :
| 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 |