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

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

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

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

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Q&A

解決済

9回答

7420閲覧

SQLが重いのを改修したい

T.Yokotani

総合スコア141

MySQL

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

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

2グッド

2クリップ

投稿2016/03/14 10:35

編集2016/03/14 13:50

現在oracle+PHPで作られたプログラムの改修を行っています。
その内容が、oracleからMySQLへのDBの変更といった内容なのですが、そこで問題になったのがoracle独自の関数を用いて作られたSQLです。
今、問題なっているのが、

sql

1select * from ( 2 select t1.TENPO_CD as TENPO_CD, 3 t1.TODOFUKEN_CD as TODOFUKEN_CD, 4 t1.DATE as DATE, 5 t1.KBN as KBN, 6 t1.TANKA as TANKA, 7 trim(format(t1.RESULT,0)) as RESULT, 8 t1.XX_CD as XX_CD, 9 t1.XX_NAME as XX_NAME, 10 t1.XX_NO as XX_NO, 11 (select count(*) +1 from XXtable as t2 where 1 and CAST(CAST(t2.RESULT as UNSIGNED) as SIGNED) > CAST(CAST(t1.RESULT as UNSIGNED) as SIGNED) and concat(t2.KBN,t2.TANKA)= concat(t1.KBN,t1.TANKA)) as rank 12 from XXtable as t1 13 where TODOFUKEN_CD = '23' 14 and DATE like '2016-03-12%' 15 and DEL_FLG = 0 16 order byKBN asc,TANKA desc) as A1 17where rank <= 20; 18

といったSQLです。
もともとはoracleのrow_numberを使って記載されていたものをMySQLに対応させてみました。
ラッピングしている中身だけであれば1秒かからず処理ができるのですが、

where rank <= 20;

の部分を対応させると30秒近くかかってしまいます。
もともとデータをほぼ全読みするものであるため、インデックスなども付けられず、件数はテストデータでは8000件程度です。
本番ではこの7倍が想定されていますので、到底耐えうるものではなくなってしまいました。
何か高速化する手段はないものでしょうか?

MySQLのバージョン(5.1.73)

t.kawaji👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2016/03/15 00:01

テーブル定義について、質問です。 RESULTの型が、不明です。 format(t1.RESULT,0) を使っているので、小数点があると思いましたが、 CAST(CAST(t2.RESULT as UNSIGNED) as SIGNED) と CASTしているので どんな値が、入っているのか気になります。
T.Yokotani

2016/03/15 01:30

カラムの定義はchar型です。 ただし、中身は符号付数値です。
guest

回答9

0

2016/03/15 15:08に退会済みユーザが投稿してる
ユーザ変数を使う方法ですが

OracleACEのAketiJyuuzouさんとyoku0825さんと
日本オラクルの木村明治さんによると
MySQLのユーザ変数は評価順序が未定義です。
http://qiita.com/AketiJyuuzou/items/cced9b70cc714b382d98

なので、結果が保証されませんので、
納品物件などでは、問題外の品質です。

投稿2016/04/22 06:08

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

興味深く参照させていただきました。

XXtableの1レコードに対して、
XXtableを全読みした場合のオーダーはn*n

ただ、
XXtableの全読みに対して、インデックスが利けば
実質nで済むので、
インデックスが利くようなSQL文を検討してみてはどうでしょうか?

OracleのRow_Numberだと
クイックソートでも使ってるでしょうから
n*log(n)なんでしょうね。

せめて、MySQLで

SQL

1select colA 2from XXtable a 3where (select count(*) 4 from (select 1 from XXtable b 5 where b.colA=a.colA --順位を決める条件 6 Limit 21) as TmpV ) <= 20;

と書ければいいのですが、
サブクエリの2段ネストでは、aはスコープ外になるので不可のようです。

投稿2016/03/15 06:16

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

T.Yokotani

2016/03/15 08:33

回答ありがとうございます。 おっしゃられている通りでした。 プログラムのスコープと扱いが違うので、なかなか難しいですね。。。
guest

0

MySQLのOffSetを忘れてました。
MySQLでもこれなら通りますね。

SQL

