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

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

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

INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

MySQL

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

SQL

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

Hive

Hiveとは、Hadoop(オープンソースの大規模分散計算フレームワーク)の上で動作するDWH(Data Warehouse:データウエアハウス)向けのプロダクトです。HiveQLというSQLのような言語で、Hadoop上のデータを操作することができます。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

Q&A

解決済

5回答

1816閲覧

テーブル自体を簡略化したいです。

teiou104

総合スコア16

INSERT

INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

MySQL

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

SQL

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

Hive

Hiveとは、Hadoop(オープンソースの大規模分散計算フレームワーク)の上で動作するDWH(Data Warehouse:データウエアハウス)向けのプロダクトです。HiveQLというSQLのような言語で、Hadoop上のデータを操作することができます。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

0グッド

0クリップ

投稿2016/08/15 15:01

編集2016/09/19 14:18

sqlはdmlができるくらいのレベルです。ほぼ初心者レベルです。
Hive,バージョン1.0.0
すべてを記載すると長くて読みづらいので割愛しています。

以下のようなinsert文が96あります。
15分おきのデータで1日分ありテーブルにinsertを96回行わないといかず日付データを入れ替えるだけで面倒だしミスもしやすいし時間がかかります。
insertを96回せずに1回で終わる方法はないでしょうか?
CASE文とか使えば上手くいきそうな気がしますが、良い案が思いつきません。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2016/08/16 07:52

mysqlなのかpostgresqlなのかそれともoracleなのか、RDBMSについても示していただければより適切なドキュメントへの誘導が出来そうです。
guest

回答5

0

ベストアンサー

ボトルネックは15分おきの最小時刻を決定するデータが副問い合わせで表現されている点につきます。
つまり、日付と最小時分秒(その他一意化に非必要な項目)のみを持つ介在補助テーブルを実在する
(副問い合わせでなく)とみなせるならば、INSERTコマンドは96個ではなく1個に集約できます。
よって、格段にスピードアップできます。
具体的には、時刻を15で割った項目(+一意化に非必要な項目)でGROUP BY して、最小時分秒を求めた仲介補助テーブルが存在し、仲介補助テーブルによる検索条件を満たすレコードのみからなる第二の仲介補助テーブルが存在すると仮定するならば、INSERTコマンドは96個ではなく1個に集約できます。
※済みませんん。mysqlは TEMPORARYテーブルを作成できます、HiVEでは等価な仲介補助テーブルのような
ものが利用できるかどうかは勉強不足でお答えできません。

投稿2016/08/31 18:29

km668

総合スコア65

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

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

teiou104

2016/09/05 13:31

返事おそくなりました。すいません。 一時テーブルは作れますよ。hiveも。 こちらこそ、不勉強ですいません。実はsql自体ほとんど知識がないのでご説明されている事がさっぱりわかりません・・・。
km668

2016/09/09 21:45

15分おきの対象を選択するデータを格納した第一の一時テーブルを CREATE TEMPORARY TABLE tmp.mod15 SELECT test1,test8,sp_date, SUBSTR(test_time - (test_time % 1500), 1 ,4) AS sp_mod15 MIN(test_time) AS test_time_min FROM tmp.test77_tbl GROUP BY 1,2,3 ; を作っておいて,更に挿入値を選択した二の一時テーブルを CREATE TEMPORARY TABLE tmp.runtime SELECT test1,test8,sp_date, SUBSTR(test_time - (test_time % 1500), 1 ,4) AS test_time_mod, run_time, test2,..., test10 FROM tmp.test77_tbl T77 LEFT OUTER JOIN tmp.mod15 M15 ON M15.test1 = T77.test1 AND M15.test8 = T77.test8 AND M15.sp_date = T77.sp_date AND M15.sp_mod15 = SUBSTR(T77.test_time - (T77.test_time % 1500), 1 ,4) AND M15.test_time_min = T77.test_time ; で作成しておけば、あとは第二の一時テーブルから日付(sp_date)だけを 条件指定してINSERTするだけです。 論理を明確にするため、第二の一時テーブルを作成しましたが、 それせず、いきなり、INSERTするコマンドにしても構いません。
km668

2016/09/09 21:50

