質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

解決済

1回答

2326閲覧

MySQLでの一定時間間隔でのデータ抽出について

shimotani1028

総合スコア5

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

1クリップ

投稿2022/06/06 07:26

sqlについて質問があります。
ひとつのテーブルに以下のような大量の時系列データがあります。時間は1分間隔のときもあれば5分間隔のときもありランダムです。

テーブル名:test01

計測時間データデータid
2022/06/06 0:00:001.0010
2022/06/06 0:01:001.0030
:::
2022/12/01 0:00:002.0050
2022/06/06 0:00:002.0011
2022/06/06 0:01:002.0031
:::
2022/12/01 0:00:001.0051
2022/06/06 0:00:003.0012
:::

このテーブルから一つのデータid(以下ではデータid=0)の1時間間隔で高速にデータを抽出しようとしており、いろいろ試しているのですが、
以下のコマンドを入力した場合に比較的速くデータが抽出できました。

mysql

1set @dt := '2022-06-05 23:00:00'; 2select(@dt := @dt + interval 1 hour) as time, データ, データid from test01 where 計測時間 = @dt + interval 1 hour and データid =0 and @dt<='2022-12-01 0:00:00';

sql結果

timeデータデータid
2022/06/06 0:00:001.0010
:::
2022/06/06 0:00:002.0050

しかし以下のようにデータがない期間をセットする場合にそこで検索が止まってしまい、それ以降の結果が得られませんでした。

mysql

1set @dt := '2022-06-05 22:00:00'; #←23:00:00から22:00:00に変更 2select(@dt := @dt + interval 1 hour) as time, データ, データid from test01 where 計測時間 = @dt + interval 1 hour and データid =0 and @dt<='2022-12-01 0:00:00';

sql結果

timeデータデータid

実際にはwhere句でマッチしない時間については、無視して出力してほしいのですが、もし改善案がありましたらご教授いただけませんでしょうか。

よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

information_schema.columnsを利用して範囲を指定して等間隔の表を入手し
元テーブルの方は生成列をつくってインデックスを貼っておいて処理すれば
効率的に集計できると思います

参考

2022-06-01 1時から10時まで1時間ごとのdatetime

SQL

1SELECT (select @a := @a + interval 1 hour from (select @a:='2022-06-01 0:00:00') as dummy) AS tm 2FROM information_schema.COLUMNS 3where @a<='2022-06-01 10:00:00'

テーブルのサンプル

SQL

1create table test01 2( 3cal_time datetime, # 計測時間 4data real, # データ 5data_id int, # データid 6cal_time2 varchar(20) as (cal_time - interval minute(cal_time) minute - interval second(cal_time) second), 7 index(cal_time2) 8); 9 10insert into test01(cal_time,data,data_id) values 11('2022-06-06 0:00:00',1.001,0), 12('2022-06-06 0:01:00',1.003,0), 13('2022-12-01 0:00:00',2.005,0), 14('2022-06-06 0:00:00',2.001,1), 15('2022-06-06 0:01:00',2.003,1), 16('2022-12-01 0:00:00',1.005,1), 17('2022-06-06 0:00:00',3.001,2), 18('2022-06-06 1:01:00',1.001,1), 19('2022-06-06 2:05:00',1.002,1), 20('2022-06-06 2:10:00',1.003,2);

上記cal_time2が時間単位のデータになっているのでそれをキーに集計すればそこそこ効率的です

SQL

1select cal_time2,count(*) from test01 2group by cal_time2

投稿2022/06/06 07:37

編集2022/06/07 01:24
yambejp

総合スコア117669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shimotani1028

2022/06/07 00:55 編集

回答ありがとうございます。 一度以下のように等間隔の表を作成して処理したのですが、30分くらいかかってしまって使い物になりませんでした。 インデックスは"データid"に貼っています。 1億行ほどあるので、それが普通なのか、そもそもmysqlにこういった処理が向いていないとかもあるんでしょうか。 ```mysql select time,データ from ( SELECT @dt := '2022-06-01 0:00:00' AS time UNION SELECT @dt := @dt + interval 1 hour FROM information_schema.COLUMNS WHERE @dt<='2022-12-01 0:00:00' ) as A left join (select * from test01 where データid= 0) B on A.time = B.計測時間; ```
yambejp

2022/06/06 07:56 編集

集計したいサンプルデータを提示ください (create table+insert形式で) 現状アバウトすぎてsampleが提示できません
shimotani1028

2022/06/06 08:01

もとがcsvをload dataしたものでして、少し時間ください。
yambejp

2022/06/06 08:07

あんまり大量のデータじゃないほうがいいと思います。 10~20レコードが目安ですかね
shimotani1028

2022/06/07 01:04 編集

初心者で時間がかかってしまい、申し訳ございません。 以下のコードでサンプルのテーブル(test01)が作成できると思います。 実際にはデータ数は数10万、データid数は500以上あります。 ```mysql drop table IF EXISTS test01; create table test01 ( cal_time datetime, # 計測時間 data real, # データ data_id int # データid ); DROP PROCEDURE IF EXISTS insert_data; delimiter // create procedure insert_data(in count int, in data_count int) begin declare i int; declare j int; set i = 0; set @time = '2022-05-01 00:00'; # 計測時間の開始時間 while i < count do # データ数のループ set j = 0; # データidの開始id while j < data_count do # データid数のループ set @data_val = rand(); # データ値(仮) set @query = concat('insert into test01 values("',@time,'",',@data_val,',',j,')'); prepare stmt from @query; execute stmt; set j = j + 1; end while; set i = i + 1; set @time = @time + interval 2 minute; # 今回は2分間隔でデータがあると仮定 end while; end // delimiter ; call insert_data(10,3); # 列の追加(引数=データ数,データid数) alter table test01 add index (data_id); select * from test01; ```
yambejp

2022/06/07 01:29 編集

初心者といいつつprocedureを使いこなすのはなかなか向上心がある方ですね 一応サンプルをつけてあります cal_time2のところが仮想生成列=virtual generated columnと呼ばれるカラムで インデックスを設定できるので効率的な処理ができます あとはどういう集計をしたいかによります たとえば最初に提示したinformation_schemaで作った定期的なデータに 集計データをサブクエリにしてleft joinしてやるとか・・・
shimotani1028

2022/06/07 02:34

サンプルありがとうございます。 仮想生成列を使う方法があるんですね。 この方法だと速く処理できそうです。 ただ、後出しになって申し訳ないのですが、実際には抽出する間隔は1時間の場合だけでなく、2分とか5分とか3時間とか、様々な間隔で抽出できることが要件でして、そうなるとその都度仮想列を生成するか、別の方法を考えるかしないといけないと思っております。
yambejp

2022/06/07 04:08

集計単位があるならその分だけ生成列が必要かもしれません もちろん計算結果を利用してgroup by も実行できるので実態に合わせて 生成列を作成するかどうかを個別に検討されるとよいでしょう
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問