1select colA 2from XXtable a 3where not exists(select 1 from XXtable b 4 where b.colA> a.colA --順位を決める条件 5 OffSet 19 Limit 1) 6

ということで、
1位から20位を取りたいのですから
21位以降は正確な順位は不要ということをふまえて
LimitとOffSetを使ってみました。

サブクエリでCountStopかかるので、
多少は早くなるはずです。

SQL

1select t1.TENPO_CD as TENPO_CD, 2 t1.TODOFUKEN_CD as TODOFUKEN_CD, 3 t1.DATE as DATE, 4 t1.KBN as KBN, 5 t1.TANKA as TANKA, 6 trim(format(t1.RESULT,0)) as RESULT, 7 t1.XX_CD as XX_CD, 8 t1.XX_NAME as XX_NAME, 9 t1.XX_NO as XX_NO 10from XXtable as t1 11where TODOFUKEN_CD = '23' 12 and DATE like '2016-03-12%' 13 and DEL_FLG = 0 14 and not exists(select 1 from XXtable t2 15 where CAST(CAST(t2.RESULT as UNSIGNED) as SIGNED) 16 > CAST(CAST(t1.RESULT as UNSIGNED) as SIGNED) 17 and concat(t2.KBN,t2.TANKA)= concat(t1.KBN,t1.TANKA) 18 OffSet 19 Limit 1) 19order by KBN asc,TANKA desc;

投稿2016/03/16 01:45

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

T.Yokotani

2016/03/16 01:50

ご回答ありがとうございます! このような考え方もあるのですね。 落ち着いたら試してみます!
guest

0

テーブルCREATE

sql

1CREATE TABLE XXtable ( 2 id MEDIUMINT NOT NULL AUTO_INCREMENT, 3 TENPO_CD int(10), 4 TODOFUKEN_CD int(10), 5 DATE DATETIME, 6 KBN CHAR(3), 7 TANKA int(10), 8 RESULT CHAR(10), 9 XX_CD int(10), 10 XX_NAME CHAR(12), 11 XX_NO int(10), 12 DEL_FLG tinyint(1), 13 PRIMARY KEY (id) 14)

テストデータ作成

python

1# coding:utf-8 2import random 3import time 4 5# 0~100の乱数を生成 6def randomAge(): 7 return random.randint(0, 100) 8 9def randomTempo(): 10 return random.randint(100, 999) 11 12def randomTodou(): 13 return random.randint(1, 47) 14 15def randomTanka(): 16 return random.randint(500, 2000) / 100 * 500 17 18# startからendの間でランダムな日付生成 19def randomDate(start, end): 20 format = '%Y-%m-%d %H:%M:%S' 21 stime = time.mktime(time.strptime(start, format)) 22 etime = time.mktime(time.strptime(end, format)) 23 ptime = stime + random.random() * (etime - stime) 24 return time.strftime(format, time.localtime(ptime)) 25 26# 出力するファイル名 27OUTPUT_FILE = "TestData.sql" 28 29# 登録するデータ件数 30RECORD_COUNT = 8000 31 32# 実行するSQLコマンド文字列 33sqlCommands = "" 34 35# 使用するデータベースを指定(今回はCreateTestData) 36sqlCommands += "USE goods;\n" 37 38# 登録するデータの数だけINSERT文を生成 39for _ in range(RECORD_COUNT): 40 41 # 登録するランダムなデータの生成 42 date = randomDate("2015-12-12 00:00:00", "2015-12-20 00:00:00") 43 result = str(randomAge()) + '.' + str(randomAge()) 44 45 tenpo = randomTempo() / 100 * 10 46 tdou = randomTodou() 47 kbn = randomTempo() / 100 * 10 48 tanka = randomTanka() 49 50 # ランダムなデータからInsert文を生成 51 sqlCommands += "INSERT INTO XXtable" \ 52 "(TENPO_CD, TODOFUKEN_CD, DATE, KBN, TANKA, RESULT, DEL_FLG) " \ 53 "VALUES ('{}', '{}', '{}', '{}', '{}', '{}', 0);\n"\ 54 .format(tenpo, tdou, date, kbn, tanka, result) 55 56# 生成したSQLコマンドをファイルに書き出す 57f = open(OUTPUT_FILE, 'w') 58f.write(sqlCommands) 59f.close()