追伸 WHERE M15.test_time_min IS NOT NULLを第二の一時テーブル作成時に、あるいは、 INSERT 時に条件として追加しておいてきください。 (IS NOT NULL はM15にJOIN条件と一致するものがあると言う意味です ) また、T77とM15の両方にある項目は、T77.を付けて明示してください。
km668

2016/09/09 22:07

SQLをより簡潔にしました。 INSERT INTO ....  FROM tmp.test77_tbl AS T77,    (SELECT test1,test8,sp_date,        test_time - (test_time % 1500) AS sp_quoat        MIN(test_time) AS test_time_min      FROM tmp.test77_tbl GROUP BY 1,2,3) AS M15    WHERE M15.test1  = T77.test1      AND       M15.test8  = T77.test8      AND       M15.sp_date = T77.sp_date     AND       M15.test_time_min = T77.test_time AND       T77.sp_date = .... ;
km668

2016/09/09 22:15

10進法表記では10000(秒)は1500(秒)で割り切れないので若干訂正します。 INSERT INTO ....  FROM tmp.test77_tbl AS T77,    (SELECT test1,test8,sp_date, SUBSTR(test_time,1,2) AS sp_hour        (test_time % 10000)- ((test_time % 10000) %1500) AS sp_quoat        MIN(test_time) AS test_time_min      FROM tmp.test77_tbl GROUP BY 1,2,3,4) AS M15    WHERE M15.test1  = T77.test1      AND       M15.test8  = T77.test8      AND       M15.sp_date = T77.sp_date     AND       M15.test_time_min = T77.test_time AND       T77.sp_date = .... ;
teiou104

2016/09/10 02:07

コメントありがとうございます。 INSERT INTO ....  FROM tmp.test77_tbl AS T77,    (SELECT test1,test8,sp_date, SUBSTR(test_time,1,2) AS sp_hour        (test_time % 10000)- ((test_time % 10000) %1500) AS sp_quoat        MIN(test_time) AS test_time_min      FROM tmp.test77_tbl GROUP BY 1,2,3,4) AS M15    WHERE M15.test1  = T77.test1      AND       M15.test8  = T77.test8      AND       M15.sp_date = T77.sp_date     AND       M15.test_time_min = T77.test_time AND       T77.sp_date = .... WHERE M15.test_time_min IS NOT NULL ; すればいいって事ですかね? それならこれで来週試してみます。ありがとうございました!
km668

2016/09/10 04:43

そうです。 どうでもいいことですが、 FROM 表 AS T1,表 AS T2の場合は、INNER JOIN と等価な(書き直せる)ので、 暗黙に(自動的に)IS NOT NULL は満たされます。 従って、あっても害はなけれど必要とは言えません。
km668

2016/09/10 04:54

IS NOT NULL について更に余談。 FROM JOIN の記載によっては、要、不要が変化します。 たとえば、 FROM tmp.test_77 AS T77 RIGHT OUTER JOIN (SELECT..GROUP BY ..) AS M15 か FROM (SELECT .. GROUP BY..) M15 LEFT OUTER JOIN tmp.test_77 AS T77 でも 15分に1レコードしかレコードが生成されないので、IS NOT NULL 条件は不要。 ただし、記載順でインデックスが有効になるならないの微妙は差異が生ずることも あるかもしれないので、、、スピード重視なら複数通りの結果だけは等価な書き方を ためされてもいいかもしれません。
km668

2016/09/10 05:01

DIV演算子 X DIV n :== X - (X % n) を使えばより簡明ですが、おそらくSQL標準ではないので、、、 time DIV 10000, (time % 1000) DIV 1500
km668

2016/09/10 05:23

余談2.英大文字と英小文字の使い分け。 SQLはプログラム言語の中によく記載し、予約語がよく重複します。 私にの習慣ではSQLの予約語(CASE,IN,IF,ELSE,...)は英大文字で、プログラム言語の予約語は英小文字(case,in,if,else,...)で記載するようにしています。 目視やエディタで検索するとき区別しやすいためです。
teiou104

2016/09/19 14:18

上手くいきました。ありがとうございました
guest

0

INDEXを使えない場合、今回のSQLではどう頑張っても性能改善は難しいと思いますが。

一応、MySQL版のINDEX・SQLを紹介しますが、適宜Hiveに変換して試してくださいね。
※Hiveの場合、テーブル追加が必要かな。

