5ちゃんねる ★スマホ版★ ■掲示板に戻る■ 全部 1- 最新50  

■ このスレッドは過去ログ倉庫に格納されています

SQL質疑応答スレ 11問目

1 :NAME IS NULL:2011/03/05(土) 15:12:10.68 ID:c4C/uG2A
このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。

SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。

質問するときはDBMS名を必ず付記してください。

【質問テンプレ】
・DBMS名とバージョン
・テーブルデータ
・欲しい結果
・説明

前スレ:
SQL質疑応答スレ 10問目
http://hibari.2ch.net/test/read.cgi/db/1274791771/


937 :NAME IS NULL:2011/09/18(日) 18:52:45.40 ID:???
???

938 :NAME IS NULL:2011/09/18(日) 19:04:23.67 ID:???
テーブルに最終更新日時の列を追加しといて
トリガーで更新するとかしとかないと無理

939 :NAME IS NULL:2011/09/18(日) 19:04:50.16 ID:???
えっと・・・
id score1 score2 score3
--------------------------
1 10 10 10
2 20 10 10
3 30 10 10
このデータを
id3の人が2011-0906にWEB上で編集して
id2の人も2011-0905にWEB上で編集した。
id1の人がまったく更新していないとして・・・
id score1 score2 score3
--------------------------
3 30 10 10
2 20 10 10
1 10 10 10
こういう順番で出すようにしたいんですが 可能ですか?

940 :NAME IS NULL:2011/09/18(日) 19:11:32.94 ID:???
>>938
作らないとだめですか・・・わかりました。
ありがとうございます

941 :NAME IS NULL:2011/09/18(日) 23:24:36.64 ID:Zw+0oaRW
DBMS : Mysql

説明
データは10万件あると想定します。
挿入する際に一つのワードを二つのカラムに大して重複チェックを行いたいです。
どちらか片方にそのワードが含まれていたらcountで0を返す結果が欲しいです。

select count(*) from table where colA = 'ワード' OR colB = 'ワード'
これだと現在2秒程度かかるので高速化したいです。

よろしくお願いします。

942 :NAME IS NULL:2011/09/18(日) 23:30:16.39 ID:???
Union

943 :NAME IS NULL:2011/09/18(日) 23:41:22.00 ID:???
>>942
同じテーブル内にAとBがあります。
それでもUnionの使い方によっては早くなりますか?

944 :NAME IS NULL:2011/09/18(日) 23:42:48.18 ID:???
それはやってみて試すしかない。

945 :NAME IS NULL:2011/09/18(日) 23:44:18.13 ID:???
頻繁にinsertするならチェック用に別テーブル作るのが一番よさげだけど

946 :NAME IS NULL:2011/09/18(日) 23:57:58.66 ID:???
>>944
concatならまだわかりますけどUnionならどう使えばいいのでしょうか?
ちなみにconcatではあまり速度は変わりませんでした。

>>945
チェック用の別テーブルとはどのように構築すれば良いのでしょうか?
現在挿入されているものは全てユニークなものになっているので行数は減らないです。


947 :NAME IS NULL:2011/09/19(月) 00:01:00.54 ID:???
COLA と COLB のデータ両方がひとつのカラムに入ったテーブル。
OR を使わなくていいんで速い。

948 :NAME IS NULL:2011/09/19(月) 00:07:16.59 ID:???
select cola from table union select colb from table
が10万件より劇的に減るなら効果ありそうだけど、難しそうだな

949 :NAME IS NULL:2011/09/19(月) 00:16:35.65 ID:???
>>947
あー、なるほど。
件数的には19万程度になると思うので微妙だと思います。

ただ、ちょっと追加情報になってしまうのですが、AかBのどちらかがNULLになってることが多いです。
この場合何かいい方法ってありますか?

950 :NAME IS NULL:2011/09/19(月) 00:21:14.59 ID:???
ならやっぱり、cola、colbにそれぞれインデックスはってunionなのかな

951 :NAME IS NULL:2011/09/19(月) 00:21:18.73 ID:???
まず言われたことやれよハゲ

952 :NAME IS NULL:2011/09/19(月) 00:35:14.92 ID:4PlpFPwP
>>950
http://labs.unoh.net/2007/06/mysql5.html
ではこの当たりが参考になりそうなのでこれで少し検証してみます。
ありがとうございました。

953 :NAME IS NULL:2011/09/19(月) 00:44:38.24 ID:???
よろしくお願いします

MySQLでint型でstartとendというフィールドがあります。start < endとなっています。
n以上m以下の範囲が、テーブルのstart以上end以下の範囲と被ってるレコードを取り出す場合、
SELECT文の条件はどうなるのでしょうか?



