我有三张桌子,设置如下:
Ph
ID
time (in the format: datetime)
Ph
Total suspended solids
ID
time (in the format: datetime)
solids
TEMPERATURE
ID
time (in the format: datetime)
temp
三个值,温度,pH值和固体值按照下面的样本相互更新几秒钟,
ID time temp
123335 2013-03-29 21:34:05 26.56
123336 2013-03-29 21:35:05 26.56
123337 2013-03-29 21:36:05 26.56
ID time solids
113886 2013-03-29 21:34:19 146
113887 2013-03-29 21:35:19 146
113888 2013-03-29 21:36:19 146
ID time Ph
62147 2013-03-29 21:34:04 7.39
62148 2013-03-29 21:35:04 7.43
62149 2013-03-29 21:36:04 7.43
我想查询mysql以获取下面的结果(注意我已经省略了表中的秒数)
time temp solids Ph
2013-03-29 21:34 26.56 146 7.39
2013-03-29 21:35 26.56 146 7.43
2013-03-29 21:36 26.56 146 7.43
请您帮我查询一下?
答案 0 :(得分:1)
可能有一个更有效的解决方案,但这样的事情应该有用......
DROP TABLE IF EXISTS ph;
CREATE TABLE Ph(time datetime PRIMARY KEY, Ph DECIMAL(5,2) NOT NULL);
DROP TABLE IF EXISTS tss;
CREATE TABLE tss(time datetime PRIMARY KEY,solids int NOT NULL);
DROP TABLE IF EXISTS temperature;
CREATE TABLE temperature(time datetime NOT NULL PRIMARY KEY,temp DECIMAL(5,2) NOT NULL);
INSERT INTO temperature VALUES
('2013-03-29 21:34:05',26.56),
('2013-03-29 21:35:05',26.56),
('2013-03-29 21:36:05',26.56);
INSERT INTO tss VALUES
('2013-03-29 21:34:19',146),
('2013-03-29 21:35:19',146),
('2013-03-29 21:36:19',146);
INSERT INTO ph VALUES
('2013-03-29 21:34:04',7.39),
('2013-03-29 21:35:04',7.43),
('2013-03-29 21:36:04',7.43);
SELECT *
FROM ph
JOIN tss
ON DATE_FORMAT(tss.time,'%Y%m%d%h%i') = DATE_FORMAT(ph.time,'%Y%m%d%h%i')
JOIN temperature t
ON DATE_FORMAT(t.time,'%Y%m%d%h%i') = DATE_FORMAT(ph.time,'%Y%m%d%h%i');
+---------------------+------+---------------------+--------+---------------------+-------+
| time | Ph | time | solids | time | temp |
+---------------------+------+---------------------+--------+---------------------+-------+
| 2013-03-29 21:34:04 | 7.39 | 2013-03-29 21:34:19 | 146 | 2013-03-29 21:34:05 | 26.56 |
| 2013-03-29 21:35:04 | 7.43 | 2013-03-29 21:35:19 | 146 | 2013-03-29 21:35:05 | 26.56 |
| 2013-03-29 21:36:04 | 7.43 | 2013-03-29 21:36:19 | 146 | 2013-03-29 21:36:05 | 26.56 |
+---------------------+------+---------------------+--------+---------------------+-------+
CREATE TABLE normalised AS
SELECT ph.time
, ph.ph
, tss.solids
, t.temp
FROM ph
JOIN tss
ON DATE_FORMAT(tss.time,'%Y%m%d%h%i') = DATE_FORMAT(ph.time,'%Y%m%d%h%i')
JOIN temperature t
ON DATE_FORMAT(t.time,'%Y%m%d%h%i') = DATE_FORMAT(ph.time,'%Y%m%d%h%i');
SELECT * FROM normalised;
+---------------------+------+--------+-------+
| time | ph | solids | temp |
+---------------------+------+--------+-------+
| 2013-03-29 21:34:04 | 7.39 | 146 | 26.56 |
| 2013-03-29 21:35:04 | 7.43 | 146 | 26.56 |
| 2013-03-29 21:36:04 | 7.43 | 146 | 26.56 |
+---------------------+------+--------+-------+
ALTER TABLE normalised ADD PRIMARY KEY(time);
答案 1 :(得分:1)
好的,查询优化器似乎在我之前使用大表的答案时遇到了一些问题。请尝试使用此解决方案,它适用于从属子查询:
SELECT DATE_FORMAT(timeTable.minuteTime, '%Y-%m-%d %k:%i') time,
T2.temp temp,
S2.solids solids,
P2.Ph Ph
FROM
(
SELECT minuteTime.minuteTime minuteTime,
( SELECT MAX(time) FROM temperature WHERE time <= minuteTime.minuteTime AND time >= NOW() - INTERVAL 1 HOUR) tempTime,
( SELECT MAX(time) FROM ph WHERE time <= minuteTime.minuteTime AND time >= NOW() - INTERVAL 1 HOUR) phTime,
( SELECT MAX(time) FROM solids WHERE time <= minuteTime.minuteTime AND time >= NOW() - INTERVAL 1 HOUR) solidsTime
FROM
(
SELECT time + INTERVAL 59 - SECOND( time ) SECOND minuteTime
FROM Ph
WHERE time >= NOW() - INTERVAL 1 HOUR AND time <= NOW()
UNION SELECT time + INTERVAL 59 - SECOND( time ) SECOND
FROM solids
WHERE time >= NOW() - INTERVAL 1 HOUR AND time <= NOW()
UNION SELECT time + INTERVAL 59 - SECOND( time ) SECOND
FROM temperature
WHERE time >= NOW() - INTERVAL 1 HOUR AND time <= NOW()
GROUP BY 1
) minuteTime
) timeTable
LEFT JOIN temperature T2 ON T2.time = timeTable.tempTime
LEFT JOIN solids S2 ON S2.time = timeTable.solidsTime
LEFT JOIN ph P2 ON P2.time = timeTable.phTime
ORDER BY minuteTime ASC
我已经设置了三个表,每个表有大约800'000行测试数据。在MySQL 5.5.30上,上面的查询在大约3.5秒内运行并返回61个结果行。但是你必须在每个时间列上都有索引:
ALTER TABLE `ph` ADD INDEX ( `time` ) ;
ALTER TABLE `solids` ADD INDEX ( `time` ) ;
ALTER TABLE `temperature` ADD INDEX ( `time` ) ;
否则,查询将不会终止。我相信没有处理此数据量的查询。
答案 2 :(得分:0)
我可能有一个无需创建临时表的解决方案:
SELECT DATE_FORMAT(timeTable.minuteTime, '%Y-%m-%d %k:%i') time,
T2.temp temp,
S2.solids solids,
P2.Ph Ph
FROM
(
SELECT MinuteTable.minuteTime minuteTime,
MAX(T.time) tempTime,
MAX(S.time) solidsTime,
MAX(P.time) phTime
FROM
(
SELECT time + INTERVAL 59 - SECOND( time ) SECOND minuteTime
FROM Ph
WHERE time >= NOW() - INTERVAL 1 HOUR
UNION SELECT time + INTERVAL 59 - SECOND( time ) SECOND
FROM solids
WHERE time >= NOW() - INTERVAL 1 HOUR
UNION SELECT time + INTERVAL 59 - SECOND( time ) SECOND
FROM temperature
WHERE time >= NOW() - INTERVAL 1 HOUR
GROUP BY 1
) MinuteTable
LEFT JOIN temperature T ON T.time <= MinuteTable.minuteTime
LEFT JOIN solids S ON S.time <= MinuteTable.minuteTime
LEFT JOIN ph P ON P.time <= MinuteTable.minuteTime
GROUP BY 1
) timeTable
LEFT JOIN temperature T2 ON T2.time = timeTable.tempTime
LEFT JOIN solids S2 ON S2.time = timeTable.solidsTime
LEFT JOIN ph P2 ON P2.time = timeTable.phTime
ORDER BY minuteTime ASC
为了使用大量行的表有效地工作,你肯定希望在三个输入表中的每一个的时间列上都有一个UNIQUE INDEX。更好的是,如果除了生成auto_increment ID之外你真的不需要ID列,你甚至可以将时间列设为PRIMARY KEY。