SQL

1ALTER TABLE test77_tbl 2 ADD INDEX IX_test77_sp_date_1_8_time( sp_date, test1, test8, test_time, run_time ) 3; 4 5Select am02.test1, am02.test2, am02.test3, am02.test4, 6 am02.test5, am02.test6, am02.test7, am02.test8, 7 am02.test9, am02.test10,am02.test_time 8 , ( 9 Select avg(am01.run_time) 10 From test77_tbl am01 11 Where am01.sp_date = am02.sp_date 12 And am01.test1 = am02.test1 13 And am01.test8 = am02.test8 14 And Substr( am01.test_time, 1, 4 ) between '0000' and '0014' -- (3) 15 ) as run_time 16 , ( 17 Select count( 'X' ) 18 From test77_tbl am01 19 Where am01.sp_date = am02.sp_date 20 And am01.test1 = am02.test1 21 And am01.test8 = am02.test8 22 And Substr( am01.test_time, 1, 4 ) between '0000' and '0014' -- (3) 23 ) as test13 24 , am02.test14, '0000' -- (1) 25From test77_tbl am02 26Where am02.sp_date = '20160801' -- (2)(4) 27 And am02.test_time = ( 28 Select min( T1.test_time ) 29 From test77_tbl T1 30 Where T1.sp_date = am02.sp_date 31 And T1.test1 = am02.test1 32 And T1.test8 = am02.test8 33 And Substr( T1.test_time, 1, 4 ) between '0000' and '0014' -- (5) 34 ) 35; 36

投稿2016/08/25 23:46

編集2016/08/26 00:26
tomari_perform

総合スコア760

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

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

退会済みユーザー

退会済みユーザー

2016/08/25 23:58

KVSなのでは?
tomari_perform

2016/08/26 00:26

はい、Hive=KVSかと思います。 一部、誤解を与える表現だったので、修正しました。
teiou104

2016/08/28 13:04

テーブル追加も必要なんでしょうかね。 なんかエラーがでてしまいました。 INDEXはバージョンによっては使えるようになってきるようですが、うまく動かない事のが多いのかもしれません。
guest

0

SQL自体に関することではありませんが…
insert先のテーブルにインデックスや制約など付与されているなら
いったん解除してから insertしてみるのはどうでしょう。
(insert 後にまた付与します)

あと、参照されるテーブルの方に適切なインデックスは
はってあるか? ってのもちょっと気になります。