954 :NAME IS NULL:2011/09/19(月) 01:03:29.11 ID:???
>>950
一応報告まで。
Deleteを使用しているためIndexの再生成に時間がかかりすぎてしまうようです。
もうSQLどうこうの前に構造レベルでの変更が必要のようです。
ただ、貴重な意見がいただけました。
変更した際はUnionを使う方法でやりたいと思います。

ありがとうございました。

955 :NAME IS NULL:2011/09/19(月) 01:11:58.15 ID:???
>>953
被ってるってどういうこと?
n以上m以下とstart以上end以下の範囲がちょっとでも重なってればいいのか
n以上m以下がstart以上end以下にすっぽり収まるのかその逆なのか

956 :NAME IS NULL:2011/09/19(月) 02:07:55.09 ID:???
>>955
ありがとうございます
ちょっとでも重なるほうでおねがいしたいです

957 :NAME IS NULL:2011/09/19(月) 02:25:40.24 ID:???
>>956
where (n > start and n < end) or (m > start and m < end)
でいけるんじゃね

958 :NAME IS NULL:2011/09/19(月) 04:04:24.69 ID:???
>>941
ちょっと確認するけど、
「どちらか片方にそのワードが含まれていたらcountで0を返す結果が欲しいです。」
これは間違いだよね?

959 :958:2011/09/19(月) 04:07:39.31 ID:???
>>958
ごめんなさい。この質問の方が間違い。

960 :NAME IS NULL:2011/09/19(月) 06:12:02.08 ID:???
>>953
start < m and end > n

961 :NAME IS NULL:2011/09/19(月) 11:22:50.50 ID:???
>>941
EXISTS 使ってみては?

962 :NAME IS NULL:2011/09/19(月) 12:06:41.13 ID:???
>>957
それだとstart-endがすっぽりn-mに収まる時にひっかからない

963 :NAME IS NULL:2011/09/19(月) 13:50:04.79 ID:???
>>953
SELECT * FROM TBL
WHERE
n<m AND
(n BETWEEN start AND end
OR
m BETWEEN start AND end)


964 :NAME IS NULL:2011/09/19(月) 15:26:57.92 ID:eM/xKYwS
>>941
>>961
一般的にSQLの速度はEXISTS>IN=OR=UNION ALLなので
索引はEXISTSを検証してから考えてください
●oracleですまそ
SELECT 1 FROM DUAL
WHERE
EXISTS(
SELECT 1 FROM TBL AS A
WHERE カラムA=ワード)
AND
EXISTS(
SELECT 1 FROM TBL AS B
WHERE カラムB=ワード)
両方のEXISTSがTRUEならSELECT結果は1、それ以外ならスペース表示
MYSQLにDUAL表(1×1マスのDUMMY列を持つ表)なんてある?なかったらすまそ

965 :NAME IS NULL:2011/09/19(月) 15:30:06.35 ID:eM/xKYwS
↑ORやINからのEXISTS化はバグになりやすいから間違ってる結果を返すかもなので実験してください( ̄ω ̄)

966 :NAME IS NULL:2011/09/19(月) 15:32:12.20 ID:???
なんか違うだろ。

967 :NAME IS NULL:2011/09/19(月) 15:41:59.11 ID:eM/xKYwS
違った?重複チェックできると思うけど

968 :NAME IS NULL:2011/09/19(月) 15:48:10.64 ID:BzSFxFF/

テーブル A: フィールド t, r
テーブル B: フィールド p, t

テーブル B から p の値を指定して t の値を読み込みたいです。
これだけなら select t from B where p = hoge で済むと思います。

さらに条件を追加して、テーブルAにおいて t の値がそれに等しいようなレコードの数が最小なものを選ぶにはどのようにすればよいでしょうか?

例えば
テーブルAが (0, 1), (0, 2), (0, 3), (1, 1), (1, 2)
テーブルBが (0, 0), (0, 1), (1, 0), (1, 1), ...
となっていたら
(0), (1)
ではなく
(1)
だけを得たいです。


969 :968:2011/09/19(月) 15:50:16.34 ID:BzSFxFF/
なお、上記条件に合致する値はただ1つになるような実装となる予定です。これを用いることでコードが簡単になったり動作が速くなったりするならばそうしていただけるとありがたいです。

970 :NAME IS NULL:2011/09/19(月) 15:57:57.06 ID:eM/xKYwS
>>966
リトライします

971 :NAME IS NULL:2011/09/19(月) 16:02:16.07 ID:???
「ような」ってなんだよw
意味がよくわからんけど、たぶん、テンプレのどれかでできる。

972 :NAME IS NULL:2011/09/19(月) 16:09:55.18 ID:???
>>968
ごく一般的に書くとこうなる

select T3.t
from  (select t, count(*) as cnt from A group by t) as T1
    inner join
    (select min(cnt) as min_cnt from (select t, count(*) as cnt from A group by t)) as T2
    on T1.cnt = T2.min_cnt
    inner join
    B as T3
    on T1.t = T3.t