追加のSQL

SQL

1-- KBN 昇順 TANKA 降順 のインデックス 2alter table XXtable ADD KBN_TANKA int; 3update XXtable set KBN_TANKA = KBN * 10000000 + ( 10000000 - TANKA); 4 5-- RESULT 降順 のインデックス 6alter table XXtable ADD RESULT_SORT int; 7update XXtable set RESULT_SORT = 10000000 - RESULT * 1000; 8 9-- RESULT KBN TANKA 10 create index index_kbntankaresult_sort on XXtable (KBN_TANKA, RESULT_SORT);

MySQLのインデックスは、降順が出来ず、指定しても無視され昇順で、格納されるので、
降順で並ぶように細工が必要になります。

区分、TANKA 毎のランキング 上位20位抽出SQL

SQL

1select * from 2 ( select 3 *, 4 @kbn_rank := IF(@current_kbn = KBN_TANKA, @kbn_rank + 1, 1) AS kbn_rank, 5 @current_kbn := KBN_TANKA 6 from (SELECT @kbn_rank := -1) s, 7        (SELECT @current_kbn := -1) c, 8        XXtable 9 order by KBN_TANKA, RESULT_SORT 10 ) ranked 11where 12 kbn_rank <= 20 13 and TODOFUKEN_CD = '23' 14 and DATE >= '2015-12-17' and DATE < '2015-12-18' 15 and DEL_FLG = 0 ;

投稿2016/03/15 06:08

編集2016/03/15 06:35
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2016/03/15 06:20

マニュアルに https://dev.mysql.com/doc/refman/5.6/ja/user-variables.html >ただし、ユーザー変数を含む式の評価の順序は、定義されていません。 とあるので 区分、TANKA 毎のランキング 上位20位を抽出できることは、 保証されないのではないでしょうか?
退会済みユーザー

退会済みユーザー

2016/03/15 07:05

https://dev.mysql.com/doc/refman/5.6/ja/user-variables.html マニュアルに >1つのステートメントで複数回のユーザ変数を使った場合の >評価順序が保証されない。 とあります。 いいかえれば OrderBy句のソート順かつ、Select句の左から右に ユーザ変数が評価されることが保証されてませんので、 インラインビューを増やして、-1で初期化しても 結果は保証されないと思います。 (たいていは、期待した結果になるようですが)
退会済みユーザー

退会済みユーザー

2016/03/15 07:41

まっやって見て できてれば OK.  何を 心配しているのか、 まったく 私には、大学も出ていない、高校も出ていないので わかりません。ただし、プログラムに関しては、マニュアルを読まずにソースを見て 動いているものを見て覚えています。 マニュアルを見て、理解して プログラム出来る人は、天才だと思います。 IBMのスパーコンピュータのドキュメントすべて記憶している人の月収は、300万とか聞きました。脱線しましたが、指摘の内容がわかりません。
T.Yokotani

2016/03/15 08:37

terion様の例題を参考に高速化することができました。 ただ、グループ化したランキングごとに20位までという点についてはどうしてもうまくいかないようでしたので、その部分はプログラムにて対応することにいたしました。 長時間お力添えいただきましてありがとうございました。
退会済みユーザー

退会済みユーザー

2016/04/04 08:22

(退会済みユーザその1)さんが御指摘されてる MySQLユーザ定義変数の評価順序については、 OracleACEのAketiJyuuzouさんとyoku0825さん が分かりやすくかかれてますね。 http://qiita.com/AketiJyuuzou/items/cced9b70cc714b382d98 (退会済みユーザその2)さんは、御一読されてみてはどうでしょう?
guest

0

terionさんの指摘も組み込んで、まとめてみました。
下記いかがでしょうか?

mysql