ただ、Hiveに関して上記が有効かどうかは
ちょっと確信が無いので、まあ、そういうことで。(^_^;

投稿2016/08/23 12:54

takasima20

総合スコア7458

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

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

teiou104

2016/08/23 13:02

回答ありがとうございます。 実はHiveにはIndexがないため、適切なパーティションを設定し、検索範囲の限定をしないといけないんです。
takasima20

2016/08/23 13:10

あー、そういうものでしたか~ 勉強になります。
guest

0

testやtmpといった文字が多くてなかなか頭に入ってこないSQLですね(^_^;

目的の動作をさせるために、あらかじめ以下のような時間幅のテーブルを用意しておいてはどうでしょうか。

[W_TIME_TBL] HM_F, HM_T ------------- 0000, 0014 0015, 0029 0030, 0044 ・・・ 2345, 2359 -------------

上記テーブルを利用したSQLは以下のようになると思います。

Insert Into Table test_tmp.Am_15min Partition (sp_yyyymmdd,sp_hhmm) Select am01.test1, am02.test2, am02.test3, am02.test4, am02.test5, am02.test6, am02.test7, am01.test8, am02.test9, am02.test10,am02.test_time, am01.run_time, am01.test13,am02.test14, am01.HM_F -- (1) From (select T1.TEST1 , T1.TEST8 , AVG(T1.RUN_TIME) as RUN_TIME_AVG , COUNT(T1.TEST8) as TEST13 , MIN(T1.TEST_TIME) as TEST_TIME_MIN , T2.HM_F from TMP.TEST77_TBL T1 , TMP.W_TIME_TBL T2 where T1.SP_DATE = '20160801' -- (2) and SUBSTR(T1.TEST_TIME, 1, 4) between T2.HM_F and T2.HM_T group by T1.TEST1 , T1.TEST8 , T2.HM_F ) am01 Left outer Join (select T1.* from TMP.TEST77_TBL T1 , TMP.W_TIME_TBL T2 where T1.SP_DATE = '20160801' -- (4) and SUBSTR(T1.TEST_TIME, 1, 4) between T2.HM_F and T2.HM_T ) am02 --(5) On (am01.test1 = am02.test1 And am01.test8 = am02.test8 And am01.test_time_min = am02.test_time)

SQL実行環境がないためそのままではエラー等あるかもしれませんが、参考になれば幸いです。

投稿2016/08/23 01:57

編集2016/08/23 02:02
jawa

総合スコア3013

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

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

teiou104

2016/08/23 12:24

ありがとうございます。 明日実際に試してみます。
teiou104

2016/08/24 13:18

試してみたら動いて流せましたが 最初に Warning: Map Join MAPJOIN[63][bigTable=t1] in task 'Stage-9:MAPRED' is a cross product Warning: Map Join MAPJOIN[64][bigTable=t1] in task 'Stage-4:MAPRED' is a cross product という警告が出てしまいました。
guest

0

人に読んでもらいたいなら、もうちょっとなんとかなりませんかと、さすがに思いますが、
以下の5カ所しか差がないSQL、日付以外は 15ずつ増えるだけという事でしょうか。

他の方法で思いつくのはストアドプロシージャでループですね。

sql

1Insert Into Table test_tmp.Am_15min Partition (sp_yyyymmdd,sp_hhmm) 2Select am01.test1, am02.test2, am02.test3, am02.test4, 3 am02.test5, am02.test6, am02.test7, am01.test8, 4 am02.test9, am02.test10,am02.test_time, am01.run_time, 5 am01.test13,am02.test14, '0000' -- (1) 6From 7 (Select test1,test8,avg(run_time) as run_time_avg,count(test8) as test13, 8 min(test_time) as test_time_min 9 From tmp.test77_tbl 10 Where sp_date='20160801' -- (2) 11 and Substr(test_time,1,4) between 0000 and 0014 Group by test1, test8) am01 --(3) 12 Left outer Join 13 (Select * from tmp.test77_tbl 14 where sp_date='20160801' -- (4) 15 and Substr(test_time,1,4) between 0000 and 0014) am02 --(5) 16 On (am01.test1 = am02.test1 And am01.test8 = am02.test8 17 And am01.test_time_min = am02.test_time);

(2個目)

sql

1Insert Into Table test_tmp.Am_15min Partition (sp_yyyymmdd,sp_hhmm) 2Select am01.test1, am02.test2, am02.test3, am02.test4, 3 am02.test5, am02.test6, am02.test7, am01.test8, 4 am02.test9, am02.test10,am02.test_time, am01.run_time, 5 am01.test13,am02.test14, '0015' 6From 7 (Select test1,test8,avg(run_time) as run_time_avg,count(test8) as test13, 8 min(test_time) as test_time_min 9 From tmp.test77_tbl 10 Where sp_date='20160801' 11 and Substr(test_time,1,4) between 0015 and 0029 Group by test1, test8) am01 12 Left outer Join 13 (Select * from tmp.test77_tbl 14 where sp_date='20160801' 15 and Substr(test_time,1,4) between 0015 and 0029) am02 16 On (am01.test1 = am02.test1 And am01.test8 = am02.test8 17 And am01.test_time_min = am02.test_time);

投稿2016/08/15 15:33

flied_onion

総合スコア2604

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

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

teiou104

2016/08/16 01:55

すいません、読みにくて。日付以外は15ずつ増えるだけです。
teiou104

2016/08/16 02:02

ストアドプロシージャでループって具体的にはどのように書けばいいのですか?
flied_onion

2016/08/16 02:53

それは調べてみてください。 2、3列の練習用のテーブルを使ってやってみるといいでしょう。 そもそも利用しているDBよって文法は少し変わってきます。 select文は普通より変わる部分が出てきますが、 insert文(insert 〜Select含む)を単体で実行するのはそれほど差はないはずなのでinsert文で練習してみると良いかと。 変数とWhileやFor、必要に応じて数値から文字への変換(これは普通のSQLでも使いますね)を組み合わせれば実現できるかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問