where  T3.p = hoge
;

limitとかrank()とか使えればもっと簡単になるけど
DBMS名を書いてもらわないと何とも

973 :NAME IS NULL:2011/09/19(月) 16:12:31.03 ID:???
それより誰か次スレ頼む

974 :NAME IS NULL:2011/09/19(月) 16:29:32.40 ID:eM/xKYwS
>>941
>>961
こんな感じ?
●oracleですまそ
SELECT 0 FROM DUAL
WHERE
EXISTS(
SELECT 1 FROM TBL AS A
WHERE カラムA=ワード
AND カラムB<>ワード
)
OR
EXISTS(
SELECT 1 FROM TBL AS B
WHERE カラムA<>ワード
AND カラムB=ワード)
片方のカラムに存在すればゼロを返却

オラクルでは<>つかうと索引使われなくなるどす

975 :NAME IS NULL:2011/09/19(月) 16:46:03.75 ID:???
>>972
T2にもhogeの条件必要だと思う

976 :968:2011/09/19(月) 17:29:04.72 ID:BzSFxFF/
>>972
ありがとうございます。
質問の文章が曖昧だったためで申し訳ないのですが、私の意図した質問と異なるものに答えられたように思います。

p が与えられたときに、
テーブルBに (p, t) というレコードが存在するような t の中で
テーブルAに存在する (t, r) というレコードの数が最小であるもの
を意図していました。

>>972 のコードは
p が与えられたときに、
テーブルBに (p, t) というレコードが存在するような t であって、
すべての t' に対して、
テーブルAに存在する (t, r) というレコードの数は テーブルAに存在する (t', r) というレコードの数 以下であるもの
を選択しているように思いますが、私の読み違いでしょうか?

DBMS というのが何を指すのかわからないのですが、MySQL の 4.1 以降の何か、でよいですか?

977 :NAME IS NULL:2011/09/19(月) 17:32:48.20 ID:???
お安い御用です。

978 :972:2011/09/19(月) 18:57:56.20 ID:???
ごめん間違えた

一般解はこんな感じかな?
select T3.t
from  (select T1.t,
         T1.cnt as cnt
     from  (select t, count(*) as cnt from A group by t) as T1
         inner join
         B as T2
         on T1.t = T2.t
     where  T2.p = hoge
    ) as T3
    inner join
    (select min(T4.cnt) as min_cnt
     from  (select    t, count(*) as cnt from A group by t) as T4
         inner join
         B as T5
         on T4.t = T5.t
     where  T5.p = hoge
    ) as T6
    on T3.cnt = T6.min_cnt
;

MySQL限定なら
select T1.t
from  (select t, count(*) as cnt from A group by t) as T1
    inner join
    B as T2
    on T1.t = T2.t
where  T2.p = hoge
order by T1.cnt
limit 1
;

979 :968:2011/09/19(月) 19:10:19.28 ID:BzSFxFF/
MySQL限定ってだけでそんな違うんですね! 昇順ソートして1つだけ取ればよいということでしょうか。とてもわかりやすくなりました。ありがとうございました。


980 :NAME IS NULL:2011/09/19(月) 19:50:45.46 ID:Hy6kQx4A
H2データベースを、MySQLに読み込んで、
MySQLから参照できるようにしたいのですが、
インポートはどのようにすればよいのでしょうか・・・
よろしくお願いします

981 :NAME IS NULL:2011/09/19(月) 19:51:14.84 ID:???
スレ違い。

982 :980:2011/09/19(月) 19:58:06.94 ID:???
>>981
すみません〜
誘導お願いできないでしょうか?
MySQLスレで質問させてもらったらいいでしょうか・・?

983 :NAME IS NULL:2011/09/19(月) 20:22:08.66 ID:???
>>982
MySQLの方でもどうかと思うがな〜
そのH2DBではテキスト(*.txt *.csv)で出力することは出来んの?


984 :NAME IS NULL:2011/09/19(月) 20:24:33.96 ID:???
>>953
おまえ、SQL以外でも人生でわからないことが多くて困ってるタイプだろ。

985 :980:2011/09/19(月) 20:41:07.14 ID:???
>>983
あぁ・・すみません
csvなどのテキスト出力方法がわからず困ってたのですが出力できました
このテキストをMySQLで読み込めばいいのですね。
ありがとうございました、助かりました

986 :NAME IS NULL:2011/09/20(火) 00:08:35.18 ID:???
お安い御用です。

258 KB
■ このスレッドは過去ログ倉庫に格納されています

★スマホ版★ 掲示板に戻る 全部 前100 次100 最新50

read.cgi ver 05.04.00 2017/10/04 Walang Kapalit ★
FOX ★ DSO(Dynamic Shared Object)