SQL質疑応答スレ 15問目

このエントリーをはてなブックマークに追加
615NAME IS NULL:2015/02/20(金) 18:54:12.30 ID:???
idが数値だとして、その最大値 + 1 を返すストアドファンクションを作ってはいるけど
616NAME IS NULL:2015/02/20(金) 23:09:00.17 ID:???
>>612
です。
新しいidはクエリーの呼び出し側でせっていして、古い方のidをitem tabl
eからとってきて、挿入したかったのですが、ストアドプロシージャで作れました
617NAME IS NULL:2015/02/20(金) 23:16:33.00 ID:???
mysql5.6
sim(id1,id2,sim,ts)
でタイムスタンプの最も古いものを最新のsimを持ったものに更新するストアドプロシージャを作ったのですが、290万回実行したいのに1800回実行したあたりで実行結果が反映されなくなってしまいます。
どうしたらよいですか?
618NAME IS NULL:2015/02/21(土) 00:01:15.38 ID:???
>>616
誰に安価つけてんのかわからんがストアドいらんよ

>>617
何をしたいのか具体的に書いてくれ
619NAME IS NULL:2015/02/21(土) 00:12:49.55 ID:???
>>618

最初はうまく行ったのに、作ったストアドプロシージャを呼び出しても0 rows affectedになってしまうんです。
ストアドプロシージャの中身はreviewテーブルのデータから相関係数を求めて、それをsimに入れるだけです
620NAME IS NULL:2015/02/21(土) 02:04:50.37 ID:???
だめだこりゃ
621NAME IS NULL:2015/02/21(土) 11:11:02.04 ID:brE3by3l
DELIMITER //
CREATE PROCEDURE updateSimilarity()
BEGIN
DECLARE id1,id2 int unsigned;
DECLARE done int default 0;
DECLARE id1_ave,id2_ave,v1,v2,cov float default 0;
DECLARE rating1,rating2 tinyint unsigned default 0;
DECLARE result float default 0;
DECLARE cur CURSOR FOR
SELECT x.rating,y.rating
from (
SELECT *
from Review
where item_id=id1
) as x
,
(
SELECT *
from Review
where item_id=id2
) as y
where x.user_id = y.user_id;
DECLARE continue handler for not found set done=1;
SELECT item_id1,item_id2
from Similarity
order by ts asc
limit 0,1
into id1,id2;
SELECT AVG(rating)
from review
where item_id=id1
into id1_ave;
SELECT AVG(rating)
from review
where item_id=id2
into id2_ave;


open cur;
while done != 1 do
fetch cur into rating1,rating2;
set cov = (rating1-id1_ave)*(rating2-id2_ave)+cov;
set v1 = (rating1-id1_ave)*(rating1-id1_ave)+v1;
set v2 = (rating2-id2_ave)*(rating2-id2_ave)+v2;
end while;
close cur;
IF v1 != 0 OR v2 != 0 then
set result=cov/sqrt(v1)/sqrt(v2);
END IF;
update Similarity
set similarity=result
where item_id1=id1 and item_id2 = id2;
update Similarity
set similarity=result
where item_id1=id2 and item_id2 = id1;
END
//
DELIMITER ;

これを実行したのですが1800回程度実行して以降テーブルに結果が反映されなくなりました。
622NAME IS NULL:2015/02/21(土) 11:47:13.79 ID:brE3by3l
IF v1!=0 and v2!=0 then
でした
書き間違えました
623NAME IS NULL:2015/02/21(土) 13:46:07.12 ID:???
これ以上はmysqlスレに行ったほうがいいと思うけど、
show warnings;やshow errors; でメッセージとか出てないの?
624NAME IS NULL:2015/02/21(土) 18:34:26.25 ID:???
>>623
けいこくもがエラーもないです
mysqlスレでも聞いてみます
625NAME IS NULL:2015/02/21(土) 19:17:01.44 ID:brE3by3l
自己解決しました。
類似度が0の場合、updateされた時にタイムスタンプが更新されないためでした。
ご迷惑をお掛けしました
626NAME IS NULL:2015/02/23(月) 19:57:45.96 ID:???
accessの2000くらいの、古いバージョンなんですが、
いくつかのテーブルからフィールドを選んで結合したクエリがあって、
そのクエリの日付型フィールドから、既に開いてるフォームのテキストボックスに入力された日付に合致したレコードのみを取り出し、
Aフィールドの文字列によって、AフィールドとBフィールドのどちらかの値を取り出し、
新しいテーブルに書き込むということをしたいと考えてます

