Những câu hỏi ngắn và đơn giản có xu hướng thu hút nhiều sự chú ý hơn những câu dài / phức tạp. Điều này không phải vì chúng tôi không thể trả lời mà là do có quá nhiều câu hỏi và quá ít thời gian dành cho tình nguyện viên, thật khó để có đủ thời gian để đọc những câu hỏi lớn.
Tuy nhiên, tôi nghĩ rằng yêu cầu cơ bản của bạn không quá phức tạp. Bạn muốn một cách để truy xuất các hàng nằm trong phạm vi thời gian HOẶC nếu không nằm trong phạm vi đó, hãy cung cấp các hàng gần nhất với phạm vi đó.
Trong cơ sở dữ liệu hỗ trợ ROW_NUMBER () OVER () điều này khá dễ dàng (và MySQL 8.x được lên kế hoạch hỗ trợ điều này), nhưng cho đến thời điểm đó để mô phỏng row_number (), bạn có thể sử dụng các biến và một truy vấn con có thứ tự.
Bạn có thể dùng thử giải pháp này tại đây SQL Fiddle
Thiết lập lược đồ 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);
Truy vấn :
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)
Vì vậy, những gì điều này làm là tính toán một "RowNumber" bắt đầu từ 1 cho hàng gần đây nhất cho mỗi bảng nguồn. Sau đó, bảng dẫn xuất này được lọc theo phạm vi thời gian hoặc theo số hàng nếu không nằm trong phạm vi thời gian.
Cũng xin lưu ý rằng tôi đã KHÔNG sử dụng UNION
nhưng thay vào đó đã sử dụng UNION ALL
. Có sự khác biệt lớn về hiệu suất và nên học cách sử dụng từng loại tùy theo nhu cầu. Nếu sử dụng UNION
cũng không sử dụng select distinct
bởi vì bạn chỉ đang lãng phí nỗ lực.
Kết quả :
| 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 |