1 select t1.TENPO_CD as TENPO_CD, 2 t1.TODOFUKEN_CD as TODOFUKEN_CD, 3 t1.DATE as DATE, 4 t1.KBN as KBN, 5 t1.TANKA as TANKA, 6 trim(format(t1.RESULT,0)) as RESULT, 7 t1.XX_CD as XX_CD, 8 t1.XX_NAME as XX_NAME, 9 t1.XX_NO as XX_NO, 10 (select count(t2.TEMPO_CD) +1 --count(*)より、主キーやNOT NULLのインデックスのはられた列をcountした方が高速です。 11 from 12 XXtable as t2 13 where 14 1 15 and CAST(CAST(t2.RESULT as UNSIGNED) as SIGNED) > CAST(CAST(t1.RESULT as UNSIGNED) as SIGNED) --ここでやりたいことってどういうことなんでしょうか?冗長な匂いがします。 16 and concat(t2.KBN,t2.TANKA)= concat(t1.KBN,t1.TANKA)) as rank 17 from XXtable as t1 18 where TODOFUKEN_CD = '23' 19 and DATE >= '2016-03-12' and DATE < '2016-03-13' 20 and rank <= 20 --rankを内側に入れ、ネストを1つ減らしました。 21 and DEL_FLG = 0 --絞り込みに使いにくい条件はWhereの外側に、絞り込める条件を内側に書いた方が早くなる場合あります。 22 order byKBN asc,TANKA desc) as A1

投稿2016/03/14 15:52

Odacchi

総合スコア907

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

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

T.Yokotani

2016/03/15 01:37

非常に丁寧な回答ありがとうございます。 rankに関しては私も内部でやってみたのですが、Unknown columnになってしまいます。 どうも条件には使えないようです。 また、countをキー項目で行うことも試してみたのですが、微々たる変化しかありませんでした。 分割してプログラムに一部機能を移植しようかと思いだしています。
Odacchi

2016/03/15 02:01

実際に動作させることができないこともあり、動かない解答を送ってしまいすみません。 問題の本質は、8000件のcountを8000件のデータに対して毎回行っていることによって、 8000*8000回(O(n^2))、つまりレコード件数の2乗に比例する時間がかかっていることだと思います。 ですので、下記の1番ネストが深い部分が何をしたいのかが分かれば、要件を満たす別のSQLを考えるなどもできるかもしれません。 ヒントになれば幸いです。 select count(t2.TEMPO_CD) +1 from XXtable as t2 where 1 and CAST(CAST(t2.RESULT as UNSIGNED) as SIGNED) > CAST(CAST(t1.RESULT as UNSIGNED) as SIGNED) --ここでやりたいことってどういうことなんでしょうか?冗長な匂いがします。 and concat(t2.KBN,t2.TANKA)= concat(t1.KBN,t1.TANKA)) as rank
T.Yokotani

2016/03/15 05:42

冗長ではないかという部分の意味ですが、そちらの項目は符号付数値が文字列として入っております。 そのため、unsignののち、signで定義しないと数値型として変換できなかったという経緯があります。 数値にしてから比較をしないとランキングがうまく出せなかったためです。 区分と単価毎にグループ化して、結果でソートしてグループ内のランキングを出すというものです。 この事故結合のところがやはり問題ですよね。。。。 結果1行に対して必ず1回SQLで全読みしてしまうというものなので、どうしても時間がかかりますよね。。。。 データベースの変更がこんなに大変だとは思っていませんでした。 SQLを少し変えればいいんだと思っていましたので、反省しております^^;
Odacchi

2016/03/15 06:03

なるほどです。 このSQLは画面表示時などに毎回流すものでしょうか? そうであれば、リアルタイム性は損なわれますが、 [XXtable]に[RANK]というカラムを追加し、 定期的にバッチでUPDATEかけるようにしてみてはいかがでしょうか?
T.Yokotani

2016/03/15 10:26

こちら画面表示プログラムになります。 1画面で複数のランキングを一度に表示する機能であるため、グループごとのランキングが必要になっております。 ランクカラムについてなのですが、色々な条件で抽出をかけるため、抽出条件ごとに順位が変わるため、それもできなかったのです。。。 色々とご指導いただき、本当にありがとうございます。
guest

0