さしあたって日付に一致したレコードを取り出すとこからやりたいのですが
クエリの抽出条件に[forms]![フォーム名]![テキストボックス名]と書いて、
SQLで
OpenRecordset("クエリ名",dbopendynaset)
とするとパラメーターが足りないとエラーが返されます
次に、
OpenRecordset("SELECT * FROM クエリ名 where フィールド名 = # & [forms]![フォーム名]![テキストボックス名] & #, dbOpenDynaset,)
としてみると日付型が一致しないとエラーが出てしまいます

どー直せば期待する結果を得られるでしょうか
627NAME IS NULL:2015/02/23(月) 23:32:37.22 ID:???
>>626
クエリ定義をSQLビューで表示して全部書いてみて
下のOpenRecordsetは"が閉じてないけど、ちゃんとプログラム通りに書いて
628NAME IS NULL:2015/02/25(水) 13:31:45.28 ID:67mWbYxh
お世話になります、質問です。

あるテーブルに、ふりがな列と生年月日の列があります。
これを歳の若い順に50件出力したいのですが、
出力の順番はふりがな順(あいうえお順)にしたいのです。

こういうのってSQLだけでできますか?
(PostgreSQLです)
629NAME IS NULL:2015/02/25(水) 13:33:32.44 ID:67mWbYxh
>>628
あ、すいません、もちろん副問い合わせとかなしでの話です。
630NAME IS NULL:2015/02/25(水) 13:41:11.21 ID:???
もちろん って普通サブクエリ使うだろ
631NAME IS NULL:2015/02/25(水) 13:48:53.25 ID:???
余裕でできる→無理
に変わった瞬間を見た
632NAME IS NULL:2015/02/25(水) 13:59:59.31 ID:???
>>628
select * from ユーザ order by 生年月日 desc, ふりがな limit 50;
633NAME IS NULL:2015/02/25(水) 14:05:25.24 ID:???
それ生年月日順やん
634NAME IS NULL:2015/02/25(水) 15:31:27.88 ID:???
>>633
select * from ユーザ order by date_part('years', age(生年月日)) desc, ふりがな limit 50;
635NAME IS NULL:2015/02/25(水) 15:39:51.76 ID:???
>>632 >>634
ポスグレのorder byってこれでふりがな順になるの?逆におかしくね?
636NAME IS NULL:2015/02/25(水) 15:47:57.32 ID:???
>>635
何がおかしいのか理解できない
637NAME IS NULL:2015/02/25(水) 15:48:25.79 ID:???
サブクエリ以外でやれるDBっていったらaccessくらいしか思いつかん
通るか知らんがこんなイメージ

select * from (select * from ユーザ order by 生年月日 desc limit 50 ) order by ふりがな
638NAME IS NULL:2015/02/25(水) 15:48:50.95 ID:???
あと、年の若い順だから>>634でdescはいらないね
639NAME IS NULL:2015/02/25(水) 15:51:54.46 ID:???
>>637
なんだそのアホクエリーは
640NAME IS NULL:2015/02/25(水) 15:58:38.49 ID:???
なんかOracleみたいだな
641NAME IS NULL:2015/02/25(水) 16:04:01.95 ID:???
>>635
descが余分なのは置いといて、俺も>>634の何がおかしいのかわからんぞ。
年齢順・フリガナ順に並べて先頭50件だろ?
642NAME IS NULL:2015/02/25(水) 16:05:08.07 ID:???
row_number() over 〜 って Postagre でも使えたっけ?
643NAME IS NULL:2015/02/25(水) 16:06:15.59 ID:???
ん、ひょっとして、
・年齢順に並べて
・その先頭50件を
・フリガナ順で並べる
ってことか?結果として年齢順にならないソート。
644NAME IS NULL:2015/02/25(水) 16:07:22.18 ID:???
>>641
生年月日順に若い方50件抜き出した上で、それを名前順にソート
>>637 は別名必須
645NAME IS NULL:2015/02/25(水) 16:08:36.73 ID:???
若いほうじゃないか、まあどっちでもいいな
50件以降はいらないのだよね?
646NAME IS NULL:2015/02/25(水) 16:13:09.78 ID:???
>>644
そういう要件なのか−。
でも、それって年齢順に並べたときに50件目と51件目が同じ年齢だったら破綻するんじゃないか?
50件目が、20歳、サイトウ
51件目が、20歳、アベ
で、アベが最終的に表示されなくていいのかって問題がある。
647NAME IS NULL:2015/02/25(水) 16:18:39.65 ID:???
>>646
その場合は、19歳まで全部と、20歳をふりがな順にソートした(50-19歳までのレコード数)を抜き出して、
さらに全体をふりがな順に並べる、というのが要件なのか?
648NAME IS NULL:2015/02/25(水) 16:19:52.65 ID:???
>もちろん副問い合わせとかなしでの話です。

副問い合わせの意味わかって書いてるのかなあこれ、、、
SQL一発で済ませろ的な意味なんじゃないかと、、それじゃなきゃ無理だろw
649NAME IS NULL:2015/02/25(水) 16:22:45.54 ID:???
> 歳の若い順に50件出力
をもっと正しく表して欲さないと終わらない話だなこれ
650NAME IS NULL:2015/02/25(水) 17:09:28.38 ID:???
Window関数使えば出来るのかな?
まあ副問い合わせ禁止する理由がわからんが

>>637
それも普通は副問い合わせに入るんじゃね
651NAME IS NULL:2015/02/25(水) 18:43:39.80 ID:???
select t1.age,t1.name,t1.seq
from user t1
left join user t2
on t1.age > t2.age
or (t1.age = t2.age and t1.name > t2.name)
or (t1.age = t2.age and t1.name = t2.name and t1.seq > t2.seq)
group by t1.age,t1.name,t1.seq
having count(1) < 50
order t1.name

動作確認はしてないが同姓同名、同年齢なら一意キーで若い方
という想定で作ってみたが、こんなんでどうだ?
652NAME IS NULL:2015/02/25(水) 18:47:47.34 ID:???
レコード件数増えたら面白いことになりそうだな、これ
653NAME IS NULL:2015/02/26(木) 03:05:55.44 ID:???
副問い合わせは許されんのに結合は許されるのだろうか
654NAME IS NULL:2015/02/27(金) 17:00:21.61 ID:oUXcvWpV
・mySQL5.5
・1つのカラムにカンマ区切りの数値が格納されている→1,2,3,4,5のような値
・指定した数値(複数有)がカラムに含まれているデータを取得したい

画面上にチェックボックスが複数あり、チェックされた項目に応じた
数値がカンマ区切りでカラムに格納されます。
別途、検索画面がありそのカラムに指定した数値(こちらもチェックボックスです)が
含まれているデータを抽出したいという処理です。
likeを使った曖昧検索のようなイメージです。

例えば
 レコードA → 1,2,3,4,5
 レコードB → 1,2,3,4

検索条件
 検索パターンA:2,3を選択 → レコードAもBも抽出される
 検索パターンB:1,6を選択 → レコードAもBも抽出される
 検索パターンC:5を選択 →  レコードAだけ抽出される
 検索パターンD:6を選択 → どちらのレコードも抽出されない

カンマで格納されているデータをカンマ区切りで分割するのは特に問題ありません。
チェックする項目毎にtinyint(1)型のカラムを作るという案もあったのですが
将来的に増えていく可能性もあるので、その案は取りやめになりました。

1つのテーブルだけで実装するという仕様があるものの、
データの持ち方がそもそもおかしいかもしれませんが、いい方法あったら教えて下さい。
655NAME IS NULL:2015/02/27(金) 17:04:53.95 ID:???
in('dummy',',選択1,',',選択2,',',選択3,')
656NAME IS NULL:2015/02/28(土) 01:44:52.06 ID:???
WHERE concat(',',カラム,',') regexp '\\,(2|3)\\,'
WHERE concat(',',カラム,',') regexp '\\,(1|6)\\,'
WHERE concat(',',カラム,',') regexp '\\,(5)\\,'
WHERE concat(',',カラム,',') regexp '\\,(6)\\,'

正規表現で出来るんじゃないかと始めて見たものの
結局俺には出来なくてカラムにカンマ付け足した。
657NAME IS NULL:2015/02/28(土) 02:58:09.92 ID:???
カンマは正規表現で特殊な意味を持たないよ(=エスケープしなくていいよ)
658NAME IS NULL:2015/02/28(土) 03:01:31.77 ID:???
で、今調べたけど、mysqlならこれでいいんじゃないの?
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
659NAME IS NULL:2015/03/01(日) 03:55:58.57 ID:???
>>654です。
レス遅くなりましたが、回答ありがとうございます。

>>658
こちらが自分のイメージにぴったりでした!
ありがとうございましたー
660NAME IS NULL:2015/03/03(火) 17:00:11.79 ID:???
SQLServerですけど
checksum は稀にコリジョン起きるという話ですが

select checksum('ab'),checksum('a-b')

これが同じ値を示します。
「-」の有無だけなのですが・・・
661NAME IS NULL:2015/03/03(火) 17:05:47.46 ID:???
失礼しました
binary_checksumを使って解消しました
662NAME IS NULL:2015/03/03(火) 20:16:04.97 ID:???
>>660
コリジョン(偶然の一致)じゃなくて一致する値を返してるだけだろ
'ab'と'a-b'が同じと判定される照合順序なら同じ値返してくれないと困るじゃないか
663NAME IS NULL:2015/03/03(火) 20:52:09.81 ID:???
最初は binary_checksum なるものの存在を知らず、checksum がバイナリ比較かと思ってたんですよ
どうもすみません。。
664NAME IS NULL
ま、おかしいと思った時点で a--b a---bとか試してみることに気がつくべきだったな