0

我有三个表,设置如下:

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

请问你能帮我查询吗?

4

3 回答 3

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);
于 2013-03-29T11:18:08.290 回答
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` ) ;

否则,查询不会终止。我相信处理这么多数据的查询不会。

于 2013-03-29T20:56:51.333 回答
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。

于 2013-03-29T11:30:01.430 回答