グループ毎の上位20件を抽出するってことですよね?
難しいですね。
所で、サブクエリだけなら1秒で終わるんですか?count(*)の要素まで含めても?
それならソートをサブクエリの外に移したらどうでしょう?
サブクエリ内でソートしたものを、外側でrankで絞り込むためにまた、rankでソートしたりしてるんじゃないかなと思ったり。
※後、外にwhereを置いたSQLだとサブクエリ内のソートは無意味だったような気がします。(うろ覚え)

投稿2016/03/14 12:02

編集2016/03/14 12:02
hirohiro

総合スコア2068

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

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

T.Yokotani

2016/03/14 12:11

ご回答ありがとうございます。 サブクエリだけですと、count(*)を含めても1秒以内でした。(8000件でですが) ソートを外で行ってみましたが、変化はありませんでした。
hirohiro

2016/03/14 12:23 編集

そうですか、お役に立てず申し訳ない。 後、これも有効かどうか不明ですが、countではなくexistsではどうでしょう? and EXISTS ( SELECT * FROM ( SELECT RESULT FROM XXtable WHERE KBN = t1.KBN AND TANKA = t1.TANAKA LIMIT 20 ) t2 WHERE trim(format(t1.RESULT,0)) >= trim(format(t2.RESULT,0)) ) サブクエリ部分だけにして、countの部分を消し、絞込み条件に追加のつもりです。 自分のRESULTより大きな値がグループの上位20件に存在すれば..的な条件です。 ※コード検証していません。サブクエリのLIMITはmysqlのバージョンで縛りがあったかも mysqlのオプティマイザに過大な期待かもしれませんが、 サブサブクエリがグループ数分だけですむことに気づいてくれればひょっとして...
T.Yokotani

2016/03/14 12:52

何度もありがとうございます。 上記試してみましたが、t1のスコープが届きませんでした。。。。
hirohiro

2016/03/14 14:15 編集

そうか、なるほど、そうですね。 ちょっとこの方面で進めていっても私に動作確認環境がないのと、遅い根本原因とずれている感じがしてきましたのでやめておこうと思います。すみません。 私もlilithchanさんが書かれているように8000件分の相関サブクエリでのcount集計が遅いのだと思っていましたが、(一秒が十分な速度かという問題はありますが)その点に問題がなかったのなら、Odacchiさんの方法でうまくいきそうな気がします。
T.Yokotani

2016/03/15 01:39

色々教えていただきましてありがとうございました。 プログラム側に一部移植しつつ対応する方向にしていこうかと考え出しています。
guest

0

ベストアンサー

MySQL でrankを出すとき
変数を使用すると、早くなります。
http://stackoverflow.com/questions/11084668/finding-rank-of-student-in-table

追記1
日付はLIKE検索してはいけません。
LIKE検索の場合はインデックスが使用されずフルテーブルスキャンが走ってしまいます。

SQL

1 SELECT * FROM test WHERE c2 >= '2014-01-02' AND c2 < '2014-01-03';

投稿2016/03/14 11:07

編集2016/03/14 11:24
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

T.Yokotani

2016/03/14 11:11

回答ありがとうざいます。 変数については不勉強で、まだ使ったことがありませんでした。 少し調べてみます。
退会済みユーザー

退会済みユーザー

2016/03/14 11:25

LIKE問題がクリアになったので、インデックス出来るんじゃないかな?
T.Yokotani

2016/03/14 11:42

上記ありがとうございます。 LIKEは確かにおかしいですね。。。以前のSQLのゴミでした。。。 こちらのインデックスに関しても対応してみましたが、あまり変わらずでした。 どうしても事故結合している部分をwhere句に入れると遅くなってしまいます。 変数に関してもcount(*)の部分に適用してみたのですが、グループが変わったときに初期化されず、データとしてNGになってしまいました。
退会済みユーザー

退会済みユーザー

2016/03/15 00:08

concat(t2.KBN,t2.TANKA)= concat(t1.KBN,t1.TANKA)) のぶぶん、 ちょっと、文字数減らすために、やっているのが 逆に遅くなっていますね。 これもインデックスを使えなくしている要素です。 (( t2.KBN = t1.KBN ) AND ( t2.TANKA= t1.TANKA)) と書けば インデックスが効くと思います。 この部分で、結合しているので、結合しないように出来きる方法があるか、検討が必要かも、
退会済みユーザー

