0

次の設定で、3 つのテーブルがあります。

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、固体の 3 つの値は、以下のサンプルに従って、互いに数秒間隔で更新されます。

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 行のテスト データを含む 3 つのテーブルをセットアップしました。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

これを多数の行を持つテーブルで効率的に機能させるには、3 つの入力テーブルのそれぞれの時間列に UNIQUE INDEX を設定する必要があります。さらに良いことに、auto_increment ID の生成以外に ID 列が本当に必要ない場合は、時間列を PRIMARY KEY にすることもできます。

于 2013-03-29T11:30:01.430 に答える