退会済みユーザー

2016/03/15 01:06

わかった。 参考サイト http://qiita.com/hmuronaka/items/1afc132ddf400363efc count でランキングを自分もやってたけど、300秒かかってしまい。 @変数のranking にしたら、0.025 秒になったことがあります。 まさに、上記のサイトの書かれいることです。
退会済みユーザー

退会済みユーザー

2016/03/15 02:28

ユーザ変数で、row_numberなどの代用はよく見かけますが マニュアルに https://dev.mysql.com/doc/refman/5.6/ja/user-variables.html >ただし、ユーザー変数を含む式の評価の順序は、定義されていません。 とあり、MySQLのユーザ変数は、 OrderBy句のソート順で、なおかつ、Select句の左から右に評価することを 保証していないため。 MySQLのユーザ変数でのRankの代用は、結果も保証されないと思います。 (たいていは、期待した結果になるようですが)
T.Yokotani

2016/03/15 05:45

terion様 実例ありがとうございます。qiitaの方はnot foundになってしまい拝見できませんでしたが、stackoverflowの方は確認いたしました。まさにやりたいのはこれなのですが、変数の使い方が想像以上に難しく。。。。勉強いたします! HibinoMeguru様 回答ありがとうございます。 そちらも読ませていただきました。MySQLとOracleでこんな違いがあるとは思いませんでした。。。
退会済みユーザー

退会済みユーザー

2018/09/16 06:46

期待通りの結果を得られるかもしれませんが、それが確約されないSQLで、 仕事では使いものになりませんので、マイナス投票します。 http://download.nust.na/pub6/mysql/doc/refman/5.1/ja/user-variables.html >基本的なルールは、ステートメントの一部でユーザ変数値を割り当てないこと >および同一ステートメント内の他部分で同じ変数を使用しないことです。 >期待通りの結果を得られるかもしれませんが、これは確約されていません。
guest

0

深く読み込んだわけではないですが、下記のように外側のSelect句はいらないように思いますが、いかがでしょうか?

mysql

1select t1.TENPO_CD as TENPO_CD, 2 t1.TODOFUKEN_CD as TODOFUKEN_CD, 3 t1.DATE as DATE, 4 t1.KBN as KBN, 5 t1.TANKA as TANKA, 6 trim(format(t1.RESULT,0)) as RESULT, 7 t1.XX_CD as XX_CD, 8 t1.XX_NAME as XX_NAME, 9 t1.XX_NO as XX_NO, 10 (select count(*) +1 from XXtable as t2 where 1 and CAST(CAST(t2.RESULT as UNSIGNED) as SIGNED) > CAST(CAST(t1.RESULT as UNSIGNED) as SIGNED) and concat(t2.KBN,t2.TANKA)= concat(t1.KBN,t1.TANKA) ) as rank 11 from XXtable as t1 12 where TODOFUKEN_CD = '23' 13 and DATE like '2016-03-12%' 14 and DEL_FLG = 0 15 and rank <= 20 16 order by KBN asc,TANKA desc

投稿2016/03/14 10:55

編集2016/03/14 15:03
Odacchi

総合スコア907

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

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

T.Yokotani

2016/03/14 11:07

返答ありがとうございました。 試してみたのですが、なぜか1件になってしまいました。。。
Odacchi

2016/03/14 15:23 編集

ソースコードを修正しました。 rank <= 20の箇所を変えてます。 これで単純にスピードアップしませんか?
guest

0

ORDER BYした結果を副問い合わせしてLIMITで件数を絞ればいいのではないでしょうか。

http://www.dbonline.jp/mysql/select/index12.html

たぶん、row_numberを改変した質問文のやり方ですと、8000件分のSELECT COUNT(*)が走ると思うので激重だと思います。

投稿2016/03/14 10:52

lilithchan

総合スコア249

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

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

T.Yokotani

2016/03/14 11:08

回答ありがとうございます。 グループごとにランキングを付けているので、LIMITが使えないのです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問