このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。
SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。
質問するときはDBMS名を必ず付記してください。
【質問テンプレ】
・DBMS名とバージョン
・テーブルデータ
・欲しい結果
・説明
前スレ:
SQL質疑応答スレ 11問目
http://hibari.2ch.net/test/read.cgi/db/1299305530/
よくある質問1 (問) ID | DATE | DATA --+----------+----- 1 | 2007-11-11 | aaa 2 | 2007-11-11 | bbb 1 | 2007-11-10 | ccc 3 | 2007-11-12 | ddd 3 | 2007-11-11 | eee 4 | 2007-11-10 | fff 1 | 2007-11-12 | ggg このようなテーブルから、下記のように 1 | 2007-11-12 | ggg 3 | 2007-11-12 | ddd 2 | 2007-11-11 | bbb 4 | 2007-11-10 | fff 各idに対して最新の1件だけ抽出するSQLの書き方を教えてください。 (答) select A.ID, A.DATE, A.DATA from TableName A inner join (select ID, max(DATE) as MAX_DATE from TableName group by ID ) B on A.ID = B.ID and A.DATE = B.MAX_DATE ;
よくある質問2 (問) key data ---------------- 1 a 1 a 1 b 1 b 1 a 2 b 2 a 2 a というテーブルから key a b -------------------- 1 3 2 2 2 1 というExcelのピボットの様なデータを取得したいのですが、どういうSQLになりますか? a,bというのは固定なので、仮にcというデータがあっても無視して構いません。 (答) SELECT key, SUM(CASE data WHEN 'a' THEN 1 END) AS a, SUM(CASE data WHEN 'b' THEN 1 END) AS b FROM table GROUP BY key ORDER BY key ;
よくある質問3 (問) ID HOGE 01 A 01 B 01 C 02 A 03 B HOGEをAもBもCも持っている、ID:01だけ取り出すにはどうすればよかですか (答1) SELECT id FROM TableName WHERE hoge in ('A','B','C') GROUP BY id HAVING count(DISTINCT hoge) = 3 ; (答2) select * from TableName T1 where not exists (select * from (values 'A', 'B', 'C') T2 (HOGE) where not exists (select * from TableName T3 where T1.ID = T3.ID and T2.HOGE = T3.HOGE ) ) ; ※valuesの部分(Table Value Constructor)はDBMSによって文法がかなり違うので注意
よくある質問5 (問) 年月(YYYYMM)を指定し、その年月に対応する年月日を取得したい 例:201006を指定したら、以下の結果を得たい 20100601 20100602 ・ ・ ・ 20100630 (答) SQLでは存在しないデータを生成することはできません。 この問いの場合は素直にカレンダーテーブルを用意しましょう。 どうしてもやりたければ以下のような方法もなくはないですが、 再帰問合せの本来の使い方ではありません。 やめておくことを強くお奨めします。 (PostgreSQLのgenerate_series()関数なら辛うじてセーフかもしれませんが 賛否の分かれるところでしょう。) with TEMP (NUM) as ( select 1 from dual union all select NUM + 1 from TEMP where NUM < 31 ) select to_char(to_date('201006', 'YYYYMM') + NUM - 1, 'YYYYMMDD') from TEMP where to_date('201006', 'YYYYMM') + NUM - 1 < add_months(to_date('201006', 'YYYYMM'), 1) ; ※上記はOracleの場合です。(11gR2以降) ※再帰問合せをサポートするDBMSならこれを適当に改変すれば動きますが どのみちお奨めしません。
以上、テンプレ終わり
終了
おつ
ちん
ぽこの
さき
っちょ
ペロ
なめ
たい
いいよ
SQLマジSQL
SQLマゾSQL
まん
ぼっ!!
なめ
よかった、SQLで悩んでる人はいなかったんだ
いく
でる
のんで
・DBMS名とバージョン MySQL 5.0 ・テーブルデータ userテーブル id int name varchar ・欲しい結果&説明 nameはユニークではないので、値が同じレコードが複数存在します。 nameの値が自分と同じ値を持つレコードが存在するレコードだけ全件抽出したいです 例) id name 1 aaa 2 bbb 3 ccc 4 bbb この場合idが2と4のレコードだけ抽出したいです。 どのようなSQLを書けばいいでしょうか。 よろしくお願いします。
select * from user where name = 'bbb';
ああー、意味がわかった select * from user where id in (select id from user group by name having count(*) > 1) こうかな
where name in (select name以下略 の間違いだろ existsでもいい select * from user T1 where exists (select * from user T2 where T1.id <> T2.id and T1.name = T2.name) ;
>>32 MySQLって無茶苦茶なSQL通すから、間違いじゃないのかもしれん
が、それを堂々と回答されてもなぁ
37 :
NAME IS NULL :2011/09/29(木) 10:04:07.13 ID:wcoCYq1V
すみません。WebPG板より誘導していただいてきました。質問させてください。 mysqlver5.1.6で update tbTest set flg=1 where seq_host = 524 AND non_printable=0 ORDER BY seq LIMIT 0 ,10 というのを実行しようとしたらmysqlではupdate文のoffsetができない?らしくエラーになりました。 これを実行(seqが特定のものから10個をフラグ建てたい) するにはどうしたらいいでしょうか?
update文にORDER BYって
またMySQLか
>>37 ためしてないけど
update tbTest set flg=1 where seq_host = 524 AND non_printable=0 AND seq in(
select seq from tbTest t where
(select COUNT(*) from tbTest where seq<t.seq)<10
)
updateのテーブルに別名付けれたり、updateにfromかけたりするともうちょっとすっきりするかもしれんが
それは多分標準的なSQLじゃないだろうし
・DBMS名とバージョン : SQL-Server 2008 売り上げ ID | AMOUNT | --+---------------------- 1,200 1,300 1,400 2,100 4,100 5,200 5,300 6,400 得意先マスタ ID | NAME | OYA_CODE --+----------------------+-------------- 1,abc商事 本店,1 2,abc商事 い支店,1 3,abc商事 う支店,1 4,def工務店 本店,4 5,def工務店 い支店,4 6,ghiサービス,6 7,jklシステム,7 ・欲しい結果 1,abc商事 本店,900 4,def工務店 本店,600 6,ghiサービス,6 7,jklシステム,400 ・説明 会社ごとに、売り上げ合計を出したいです。 得意先マスタに親会社コードを持っているので、親会社がある場合は親会社に合算したいです。 自分が親会社の場合は自らのコードが入っています。
すみません結果の訂正です 6,ghiサービス,400 自らが子会社の場合は親会社に合算するので、子会社としては表示しません。 お願いします。
>>41 ID=1,2,3がabc商事なら、結果の1行目は200+300+400+100で1000じゃないのか?
売上テーブルに7,400の行が無いのは抜けてるだけか?
子会社の子会社はあり得るのか?
>>41 抜けていたのと、計算違いすみません。
子会社の子会社(孫)はありません。
よろしくお願いします。
>>44 select
ID,
NAME,
(select sum(AMOUNT) from 売り上げ where ID in (select ID from 得意先マスタwhere OYA_CODE=t.ID) ) as 合計
from 得意先マスタ t
where ID=OYA_CODE
とかでどうだ
46 :
29 :2011/09/29(木) 13:54:27.91 ID:???
>>31-32 教えていただいたSQLでほしい情報を取得できました。
ありがとうございました。
>>45 ありがとうございます。
ちょっとテーブル構成がより複雑なので修正してやってみます。
副問い合わせがよくわからなかったものでして。
お安い御用です。
いみません、41の続きです。 ○売伝(既に結合したビュー) 売伝番号,得意先名,得意先コード,親得意先コード 1000,A商事 本店,20000,20000 1001,A商事 あ店,20001,20000 1002,A商事 い店,20002,20000 1003,B工務店,30000,30000 ○売伝明細(既に結合したビュー) 売伝番号,売掛締年月,明細金額 1000,2011/09,1000 1000,2011/09,2000 1000,2011/09,3000 1001,2011/09,500 1001,2011/09,500 1002,2011/09,100 1003,2011/08,300 ■期待する結果 A商事 本店,5100 B工務店,300 ■試してみたSQL SELECT dbo.売伝.得意先名, dbo.売伝明細.売掛締年月, (SELECT sum(dbo.売伝明細.明細金額) FROM dbo.売伝明細 WHERE dbo.売伝.得意先コード in ( SELECT dbo.売伝.得意先コード FROM dbo.売伝 WHERE dbo.売伝.親得意先コード = t.得意先コード)) AS 合計 FROM dbo.売伝 t, dbo.売伝 CROSS JOIN dbo.売伝明細 WHERE dbo.売伝.得意先コード=dbo.売伝.親得意先コード ■問題点? CROSS JOINのせいで同じ結果がたくさん出てきてしまいます。 ビュー同士の結合とかはダメなんでしょうか? うまく親会社ごとに合計したいです。お願いします。
dbo.売伝 CROSS JOIN dbo.売伝明細 の部分が要らないと思う
>>49 A商事 本店,5100
どういう計算だ?
>>49 いろいろと突っ込みどころ満載なんだがとりあえず
SELECT
得意先名,
(SELECT sum(明細金額) FROM 売伝明細
WHERE 売伝番号 in
(SELECT 売伝番号 FROM 売伝 WHERE 親得意先コード = t.得意先コード)
) as 合計
FROM
売伝 t,
WHERE
得意先コード=親得意先コード
とか
JOINでやりたいなら、得意先名いらなければ
select
売伝.親得意先コード,
sum(明細金額) as 合計
from 売伝
join 売伝明細 on 売伝.売伝番号=売伝明細.売伝番号
group by 売伝.親得意先コード
とかでできるんじゃないか
得意先名ほしければ、これに得意先マスタ(あるだろ?)JOINしろ
売掛締年月はどうしたいのかわからん
サブクエリにしてもJOINにしても、テーブルが紐付く条件よく考えてみることだ
52様、何度もすみません。 結合とか、サブクエリでの集計がよくわからないのでビューを結合してみました。 テーブル名 : 単純結合 売伝番号 金額 得意先コード 売上伝票番号 得意先名 親得意先コード 1000 5000 101 1000 モナー商事 本社 101 1001 2000 102 1001 斉藤製作所 102 1000 1000 101 1000 モナー商事 本社 101 1000 3000 101 1000 モナー商事 本社 101 1002 600 105 1002 モナー商事 岩槻事業所 101 1002 700 105 1002 モナー商事 岩槻事業所 101 1002 900 105 1002 モナー商事 岩槻事業所 101 1003 10000 106 1003 モナー商事 浦和事業所 101 これで親会社結合して モナー商事 本社 21200 斉藤製作所 2000 とするにはどうしたらよいでしょうか?
なぜそんなビューを作るのか理解できん すなおに個々のテーブル定義と欲しい結果書け
>>54 すみません。
ここのテーブルは多すぎて。
ただ1つのテーブルに親得意先コードと親得意先コードがあるため
集計のときとかとてもやっかいです。
1つの方法としては親得意先コードで、得意先名を再取得してしまえば
望むようなことができるかな?と考えています。
私のSQL知識不足もありますが、元々DBのないCOBOLからの入れ替えで
かつ途中参加になったもので苦労しています。
今回は開発側ではないけど、ちょっと作って・・・と言われました。
あとでテーブルまとめます。
これだけ見ると、Group Byでよさげ。
なんで出てくるたびに例のデータが変わってんだよw 今までにあげられたSQLではどうダメだったのか書かないと釣りかと思うぜ
58 :
57 :2011/10/03(月) 21:48:09.14 ID:???
考え方は、親でgroup化して、合算値を出して、得意先と結合して出力する、だよ。 それを求めるための方法がいくつかあるけれど、みんなそういうSQL書いてくれてるはず。
この2つのSQLは等価だと思っていますが、まちがっていますか? mysql5.1 select * from tblA inner join (tblB left join tblC on tblB.out_c = tblC.key_c) on tblA.out_b = tblB.key_b select * from tblA inner join tblB on tblA.out_b = tblB.key_b left join tblC on tblB.out_c = tblC.key_c
・DBMS名とバージョン PostgreSQL 9.0 ・テーブルデータ posts id post_tags post_id tag_id tags id tag(タグ文字列) ・欲しい結果 複数のタグ(tags.tag)を指定してAND検索でpostsを取得 ・説明 実際にはユーザテーブルも絡んだりしてもうちょっと複雑なのですが、タグ一つでの検索の場合は以下のような感じになると思います。 SELECT posts.* FROM posts JOIN post_tags ON post_tags.post_id = posts.id JOIN tags ON tags.id = post_tags.tag_id WHERE tags.tag = 'javascript' これを例えばタグ「javascript」とタグ「php」両方を持つpostを取得するにはどうしたら良いでしょうか?
>>61 かな〜り特殊な書き方だけどやってみた。
select * from (
select *
from crosstab('SELECT posts.id,post_tags.tag_id, tags.tag FROM posts
JOIN post_tags ON post_tags.post_id = posts.id
JOIN tags ON tags.id = post_tags.tag_id ORDER BY 1, 2' ) AS
ct( id integer, tag1 character varying, tag2 character varying,tag3 character varying, tag4 character varying)
) as t
WHERE concat(tag1,tag2,tag3,tag4) LIKE '%javascript%'
AND concat(tag1,tag2,tag3,tag4) LIKE '%php%'
ちなみにconcatの部分は9.1じゃない場合はnullを除外して連結しなおす必要がある。
あと、crosstabを使ってるから、tablefuncモジュールインストールしないといけない。
最後のWHERE句は以下のように変更してもいける
WHERE (tag1 = 'javascript' OR tag2 = 'javascript' OR tag3 = 'javascript' OR tag4 = 'javascript')
AND (tag1 = 'php' OR tag2 = 'php' OR tag3 = 'php' OR tag4 = 'php')
すなおに WHERE post_tags.tag_id in (SELECT id FROM tags where tag = 'javascript' ) AND post_tags.tag_id in (SELECT id FROM tags where tag = 'php' ) とかじゃいかんのか?
65 :
61 :2011/10/08(土) 19:49:37.40 ID:???
>>62 JOINが増えてるだけでやろうとしてることは同じような感じでした!
参考にします、ありがとうございます
>>63 crosstab初めて聞きました!
まだSQL文を理解できてないですが、勉強してみます、ありがとうございます
>>64 post_tagsを2回JOINすれば大丈夫そうです!
SELECT posts.* FROM posts
JOIN post_tags AS pt1 ON pt1.post_id = posts.id
JOIN post_tags AS pt2 ON pt2.post_id = posts.id
WHERE pt1.tag_id in (SELECT id FROM tags where tag = 'javascript' )
AND pt2.tag_id in (SELECT id FROM tags where tag = 'php' )
もしくはJOINだけでもいけました。
SELECT posts.* FROM posts
JOIN post_tags AS pt1 ON pt1.post_id = posts.id
JOIN tags AS t1 ON t1.id = pt1.tag_id
JOIN post_tags AS pt2 ON pt2.post_id = posts.id
JOIN tags AS t2 ON t2.id = pt2.tag_id
WHERE t1.tag = 'javascript' AND t2.tag = 'php'
パフォーマンステストをして方法を検討したいと思います
皆さんありがとうございました!
post_tagsを2回もJOINする必要あるの?
ない。
68 :
NAME IS NULL :2011/10/09(日) 03:19:30.94 ID:q9Vzai3H
掲示板のスクリプトをつくっています。 投稿のテーブルをつくり、 そこに1つの投稿へのレスもまとめて1つのテーブルに収めています。 設計としては以下のようになっています(説明のため多少シンプルにしています) 投稿テーブル ・id ID ・parent_id 上記のIDを外部キーとしたもの ・message 投稿内容 現在は 1.投稿テーブルから1ページに表示したい行を取得する SELECT * FROM posts WHERE parent_id IS NULL LIMIT 10 2.上記で取得した行の id を parent_id としている行を取得する SELECT * FROM posts WHERE parent_id = 1001; SELECT * FROM posts WHERE parent_id = 1002; SELECT * FROM posts WHERE parent_id = 1003; : つまり投稿1つに対してレスを探すためにSELECT文が1つ発行されており、 1ページ表示するのに 表示する投稿数+1 のSQL文が発行されてしまっています。 これを1つのSQL文で取得したいです。 別テーブルだとJOINでできるかと思いますが、同じテーブルでどうするのかがわかりません。 どういうSQL文にしたらよいでしょうか? MySQL 5.1.51です。
再帰的な検索しないなら、同じテーブルでも別名つけてJOINすれば良いだけ 再帰的に、レスのレスのレス...も欲しいとなると ・再帰SQLをつかう ・ストアドプロシジャで処理する 辺りが通常の手段だが、MySQLでサポートされてるかどうかはしらね どっちもダメならホストアプリでやるかデータ形式工夫するかしないとダメだね
SQLサーバーで、FROM 句のテーブル名をカンマ区切りで列記した場合は INNER JOIN になる、であってるでしょうか??
CROSS JOINだろ
WHEREで結合条件指定しないならCROSS JOINじゃないか と言っておいて考えると、CROSS JOINしてからWHEREで絞っても同じだから 結合条件があろうとなかろうとCROSS JOINと等価なのか
73 :
NAME IS NULL :2011/10/12(水) 23:55:32.82 ID:qJQCBXRw
mysql5.1 なんだけどデータを挿入か上書きのどちらかをしたいときって 重複するデータの存在を調べたうえでif文で分岐させてUPDATE、REPLACEするのと とりあえず重複があるかどうか分からない状態でDELETEさせてINSERTするのと どっちが早い?
知るかよ。それぐらい自分で試せばいいだろ。いちいち人に聞くな
テーブル次第。
> REPLACEは、もしテーブル内の古い行が PRIMARY KEY か > UNIQUEインデックスの新しい行と同じ値を持っていれば、 > 古い行は新しい行が挿入される前に削除されるという事以外、 > INSERTと全く同じように機能します。 ふぅん
>>73 俺ならいきなりINSERTする。
ON DUPLICATE KEY UPDATE 〜 付きで。
79 :
NAME IS NULL :2011/10/14(金) 13:57:07.71 ID:efaJhCig
一つのデータに複数のキーワードを関連付ける物を作成しているのですが、 指定したすべてのキーワードが関連づけられているデータを探し出すSQL文はどのように書けばいいでしょうか? データ構造はdata, keyの二つで、 data=1に20と30のkeyが関連づけられていたら、 (1,20),(1,30) のようなデータが入っています。
81 :
NAME IS NULL :2011/10/14(金) 21:24:14.75 ID:i+DDWHmc
tblがひとつあり列は3つあります jinbutu、no、orderplan A 1 M A 2 N A 7 M B 3 N B 8 N B 9 N C 13 M C 14 N C 15 M C 16 N C 17 M このtblをdelete文で整理したいんですが jinbutuのなかでorderplanが同じ場合は noが一番小さいやつだけを残したいです ↓このようにしたい A 1 M A 2 N B 3 N C 13 M C 14 N よろしくお願いします
delete from tbl where exists (select * from tbl T2 where tbl.jinbutu = T2.jinbutu and tbl.orderplan = T2.orderplan and tbl.no > T2.no) ;
83 :
NAME IS NULL :2011/10/15(土) 12:49:36.09 ID:5cbPt9KL
ありがとうございます。deleteできました
宜しくお願いします DBのバージョン PupSQLite 1.9.13.5 テーブル datetime INTEGER PRIMARY KEY, ymdhm text MT4 というFX のトレードや、バックテストといった、過去の検証を行ったりするプログラムを、SQLiteを 用いて保存しているのですが、文字列フィールドのエスケープシーケンスについて教えてください。 string Table = "MATRIX_"+Period(); sqlite_exec (DB, "create table "+Table+" (datetime INTEGER PRIMARY KEY, ymdhm text)"); YMDHM[0] = "201010140730"; query = "insert into "+Table+" (datetime,yymmdd ) values (" + t1 + "," + YMDHM[0] + ");"; 上記の(" + t1 + "," + YMDHM[0] + ");"; このあたりで、 sqllite error code 1 #define SQLITE_ERROR 1 /* データベースが間違っています、または存在していません */ このエラーが出ます、文字列のエスケープシーケンスのやり方が間違っていると思うのですが、分かりません 教えて頂けないでしょうか。
スレ違い
言語のスレ
「ymdhm」でCREATEして「yymmdd」でINSERTかよ? VALUE句もTEXTならシングルクォートで囲えよ・・・まあSQLiteなら数値なら通るだろうけど。
データベースを選べるように設計したいのですが、 そうなると独自実装みたいなSQLは排除する必要があります。 主要なフリーのRDBMS MySQL PostgreSQL SQLiteあたりでどれでも動くような書き方をするのに、 参考になるサイトや文献があったら教えてもらえませんでしょうか?
そういうライブラリを使う or 標準SQLの範囲で記述するのはもちろん、各RDBMSが実装できていない部分を調べて、それらを使わないようにする。 これはマニュアルを見るのが楽。
sqliteでアプリを起動した日のみ insert into TableName (datetime) values (datetime('now', 'localtime')); このようにその日の日付(2011-10-17)をもったレコードを1日1回挿入しているのですが 90日まで遡ってまでのレコードを取得したい場合どう書くのが適切でしょうか?
日付関数あるなら簡単でしょう where 日付レコード > 現在時刻-90日分の時刻
ありがとう 今日から遡って取得したいから SELECT * FROM TableName ORDER BY id DESC WHERE datetime > datetime('2011-10-17', '-90 days'); で大丈夫かな
その調子で全部確認していく気かい
91,93どっちもdatetime()→date()だった
>>94 SQL初めて触ったけど純粋に datetime > 'yyyy-MM-DD' の比較が成り立つのが不思議でして
unixタイムに変換すればいいじゃない
>>95 型毎に演算子をオーバーロードしているようなものです
この場合は暗黙の型変換だろ
お安い御用です。
Androidでアプリを作っています。 データを抽出する条件が分からないので、助けてください。 DBはSQLiteです。 テーブル構成は次の通りです。 id:integer wdate:text wtime:text weight:real other:integer memo:text 抽出するときの条件: 日付はグループ化する グループ化されたデータは、最も遅い時刻であること。 次のようなSQLを書いて見ましたが、上手くいきませんでした。 select * from ( select * from weight_table where wdate <= julianday(datetime('now', 'localtime') ) order by wdate desc, wtime desc ) result group by result.wdate; 上記SQLだと最も早い時刻でグループ化されてしまいます。 よろしくお願いします。
>>100 一般的にサブクエリでorder byは無効だぞ(オフセット操作等除いて)
group by書いて列リストに*も無効だ。SQLiteも嘘SQL通すのか...
最も早い時刻でグループ化するとか意味わからんのだが
データと欲しい結果の例書いてみ
エスパーするなら
select wdate,max(wtime) from weight_table group by wdate
で良いような気がする
とおもったら日付でグループだった無念
Androidでアプリを作ってんのか。すげぇな。
105 :
100 :2011/10/19(水) 13:32:07.01 ID:???
>>105 解決したなら解決策を示しなよ。
>>101 を始め、何人かがあんたのために考えてやったんだからさ。
MySQLの質問です SELECTする際、レコードの状態によって取得するカラムを動的に変えることは可能 でしょうか 例えば id stage stage1_param stage2_param とカ ラムがあって stageの値が1ならstage1_param、2ならstage2_paramの値を取りたい これを1回のクエリで済ます方法があれば知りたいです 一気に全カラム取った方が速ければそれでも良いのですがカラム数が60ぐらいだとどうなんでしょう
そのSQLを生成するホスト言語側で場合分けしたらいいんでわ? しかし、 id stage param_value ---------------------------- 1 1 15 1 3 8 2 1 32 1 6 1 2 2 2 とかしといた方が、ステージ数がいくつになっても対応できるんじゃないの?
>>107 select case stage
when 1 then stage1_param
when 2 then stage2_param
…
end as stage_param
補足、stageの値によってカラム数を変えるのは無理
お安い御用です。
>>107 に近い質問だと思いますが、
レコードが0件の時に、全部のカラムをnullにしたのをinsertしたいのですが、
どういうinsert文を書けばいいでしょうか?
MySQLとSQLiteで使用可能な文だとありがたいです。
when 0 then null
助けて下さい頭がパンクしそうです。 CARD |CARDID|HOWMANYLEVEL| | 1 | | | 2 | | CARDLEVEL |CARDID|LV1|LV2|LV3|LV4|LV5| | 1 |0 | 0| 23 | 28 | 0| | 2 |0 | 0| 0 | 30 | 55| | 1 |0 | 0| 25 | 29 | 0| CARDテーブルの HOWMANYLEVELに CARDLEVELから0以外の個数を入れたいです。 CARDLEVELのCARDIDは複数あります。
その例でいうとCARDID 1 のHOWMANYLEVELは 2 なのか 4 なのか
115 :
113 :2011/10/22(土) 18:57:13.72 ID:???
4です!
insert into CARD select CARDID, sum(case when LV1 <> 0 then 1 else 0 end + case when LV2 <> 0 then 1 else 0 end + case when LV3 <> 0 then 1 else 0 end + case when LV4 <> 0 then 1 else 0 end + case when LV5 <> 0 then 1 else 0 end) from CARDLEVEL group by CARDID ;
117 :
113 :2011/10/22(土) 19:06:31.59 ID:???
>>116 ありがとうございます、sum文でも出来るんですね
非常に感謝してます
118 :
111 :2011/10/23(日) 01:24:51.45 ID:???
お安い御用です。
>>118 レコードがあるときどうするのか書いてないけど、共通のロジックにしたいのならアプリでやる。
そもそも num > 10 and num < 100.123 という条件だったらの間に何レコードあると教えるのさ
>>118 insert into テーブル名 select null,null,... from テーブル名 having count(*)=0
null,...のとこは、テーブルの項目数と同じだけnullな
デフォルト値が指定されてないなら、insertに列1個だけ指定してselectで1個だけnullでも良いけど
123 :
111 :2011/10/23(日) 20:52:06.62 ID:???
>>120 >>122 レスありがとうございます。
詳細な情報出さないですみませんでした。
テーブルを最初に作ったとき1度だけinsert文をしたいのですが、
(それ以降はupdateはするがinsert、deleteは行わないテーブルです)
create table if not exists t1 ( c1 int, c2 int, c3 int)
insert into t1 (null, null, null)
本来はこれだけでいいのですが、
このSQLをテーブルを作る初回のみに行うわけではなく、
それ以降も行う可能性があるため、
create tableのところは if not existsがあるので影響はないのですが、
insertはこのままだと挿入されてしまうので困っていました。
>>122 さんのSQLで早速試してみます。
>>122 なにこのトンデモ回答?
>>123 MySQL/SQLite専用ならcreate table if not existsとか
replace文とか使えるけど、汎用を目指すならそんな変な構文は使わず、
アプリ側で条件分岐すべき
126 :
124 :2011/10/23(日) 22:34:45.65 ID:???
>>125 一点目はnullがリテラルとして使えるかという点
二点目はgroup byなしでhavingが使えるかという点
だったが、二点目は俺の誤りだった(gropu byがなくてもhavingは使える)
一点目はちょっと確証がもてないがやはり使えないのが正しそう
127 :
122 :2011/10/24(月) 00:17:07.35 ID:???
>>126 1点目は、たしかに純粋なSQL規格ではできないと俺も思う
が、これができない実装もみたことない
ほとんどのDBMSでNULLをリテラルとして書けるようになってると思う
(ちなみにSQL Serverで試して動いてるのは確認してる)
そこまで解ってるならトンデモ回答とか言わずにちゃんとそう指摘しろよ
NULLがリテラルとして使えない実装だとどうするの?カラム指定をしないってことかな
>>128 CASTのソース(NULLをCASTする)や、CASEでのNULLはOKらしいから、それでやるんじゃね
まあ、実際はテーブルには主キーがあるべきで、主キーがあれば、
列リストに主キーだけ指定したinsert文ながせば
主キー以外はデフォルト値入るからそうするべきじゃないかと
>>128 念のために言っておくが、insertで指定されなかったカラムに入るのは
あくまでもそのカラムのデフォルト値な
明示的にNULL以外をデフォルト値にしてる場合はその値になるし、
デフォルト値が指定されていない場合は多分NULLがデフォルト値になってると思うが
これが既定の動作かどうかはしらん
そういやPostgreSQLのダンプファイルとか見ると\nって書いてるな。
お安い御用です。
SQLの質問です。 DBMSはOracle11gR2です。 MST_A ID VALUE ---- ----- 1 MA1 2 MA2 3 MA3 MST_B ID1 ID2 VALUE ---- ---- ----- 1 1 MB1 2 2 MB2 3 3 MB3 DAT_A ID1 ID2 VALUE ---- ---- ----- 1 1 DA1 2 DA2 3 4 DA3 SELECT ma.VALUE,mb.VALUE.da.VALUE FROM MST_A ma,MST_B mb,DAT_A da WHERE da.ID1 = ma.ID AND ma.ID = mb.ID1 AND da.ID2 = mb.ID2; のSQL結果に、 DAT_AのID2がnullになっているデータ(VALUE=DA2) を含めたいのです。 MST_AとMST_Bはデータ件数が非常に多い(1〜2億件)ので、 できればUNIONで複数回読み込むのは避けたいです。 アドバイスよろしくお願いいたします。
オラクルならコレでよかったかなぁ。 SELECT ma.VALUE,mb.VALUE.da.VALUE FROM MST_A ma,MST_B mb,DAT_A da WHERE da.ID1 = ma.ID AND ma.ID = mb.ID1 AND da.ID2 = mb.ID2(+);
DAT_AのID2がnullのとき、mb.VALUEはどうしたいんだ? (+)でもouter joinでもいいけど、普通にDAT_Aに外部結合するだけでいいとおもうんだが?
SQLserverの質問です 以下のようなテーブルがあります *はユニークキーです。 DATE* ID1* ID2* VALUE _______________ 200103 AAA 111 20 200103 AAA 112 10 200103 AAA 113 55 200103 AAA 121 60 200103 AAA 122 54 200103 AAA 123 44 200103 BBB 111 24 200103 BBB 113 43 200103 BBB 114 11 200103 BBB 121 11 ・ ・ ・ 200104 AAA 111 20 200104 AAA 112 10 200104 AAA 114 5 200104 AAA 122 54 200104 AAA 123 4 200104 BBB 111 24 200104 BBB 113 43 200104 BBB 112 21 200104 BBB 121 11 200105 AAA 122 54 200105 BBB 113 43 200105 BBB 112 21 200106 AAA 123 4 200106 BBB 111 24 200106 BBB 112 21 これをDATE=200103とDATE=200104だけとってきて いかのように外部結合したいのですがどのようにすればよいでしょうか? FULL JOINを利用したのですがうまくいきません。 ID1 ID2 VALUE_201103 VALUE_201104 _________________________________________ AAA 111 20 20 AAA 112 10 10 AAA 113 55 NULL AAA 114 NULL 5 AAA 121 60 NULL ・ ・ ・ よろしくお願いいたします。
DATE=200103とDATE=200104でそれぞれ抽出、 ID1とID2でfull outer joinすればいい。
select case when T1.ID1 is not null then T1.ID1 else T2.ID1 end, case when T1.ID2 is not null then T1.ID2 else T2.ID2 end, T1.VALUE as VALUE_201103, T2.VALUE as VALUE_201104 from (select ID1, ID2, VALUE from TableName where DATE = 200103 ) T1 full outer join (select ID1, ID2, VALUE from TableName where DATE = 200104 ) T2 on T1.ID1 = T2.ID1 and T1.ID2 = T2.ID2 ;
SQLiteを使用しています。 DEFAULT値で、現在のレコード数count(*)を指定したいのですが、どう書けばいいでしょうか? create table t1 ( id integer primary key autoincrement, test integer default select count(*) from t1 ) 的なことをしたいです。
つ trigger
なるほど! こういうときにtrigger使うんですね。 言葉だけは聞いたことはあったのですが、 難しそうなのでスルーしてました。 調べてみます。どうもありがとうございます。
142 :
NAME IS NULL :2011/10/27(木) 19:45:31.79 ID:HJWr1HNd
あるカラムのMAXから+1した値をとりたいのですが SELECT (SELECT MAX(column) FROM t) + 1 で問題ないでしょうか?
SELECT MAX(column) + 1 FROM t でいいだろ
お安い御用です。
そして、ありがとう!
特定のidが持つintカラムから最も近いかつ小さい数字を持つidを求めたいのですが、 select id from t1 where int_col < (select int_col from t1 where id=特定のid) order by int_col desc でできたのですが もっとよいSQLありませんか?
まず日本語でちゃんと説明できるようになってくれ
intカラムとidの差の絶対値がもっとも小さいものを取得しないとだめじゃないか?
なので
>>147 はうまく動かない場合があるのでは。
150 :
>>147 :2011/10/29(土) 17:55:38.45 ID:dmfGtvmP
簡単にできるよ。主問い合わせでmax(id)とすれば、サブクエリのid未満かつ最も近いidがSELECTできるよ。
order by int_col desc だから、max(id)じゃなくて int_col=max(int_col)な行のidが欲しいんじゃないかと 元のSQLの何が気に食わんかしらんが、目的行だけ欲しいってなら having使えばいいんじゃね
すまん。よくよまずこたえてしまった
if select * from t where id=1 then update t set foo=bar where id=1 これをSQLで表現したいのですが可能でしょうか?
なにがしたいのか、さっぱりわからん
155 :
NAME IS NULL :2011/10/31(月) 01:19:52.99 ID:aQyfoOov
SQL命令で表(TABLE)を作る 1、本(コード・題名・著者名・出版社名・価格・在庫冊数) 2、出納(費用・本のコード・冊数・日付) 3、顧客(顧客コード・氏名・連絡先) 4、予約本(顧客コード・本のコード・予約日付・入荷日付) このまんまの問題がでたんだけど意味が全く分からない
>>153 レコードがあればアップデートってことだと思うんだけど、
それなら
update t set foo=bar where id=1
だけでよくって。
>>155 create table を4つ書けってこと。それでもまったくわからないのなら、基礎を勉強してくること。
158 :
NAME IS NULL :2011/10/31(月) 04:36:12.47 ID:aQyfoOov
>>157 例えば1の場合だと
CREATE TABLE 商品表
みたいに書けばいいのか?
>>158 え?商品表って言葉どっからでてきたん?
160 :
NAME IS NULL :2011/10/31(月) 04:46:55.70 ID:aQyfoOov
>>159 カオスになってきたのでヒントか答えくださいまし
161 :
153 :2011/10/31(月) 05:07:19.45 ID:???
>>156 ありがとうございます。
確かにそれで問題はないのですが、
id=1がなかったらエラーが返ってきて、
それをログに書き込むようにしてるため、
それを無くす前に、update前にid=1があるかを確かめたい感じです。
selectとupdateを分ければ可能ですが、
1度に書くことはできないかな?と思って質問しました。
>それを無くす前に それを無くす為にです。 日本語おかしくてすみません。
>>162 問題がないと言いつつエラーが返るという表現はおかしくないのかな
まずそのあやふやなエラーが何なのか聞く方が先だと思う
>>160 カオスも何も。
create table 本 〜
日本語が気に入らないなら create table books 〜 とかにすればいい。
>>161 なかった場合は、正常に0件更新されるはずだよ。
>>163 動作上は内部でエラーが出ても、
それを出力して動作を停止させるわけではないので問題がないといったのです。
Apacheでfavicon.icoがなかったらエラーログが書きこまれまくりますが、
イメージとしてはあれみたいな感じです。
>>165 エラーを貼る。
エラーが実は出力されていなかったら
>>155 に君が回答してあげると良い。
oracle11gのsqlplusで列名のみ表示したいのですがどうすればいいですか? desc テーブル名だと列名とタイプなどが表示されますが これを列名のみにしたいです。 いろいろ調べたら select * from user_tab_columns where table_name = 'テーブル名'; select column_name from user_tab_columns where table_name = 'テーブル名'; select * from all_tab_columns where table_name = 'テーブル名'; select column_name from all_tab_columns where table_name = 'テーブル名'; などでできると書いてましたが結果は no rows selectedになります。 よろしくお願いします
desc テーブル名 じゃだめかな
テーブル名を大文字で書いてないとか
>>161 普通updateがゼロ件更新してもエラーは返さんと思うが
誰がどんなエラー返してるのか書け
>>167 そういうDBMS固有の問題はそのDBMSのスレで聞け
標準的なSQLにテーブル定義を表示する文はない
> 標準的なSQLにテーブル定義を表示する文はない え?
ORACLEが始めたあの高名な問い合わせは今は使えないのかな。 30年近く前はこれだった。 select cname from col where tname='テーブル名';
INFORMATION_SCHEMA 使えよ・・・ せっかくANSIにあるんだからさ。
>>172 そういう独自実装をまとめるためにsql2003で定義された。
sql標準への準拠なんてまちまちだから、自分が使ってるRDBMSが対応してるかどうか調べてからじゃないと使えないけどな。
>>174 えっ
nullじゃないというのはどういう条件を指定すればいいのでしょう?@SQLite testはnull可能な項目で、 select test from t where test <> null ではだめでした。
is not null
179 :
NAME IS NULL :2011/11/04(金) 21:45:03.99 ID:gwC8AWlb
メールリストのメールに任意の個数のタグをつける場合の設計について教えてください。 以下のテーブルBのように、単純なメールIDとタグIDの対応表にすると、テーブルBが膨大な行数になるんですけど、気にしなくてOK? テーブルA:メールID,SendTo,本文,... テーブルB:メールID,タグID テーブルC:タグID,タグ名 アホな質問かもしれませんが、一般的にこうやってるもんですか? 以下のように、タグIDを10個くらい用意しておくのに比べてかなり遅くなりますか? (10個以下にしろと運用制限したら以下でも十分ではありますが) テーブルA:メールID,SendTo,本文,タグID1,タグID2,タグID3,...タグID10 テーブルC:タグID,タグ名
>>179 十分だといってるそのテーブルレイアウトで、あるタグが指定されているメールを抽出するのはどうするつもり。
DBを信じるんだ。そんで、数十億件とかになるなら考えよっか。
>>179 学問上、「正規化」と呼ばれる観点から言えば前者が正しい。
学問上正しい設計が実用に耐えうるかというのはまた別の話。
183 :
179 :2011/11/04(金) 23:19:30.78 ID:???
ついでに質問。
>>179 のような例で、
テーブルA:メールID,SendTo,本文,...,タグ名
テーブルB:メールID,タグID,タグ名
テーブルC:タグID,タグ名
上のように(たとえばタグ名で)データベースを重複させるのは御法度?それとも良くある話?
データ密度的に無駄でバグ要因でもあるけど、場合によっては効率は上がりそう。
スレ違いだって言ってる相手にお礼をいってる人間のなすこととは思えんな。
>>184 御法度。「場合によっては」なんて要件もクエリもろくに決まっていない
時点で無駄に効率云々に気を取られている時点で御法度。
教科書通り正規化しておけばよし。そして大抵はそれが一番無難に速い。
必ずしも正規化が良い結果を生むとは言い切れない. 高度に抽象化するとあとで他の人の理解を妨げることもある. どんくさくてもデータ量が少ないなら視認性の高いほうがいい.
スレ違いだっつーの。
すまん.
Oracle 10g R2を使用しておりまして、以下のようなSQL文を作り、結果をcsvに出力しようと思いました。 [例1] select テーブル1.名前,テーブル2.解法,テーブル3.手順 from テーブル1 LEFT JOIN テーブル2 ON テーブル1.解法フラグ = テーブル2.解法フラグ LEFT JOIN テーブル3 ON テーブル1.手順フラグ = テーブル3.手順フラグ; ところが、上記[例1]を使用して出力したところ、「テーブル1が全件出力されていない(気がする)」という旨のことを言われました。 それについて知人に聞いたところ、知人はいつも以下[例2]のような形で出力している、とのことでした。 [例2] select テーブル1.名前,テーブル2.解法,テーブル3.手順 from テーブル1,テーブル2,テーブル3 where テーブル1.解法フラグ = テーブル2.解法フラグ(+) and テーブル1.手順フラグ = テーブル3.手順フラグ(+); 自分で調べた限り、[例1]と[例2]で得られる結果は同一ではないかと思うのですが違うのでしょうか。 因みに、自分の環境での検証では同じ結果が得られていると思います。
select テーブル1.名前 from テーブル1 LEFT JOIN テーブル2 ON テーブル1.解法フラグ = テーブル2.解法フラグ LEFT JOIN テーブル3 ON テーブル1.手順フラグ = テーブル3.手順フラグ; select テーブル1.名前 from テーブル1; この結果を比較して、全件出ていない気がする人に見せる
今後、全件でてない気がするといわれるたびに同じことを繰り返し、 めんどくさくなったらSQLの勉強してくださいという。
知人の例にある(+)はOracle方言の外部結合演算子。 例1の場合テーブル1にはあっても解法テーブルや手順テーブルに対応する行が 無い場合は出力されない。 例2の場合はテーブル1は常に全件出力される。解法テーブルや手順テーブルに 対応する行が無い場合はそこにNULLがセットされる。 後者の様な動作が必要なのであれば例1のLEFT JOINを全てLEFT OUTER JOINに 書き換えれば同じ動作をする。 あといつも外部結合を使う様な知人の言うこともイマイチ信用できないので要注意。
left join と left outer join が等価でないソース希望
例1でテーブル1が全件出力されていないなら、ORACLEにバグがあるとしか思えん ORACLEってouter join周りはバグが多いと聞いたことがあるぞ その知人はそれ嫌って(+)で外部結合してるのかもしれん(昔の人でそれしか知らんのかもしれんが) とりあえずテーブル1の件数と出力件数比べてみればすぐわかるだろ あと外部結合使う人は信用できないって人もイマイチ信用できないので要注意
196 :
NAME IS NULL :2011/11/07(月) 18:05:09.78 ID:zwU0XuxP
PHPでMySQLかsqlite3を使おうと思っています。 表の先頭に新しい行を追加して、行の総数が指定した数(たとえば10)よりも多くなった場合は 多くなった分を表の末尾から削除して行数を一定以上に増やさないようにしたいのですがどうすればいいですか? ロケット鉛筆みたいに最大数が決まっていてはみ出たら押し出すみたいなことをしたいです。 表の先頭に追加して上限を超えたら最後尾から削除するんじゃなくて 表の最後尾に追加して上限を超えたら先頭から削除するのでもいいです。 どちらのほうが簡単かどうかもわかっていませんがよろしくお願いします。
>>196 まずRDBの表に先頭とか最後尾とかいう概念はないと理解してくれ
たとえば挿入日時とか、連番カウントアップの項目を作って
挿入日時や連番みて行を削除するのは可能
MySQLかsqlite3ってトリガ使えたっけ?
198 :
196 :2011/11/07(月) 18:54:58.85 ID:???
レスどうもありがとうございます。 順番とかないんですね・・・あまりに無知すぎて恥ずかしい。 ということは行の追加は普通に挿入すればいいんですよね。 で古い新しいの目印は、連番数字だとどんどん大きくなりすぎるから行を削除するたびにすべての行の連番数字をインクリメントしないといけないっぽいから ミリ秒かマイクロ秒の時間にして、 行数の取得は SELECT COUNT(*) FROM table で、最大数よりもはみ出ているかどうかはPHP側でチェックして、 はみ出ていたら時間がもっとも小さいものを削除してまた行数を取得して最大数よりも大きいかチェックして・・・の繰り返しですか? 最小の行の削除は DELETE MIN(time) FROM table でいいですか?
RDBMSによっては、循環型の連番を作ることができる。 けれど、数字が大きくなりすぎたからといって何の問題もないので連番でいいよ。 もし最大値まで使い切るような快挙を成し遂げた場合には、ここで報告してくれるとうれしい。
200 :
196 :2011/11/07(月) 20:43:44.60 ID:???
よくよく考えればミリ秒やマイクロ秒も数字がどんどん大きくなっていきますね・・・桁数に気をとられていました 行の総数が指定した数よりも大きいかとかの比較もSQLだけでできますか? 行数を取得(SQL)→指定した数と比較(PHP)→行数のほうが大きければ連番フィールドが最小の数字の行を削除(SQL)→ 行数を取得(SQL)→指定した数と比較(PHP)→・・・の流れは無駄ですよね 今のところ行の追加は一行ずつなのでこの流れも一周だけで済みますが それでもすべてまとめてSQLでできるならSQL→PHP→SQLとするよりもいいですよね
201 :
NAME IS NULL :2011/11/07(月) 22:46:30.23 ID:HMXQlM9n
こんなsqlをmysqlで書いたんだけど、sql文が正しくないって出てくる 何が間違ってるのか教えてください SELECT * FROM mycloud WHERE F_NAME = test.txt
SELECT * FROM mycloud WHERE F_NAME = 'test.txt'
>>200 どうしてもDB側でやりたければトリガーを使うしかない
アプリでやるのとそう変わらん
>>201 エスパーするとtest.txtが識別子じゃないんだろう
文字列リテラルならシングルクォートで括る
205 :
NAME IS NULL :2011/11/07(月) 23:05:10.72 ID:HMXQlM9n
>>203 ,
>>204 おお!とおりました!!ありがとうございます。
ここで聞いていいのか分からないのですが、
さっきの 'test.txt' をphpで変数に置き換えて↓のようなsql文を通したいのですが、
この場合どうすればいいのでしょう?
SELECT * FROM mycloud WHERE F_NAME = ".basename($_FILES['userfile']['name'])
basename($_FILES['userfile']['name'])をシングルコーテーションでくくるとエラーになってしまいます・・・
スレ違いだよハゲ
>>206 すいませんでした・・・
そして自己解決できました、お騒がせして申し訳なかったです
>>200 連番 サイクル 列1 列2 として
insert or update t1
連番 = select max(連番) + 1 from t1,
サイクル = (select max(連番) + 1 from t1) % 最大行数,
列1 = …
where
サイクル = (select max(連番) + 1 from t1) % 最大行数
的なアプローチがあるかもしれない。
サイクルってのは、存在する行の中で、
サイクリックに使われる連番で、最大10行としたら、0から9が使われて、それは連番を10で割ったあまり。
行数が決まってるなら、更新日時♪が最小の行をupdateすればよくね? アプリ起動(orインストール)時にダミーデータいれとく必要あるけど
なんだこの音符は
select * from test order by hoge desc ってのは構文としてよくないんですか? where 1とかちゃんといれたほうがいいんでしょうか?
Where は別にいらん むしろ*がだめ
>>212 ありがとう
*使わないように気をつけます
>>200 ためしてないけど、たとえばIDの順で10行のこすなら
delete from table t where
(select count(*) from table where id<=t.id) > 10
とかで行けるはず
これをトリガで仕込めばまあ自動的に10行に保たれるかな
>>211 構文としては問題ない。不要なwhere条件書く必要はないし、*がダメってこともない
ただ、実際にアプリ作る時に、不必要な列までselectするのは無駄が多いから
なるべく*使うなっていう考え方はある
count(*)っていけないのかなとふとおもった count(id)とかしてる例題あんまみないよね
count(id)よりcount(1)よりcount(*)がいい
>>215 count(id)とcount(*)では意味が違う
続きはwebで
結果は同じでしょう
219 :
196 :2011/11/08(火) 20:06:55.87 ID:???
>>204 ,208-214
レスどうもありがとうございます
調べたり試したりしてみます
>>217 なぜ引っ張る?つか続きも何も本文もwebだぞ、ここw
>>218 項目の数を数えるのと行の数を数えるという意味的な違いはさておくとしても
idがnot nullなら同じ数字になるが、必ずしも同じになる保証はないのだよ
昔はcount(*)よりcount(1)ってした方が早い処理系が存在したらしいが
今ではおそらくバッドノウハウだと思われ
DBMSはMysqlの5.0.87です。 +------+------------+---------+----------+ | id | product_id | assy_id | parts_id | +------+------------+---------+----------+ | 1 | 1 | 12 | 1 | | 2 | 1 | 12 | 2 | | 3 | 1 | 12 | 3 | | 4 | 1 | 12 | 3 | | 5 | 1 | 12 | 5 | +------+------------+---------+----------+ 上記のテーブルで、product_id、assy_id、parts_idが同じレコードが2行以上有るものを抽出したいのです。 上記の例だとidが3と4のレコードになります。
>>221 ためしてないけど
select id from テーブル t where
(select count(*) from テーブル product_id=t.product_id and assy_id=t.assy_id and parts_id=t.parts_id ) >=2
とか
select id from テーブル t1 join
(select product_id,assy_id,parts_id from テーブル group by product_id,assy_id,parts_id having count(*)>=2) t2
on t1.product_id=t2.product_id and t1.assy_id=t2.assy_id and t1.parts_id=t2.parts_id
とかでいけるんじゃね
select * from t1 where exists(select * from t2 where t1.id <> t2.id and t1.product_id = t2.product_id and t1.assy_id = t2.assy_id and t1.parts_id = t2.parts_id);
224 :
NAME IS NULL :2011/11/09(水) 20:51:56.87 ID:ViYEpCpP
行数の増減はほとんどなくても(たとえば1000行前後で推移してても)INSERTとDELETEを繰り返していると 断片化か何かで処理速度が落ちてきますか? あとこういう行数はほぼ一定だけど行の挿入削除が激しい場合はindexはあまり意味ないですか? いずれもデータベースによりますか?
RDBMSによるんだけど、大抵それに対する解決方法がある インデックスはそれが有効かどうかは行数に依存しない
226 :
NAME IS NULL :2011/11/09(水) 21:33:59.91 ID:ViYEpCpP
レスありがとうございます 解決策というのはVACUUMやOPTIMIZEをしろということですか?それとも 断片化しにくいorしても速度が落ちにくい方法があるってことですか?
スレ違いだからさっさとひっこめ RDBMSによるっていってんのにRDBMSも指定しないとか脳みそ足りてんのか
行の入れ替わりが激しい場合はどうなのかわからないけど 行数が少ないとインデックスの有効性はあまりなくない?
スレ違い。
・DBMS名とバージョン oracle11g ・テーブルデータ userテーブル id int name varchar ・欲しい結果&説明 idを外からバインド変数で渡し、 IDが一致するレコードと、 その一致したレコードとnameが一致するレコードの2レコードを取得したいです。 例) バインド変数:1 id name 1 aaa 2 bbb 3 aaa idが1と3のレコードを抽出したいです。 自己結合して1レコードとして取得することはできるのですが2レコード取得する方法が思いつきません。 宜しくお願いします。
select * from user where name in (select name from user where id = @id)
232 :
230 :2011/11/12(土) 09:36:24.85 ID:???
動的SQLでセレクトした結果をカーソルに入れて返したいんですが、可能でしょうか?
>>233 無理だな
どうしても書き換えるならUNIONだろうが、そっちのほうが速いとは限らない
>>234 普通はできるがプロシージャはDBMSによって全然違うので断言できない
>>233 そのサイトもそろそろ時代遅れになってるな
>>233 どうしてもORを使いたい場合ってのは、どうしてもORを使わざるを得ない場合を指してるんだよ。
>>236 たしかにね。すこし残念な気持ちに
Oracleスレ行け。
240 :
NAME IS NULL :2011/11/13(日) 18:56:02.92 ID:BfOCLmZi
・DBMS名とバージョン SQLite3 ・説明 SQLiteは、データベースを開くとき、指定したファイルがあればそれを開いて、 指定したファイルがなければそのファイル名のデータベースを作成してから開きますが、 そんな感じで、指定したテーブルがあればそのテーブルに対してinsert等の操作をして、 指定したテーブルがなければテーブルを作成してから操作をする、 みたいなことをしたいのですがどう書けばいいですか? テーブルの有無は、検索したら (SELECT count(*) FROM sqlite_master WHERE type='table' AND name='テーブル名') = 0 で判断できるとありましたが、 sqlite_masterテーブルはSQLite独自らしいので、一般的なテーブルの有無の確認方法があれば 教えてください。 テーブルが無いかもしれないのは、テーブルを削除しない限り初回の一回だけなのに、 毎回テーブルの有無を確認するのは変な気もするので、もし やりたいことを実現できる別のアプローチがあればその書き方を教えてください。 データベース自体をあらかじめ作っておくことは出来ません。
常にCreateを投げてエラーを無視すればいい。
>>241 レスどうもありがとうございます
エラーが出ないようにしないといけないものだと思っていましたが
そういうやりかたでいいんですね
SQLiteならcreate table if not existsなんていう構文もあるが
244 :
NAME IS NULL :2011/11/14(月) 12:12:37.77 ID:+RxR3+y0
MySQL5です。 shop id name 1 Aカンパニー 2 Bカンパニー 3 Cカンパニー area 1 北海道 2 青森 3 岩手 4 秋田 shop_area shop_id area_id 1 1 1 2 1 3 2 2 2 4 3 2 3 3 青森と岩手、両方に支店のある会社を抽出したいです。 shop_id name 1 Aカンパニー 3 Cカンパニー 「青森、岩手のどちらかに店舗のある」という条件でしたら SELECT shop.id AS shop_id, shop.name FROM shop_area INNER JOIN shop ON shop_area.shop_id = shop.id WHERE shop_area.area_id IN (2, 3) ORDER BY shop.id というので出来たのですが、「両方にある」という条件になったら書き方がわかりません。 よろしくお願いします。
246 :
244 :2011/11/14(月) 16:21:41.99 ID:+RxR3+y0
>>245 その1でできそうです。
ありがとうございます。
247 :
240 :2011/11/14(月) 18:49:33.36 ID:???
>>243 どうもありがとうございます
その方法でやってみます
248 :
233 :2011/11/14(月) 21:58:39.21 ID:???
ありがとうございました。
249 :
NAME IS NULL :2011/11/15(火) 02:39:47.73 ID:nW9WdTUJ
・MySQL5です ・テーブルデータ ID|名前|データ 01|鈴木|0001 02|佐藤|0002 01|鈴木|0003 ・欲しい結果 ID|名前|*|DATA1|DATA2 01|鈴木|2|0001 |0003 02|佐藤|1|0002 | ・説明:group by と count(*) を使うと↓のように、グループ化され消えてしまう列の値を(この場合`0003`の部分)、↑みたく、行に書出す方法はありますか? ID|名前|*|データ 01|鈴木|2|0001 02|佐藤|1|0002 ・補足:IDは1~1400、count数は1~97、DATAは1~4000位あります。
方言での実装になるのでMySQLスレにいくといいかも
GROUP_CONCATで1列にしてしまうとか簡単だぞ
カウント数が97とか、データが4000とか、97列とか4000列とかのデータが欲しいってか? 要件と設計みなおした方がいいんじゃねえか
254 :
249 :2011/11/15(火) 23:53:31.31 ID:???
ありがとうございました。諦めます。
255 :
249 :2011/11/16(水) 00:00:59.45 ID:???
あ、
>>251 さんの group_concat でイケそうです。
重ねて、ありがとうございました。
256 :
249 :2011/11/16(水) 00:16:50.67 ID:???
group_concat で欲しい結果を得る事ができました。(
>>249 の件 終了)
皆さん、本当にありがとうございました。諦めずに続けていきます。
初心者です。よろしくお願いします。 使用DBはMS-ACCESSですが専用スレがないのでここで質問してみます。 犬の誕生日が記録してあるデータが入ったテーブルがあります。 兄弟犬を抽出したいという要望です。 兄弟の定義は「母が同一かつ同時に出産した個体(同胎)」だとします。 母親は各データが持っていますが、同時出産でも誕生日が日付をまたぐことがあります。 2日にまたがる難産の場合もあると思われます。 ただし、出産は数ヶ月に一度です。 このような事象をグループ化して抽出するうまい方法はありますでしょうか? よろしくお願いいたします。
申し訳ありません。 自己解決しました。 とりあえずターゲットの犬がいてその犬の兄弟だけ抽出ということだそうなので ターゲットの犬の誕生日前後数日で検索すればよいことになりました。
【質問テンプレ】 ・DBMS名とバージョン:MySQL server 5.0 ・テーブルデータ unigram(elem1 text, probability double); (レコード数:500万件) bigram(elem1 text, elem2 text, probability double); (レコード数:1億件) trigram(elem1 text, elem3 text, probability double); (レコード数:4億件) ・欲しい結果 入力された文字列の組み合わせを1〜3のngramから検索し、その出現数を返す ・説明 例えば、A-B-C-D-Eという組み合わせがあったら unigramから[A][B][C][D][E]、5つの出現件数を bigramから[A-B][B-C][C-D][D-E]、4つの出現件数を trigramから[A-B-C][B-C-D][C-D-E]、3つの出現件数を それぞれ参照し、シェルに返します。 現状では、SQL文をループで回していて、 unigramでは5回、bigramでは4回、trigramでは3回、レコードを全件探索しています。 実行結果には満足しているのですが、探索件数が膨大であるため、A〜Eという簡単な組み合わせでも、 平均で40〜50分程度かかっています。 これを高速化(可能ならば10分以内に探索を終了させたい)させるとしたら、どのような方法が考えられますでしょうか? 文字列を全て一度に送って、全件探索を一度で済ませるようなことは出来るのでしょうか? ご教示願います。
trigramのテーブルが間違っていました。 trigram(elem1 text, elem3 text, probability double); となっていましたが、 正しくは trigram(elem1 text, elem2 text, elem3 text, probability double); :-elem2 text, を追加 です。宜しくお願いします。
orとunionで結べば1文にはなると思うけど
とりあえず、index使って全件検索しないようにしてみたら?
elem1にA-BとかA-B-Cとかいう文字列が格納されてるのか? とりあえずループまわしてるSQL書いてみ
>>259 >>261 と
>>262 が正解を出してるぞ。
フルスキャンの原因はどうせ左辺の列を合体させてるとかいうオチだろ…
elem1 || elem2 || elem3 = 'ABC' みたいな…知らんけど…
こういう場合は左辺はいじらずに右辺を工夫して索引検索させる。PGで条件となるWHERE句を可変にするとかして。
あとSQL発行は1回でもテーブルが3つあるから内部的には3回走るんでSQL3回発行とそんなに差は出ないかもしれない。
ただのカンだけどね…。
Aが出現しなければA-Bも出現しないので、そういうところで減らせたりしないのだろうか
今のSQLも実行計画もださないで今より早くって言われてもな >SQL文をループで回していて、unigramでは5回 まさかとおもうが、elem1='A'を検索するSQLを発行して、elem1='B'を検索するSQLを発行して...じゃないだろうな
関数つきのインデックス(だったかな?)、 なんて言ったかなあ、あらかじめ関数の結果をインデックス化しておくやつ それやっとけば速くなるかもね。
それって結局関数の結果をDBに収めてるのと同じだろ 関数の意味ねぇな
>>267 まんま、ファンクションインデックス
>>268 インデックスだからデータが更新されれば当然インデックスも更新されるわけで
マテリアライズドビューみたいな原則非同期更新のものとは違うという意味はあると思うけど
使ったことないけど気にはなっていたマテリアライズドビューが非同期ということに驚いた ありがとう
マテリアライズドビューが原則非同期ってのが気になって調べてみたら これって昔はレプリケーション用のスナップショットと呼ばれてた、らしい なるほど インデックス付きのビューとは用途が違ってるわけか
272 :
NAME IS NULL :2011/12/03(土) 00:08:31.30 ID:IuWrM6xt
【質問テンプレ】 ・DBMS名とバージョン SQLite3 テーブル作成時についての質問です。 複合NOT NULL制約みたいのはありますか? 例えば、 CREATE TABLE t ( a INTEGER NOT NULL PRIMARY KEY, b TEXT, c TEXT ) というテーブルがあったとします。 bとcはNULLでもよいのですが、 例えばbかcの片方がNOT NULLだった場合、 もう片方もNOT NULLでなくてはならないというような制約をつけたいです。 言い換えれば、両方NULLか両方NOT NULLかでないとだめということです。 そういうことはできますでしょうか?
CREATE TABLE t ( a INTEGER NOT NULL PRIMARY KEY, b TEXT, c TEXT, CONSTRAINT null_check CHECK ( (b IS NULL AND c IS NULL) OR (b IS NOT NULL AND c IS NOT NULL) ) )
274 :
272 :2011/12/03(土) 20:35:39.61 ID:???
>>273 ありがとうございます。
アプリケーション側ではできるのですが、DB側でも二重にしたかったので助かりました。
データバインディングされる値によっては、自己結合になるリレーションをする為に、 普通の結合の時も自己結合の式をかけてデータを取りだそうと思っているのですが、 やはりかなり処理が重くなるでしょうか? 普通 select * from tbl1 inner join tbl2 on tbl1.tbl2id = tbl2.id; 今回 select * from tbl1 a inner join tbl2 b on a.tbl2id = b.id;
>>275 ちょっとその日本語が何言ってるのかよくわからんが
その普通と今回とで実行計画とってみれば?
同じ実行計画なら同じ重さ
つかその二つで違う実行計画出すDBMSあったらびっくりだが
>>276 サイキック回答ありがとうございます。
「実行計画」と言うのが初耳でした調べて見ます。
>>275 その二つは別名の有無の差しかないけれど、上の日本語の内容を見ると、実際は実行計画の異なるクエリになるはずだな。
279 :
NAME IS NULL :2011/12/04(日) 21:23:27.65 ID:mtTsMo28
MySQL5.2、ストレージエンジンInnoDB、トランザクション分離レベルREPEATABLE READの場合の話ですが、 例えば先行トランザクションとして set autocommit = 0; update t set c2 = 'b' where c1 = 30 後発のトランザクションとして set autocommit = 0; select * from t where c1 = 30 このようなトランザクションを考えますと後発のトランザクションは待たされることなく処理されるのですが、 MySQLのドキュメントには「UPDATE ... WHERE ... は、検索が直面するすべてのレコード上に排他ネクストキーロックを設定します。」 と書かれています。 先行のトランザクションでは行に排他的ロックがかかってるはずですが、何故後発のトランザクションが読み取りに成功しているのでしょうか
InnoDBってバージョニングでしょ? 更新前のデータを読むんだろ
>>279 技術的興味で質問しているんだとしたら残念ながら回答にはならないけど、
もしこのことで何か困っているんだとすれば、ロックされるかされないかに
依存するようなプログラミングはしないこと。
頼っていいのはトランザクション分離レベルだけ。
>>281 更新の激しいテーブルをFOR UPDATEで確実に処理したいと思い、詳しく調べてみたら先述のような疑問が浮かんだという感じです
つか特定のDBMSの実装の問題はそのDBMSのスレで聞け
MySQL5.1を使っていて、パーティショニングについて疑問があるので質問させてください。 10億レコードのデータをパーティショニングしたテーブルを作成したいと思い、下記のSQL文を実行しました。 create table tbl1( shopname varchar(255) not null, itemname varchar(255) not null, id int, primary key(shopname, id) ) ENGINE=InnoDB partition by hash (id) partitions 100; これを実行したところ、特にこれといったエラーもなく作成されました。 現在はこのテーブルにload data local infileを用いてデータの書き込みを行っています。 実際にテーブルを利用する際は select id from tbl1 where shopname='...'; といった具合に、shopnameからidを検索する形になります。 パーティショニングのメリットは一定の式に基づいて分類保存することで、大規模なデータでも高速で参照できることだと伺いました。 確かに、パーティショニングを行った際に与えた数値を使うことが出来た場合には、そのように出来るかもしれませんが、 上記select文の様に、パーティショニングに使ったユニークIDを利用できない場合、どのパーティションにレコードが作成されているか分からない為、 パーティショニングを使わずに一つのテーブルで作成した場合とselect文実行にかかるコストは 変わらないのではないかと疑問に感じたのですが、やはりそうなるのでしょうか? まだデータの取り込みが終わっていないので実行していませんが、 各パーティションはshopnameで別途インデックス付けする予定です。 よろしくおねがいします。
selectの速度には影響がないかもしれない。 けど、インデックスの更新速度が速くなるのはメリットだと思うよ。 詳しくはMySQLスレで聞くといいかも
not nullなカラムに空文字が入って欲しくないんですけど これはcheckでやるしかないですか?
>>287 ほとんどのDBMSではちゃんとNULLと空文字列を区別するからそう
ただ一部区別できないDBMSがある。メジャーなやつだがな
MS?
SQLite?
オラクルさんじゃね
oracleです。 ・テーブルデータ テーブルA ID |状態 100|○ 100|○ 101|○ 102|○ 104|○ 105|× テーブルB ID |状態 100|○ 100|○ 100|○ 103|○ 105|○ 106|× ・欲しい結果 ID |AのCOUNT(ID)|BのCOUNT(ID) 100|2 |3 101|1 |null 102|1 |null 104|1 |null 105|null |1 ・説明: A,B各テーブルの状態が○であるものをID単位でカウントし、 AとBのテーブルを結合したいのですが、SQL1本で可能でしょうか? 結合する際、どちらかのテーブルのカウントが1以上であれば出力したいです。
Aがある場合とない場合に場合分けして union all で繋げ
select coalesce(A.ID, B.ID), A.cnt, B.cnt from (( select ID, count(ID) cnt from テーブルA where 状態 = '○' ) A full outer join ( select ID, count(ID) cnt from テーブルB where 状態 = '○' ) B) とか?
on A.ID = B.ID がぬけてた
AとBからIDを抜いてUNION、それにAとBを外部結合とか
NULLな項目でUNIQUEを指定すると、NULLがかぶってるときも登録できなくなりますが、 NULLはかぶってもよくて、NULLでないときはUNIQUEである必要があるというのは、 どんな感じに書けばいいでしょうか?
>>299 >NULLな項目でUNIQUEを指定すると、NULLがかぶってるときも登録できなくなりますが、
できるやつと出来ないやつがあるよ。
>NULLはかぶってもよくて、NULLでないときはUNIQUEである必要がある
だから最も簡単には、DBを「nullは皆ユニーク」と扱うやつに変えてしまう、かな。
301 :
NAME IS NULL :2011/12/08(木) 14:33:06.00 ID:Q8sIgK2f
MySQLで質問させてください。 ある条件で絞ったレコードを日付でソートして 最新のn件以降を削除したい場合はどのようなSQLを書くのが良いでしょうか?
DELETE FROM table WHERE プライマリキー NOT IN ( SELECT プライマリキー FROM table WHERE ある条件 ORDER BY 日付 DESC LIMIT n ) なんてのが出来るかどうかは、試してないから知らない。
ある条件に当てはまらないものまで消えてしまわないか?
304 :
301 :2011/12/08(木) 15:57:18.19 ID:Q8sIgK2f
>>302 ,303
なるほど。
not in使えばよかったんですね。
limitでn件目以降全てというのが見当たらなかったので困ってました。
ある条件をdelete分のwhereに追加して試してみたいと思います。
ご回答ありがとうございます。
MySQL5です。 programテーブル `program_id`,`program_name` titleテーブル `program_id`,`title_id`,`title` dataテーブル `program_id`,`title_id`,`data_id`,`open_flag` という感じで3つのテーブルがあります。 ここから、data.`open_flag`が'1'の物を含む、 title.`title`を、program単位でランダムに5件抽出したいと思っていますが、 SELECT ttl.`title` ,prg.`program_id` ,ttl.`title_id` FROM `title` AS ttl LEFT JOIN `program` AS prg ON prg.`program_id`=ttl.`program_id` LEFT JOIN `data` AS dat ON dat.`program_id`=ttl.`program_id` AND dat.`title_id`=ttl.`title_id` WHERE dat.`open_flag` = 1 ORDER BY RAND() LIMIT 0,5 とやった場合、同じprogram_idが重複して抽出される場合が出てきてしまいます。。 この場合、重複せず必ずことなる`program_id`から抽出するにはどうしたら良いでしょうか?
なんか難しい気がする
UNIQUEだとnullが重複させられないDBもあるのか と思って手持ちのDBで検証してみた <UNIQUEカラムがnullのレコードを複数入れられるか> Oracle:可 DB2:不可 SQL Server:不可 MySQL:可
>>305 SLECT t.title,t.program_id,t.title_id
FROM program p
JOIN (SELECT * FROM data WHERE open_flag = 1 AND program_id=p.program_id ORDER BY RAND() LIMIT 0,1) d ON p.program_id=d.program_id
JOIN title t ON t.program_id=d.program_id AND t.title_id=d.title_id
ORDER BY RAND()
LIMIT 0,5
とかで行けないか
2つの表を結合したあとに、nullなカラムにたいしてwhereでin演算子使ったら、 null項目が消えてしまいました nullを残すにはどうしたらいいですか?
where カラム in (xxx, yyy, zzz) ってやったってこと? 普通に where カラム in (xxx, yyy, zzz) or カラム is null でいいと思うんだが。 where カラム in (xxx, yyy, zzz, null) とできるかと思ったが、だめみたい@sqlite
> 普通に where カラム in (xxx, yyy, zzz) or カラム is null でいいと思うんだが。 順番が逆 > where カラム in (xxx, yyy, zzz, null) とできるかと思ったが、だめみたい@sqlite そらそうよ
312 :
NAME IS NULL :2011/12/10(土) 19:36:11.17 ID:W27PbLIP
access2000で NEN | TUKI 23 | 11 ってデータがあったら 平成23年12月31日のように常に次月末日を返したいのですが どのようなクエリになりますか?
翌月のマイナス一日。
314 :
NAME IS NULL :2011/12/10(土) 19:53:05.54 ID:W27PbLIP
DateSerial((NEN),Month(TUKI)+2,0) ってやったら 平成35年02月28日って返ってきてしまうのですが...
西暦にすればいんじゃね? NEN+1988
316 :
NAME IS NULL :2011/12/10(土) 20:10:40.26 ID:W27PbLIP
317 :
NAME IS NULL :2011/12/11(日) 04:02:19.30 ID:NKNPQTbf
検索結果の集合の共通部分は求められますか。 たとえばid=1の結果が{a, b, c, d}でid=2の結果が{b, c, e}なら{b, c}を求めたいです。
318 :
NAME IS NULL :2011/12/11(日) 04:08:53.97 ID:NKNPQTbf
tbl_rosen (駅名と備考は1:1) 路線名 駅名 備考 ---------------------- A線 i駅 備考1 A線 j駅 備考2 A線 k駅 備考3 B線 k駅 備考3 B線 l駅 備考4 B線 m駅 備考5 C線 n駅 備考6 D線 k駅 備考3 D線 o駅 備考7 tbl_shop 店名 最寄駅 --------------- X店 j駅 X店 m駅 X店 o駅 Y店 l駅 Z店 k駅 tbl_rosenは鉄道路線とその駅名のテーブル(1路線に対して1〜n駅ある)、 tbl_shopは、スーパーの名前と最寄駅(1店に対して0〜nの最寄駅がある) <やりたいこと> ・その店に鉄道で行くことが出来る駅のリストを作成したい ・ある特定の路線は除外(上の例だと、D線は対象外) ・乗り換えは考慮しない。 →例えば、Z店はk駅が最寄りで、k駅はA線、B線、D線の乗り入れ。D線を除外すると、 i、j、k、l、m駅から電車(±徒歩)でZ店に行ける <最終的に出力したいテーブル) tbl_output 店名 最寄駅 備考 ---------------------- X店 i駅 備考1 X店 j駅 備考2 X店 k駅 備考3 X店 l駅 備考4 X店 m駅 備考5 Y店 k駅 備考3 Y店 l駅 備考4 Y店 m駅 備考5 Z店 i駅 備考1 Z店 j駅 備考2 Z店 k駅 備考3 Z店 l駅 備考4 Z店 m駅 備考5 2段階に分ければ(駅で結合して店名、路線名でグループ化(D線除外)した テンポラリテーブルをつくって、さらにtbl_rosenと結合する)普通にできるのですが、 出来れば一発のSQLで出力したいのですが、SQL自体にまだ馴染みが薄く、 どのように書いて良いのかわかりません よろしくお願いします(PostgreSQL8.4です)
> (駅で結合して店名、路線名でグループ化(D線除外)した > テンポラリテーブルをつくって、さらにtbl_rosenと結合する) これをサブクエリでやればいいと思う。 exists使えば少しすっきりするかもだけど。
>>319 SELECT 店名, 駅名, 備考
FROM
(SELECT 店名, 路線名 FROM tbl_rosen, tbl_shop
WHERE tbl_shop.最寄り駅名=tbl_rosen.駅名
GROUP BY 店名, 路線名
HAVING not in ('D線')) AS tmp, tbl_rosen
WHERE tmp.路線名=tbl_rosen.路線名;
雑で冗長だけど、これでいけるかな…
あ、最寄駅にはnullがありうるから、ダメかもw
select 店名,最寄駅,t2.路線名,t2.駅名,t2.備考 from tbl_shop join tbl_rosen t1 on 最寄駅=t1.駅名 join tbl_rosen t2 on t1.路線名=t2.路線名 where t1.路線名 <> "D線" とかでダメか?
【質問テンプレ】 ・DBMS名とバージョン MySQL 5.1 ・テーブルデータ ・欲しい結果 ・説明 テーブル「カート」 カラム 「セッションID」「商品種別」「カートに入れた時刻」 テーブル「カート詳細」 カラム 「セッションID」「商品コード」 テーブル「商品リスト」 カラム「商品コード」「商品種別」 というテーブルがあります。 最後にカートに入れた時刻から12時間以上経過したセッションIDを検索して、 そのセッションIDを持つレコードを「カート」「カート詳細」の両方から 全て削除したいのです。 同じセッションIDを持つレコードは、両方のテーブルに複数あります。 「注文」テーブルで「セッションID」「商品種別」の組合せはユニークで、 「注文詳細」テーブルでは「セッションID」「商品コード」の組合せにユニークです。 結合や副問い合わせを試してみましたが、うまいこと抽出できません。 SQLで書くやり方があれば教えてください。よろしくお願いします。
>>323 正確には抽出だけならこの文でできました。
SELECT * FROM カート, カート詳細 WHERE カート.セッションID =
カート詳細.セッションID AND カート.セッションID IN (SELECT
セッションID FROM カート詳細 WHERE カートに入れた時刻 <
unix_timestamp()-12*60*60
削除がうまいこといきません。
>>325 これでたぶん希望通りに動作するようですが、あってますか?
DELETE カート, カート詳細
FROM カート, カート詳細
WHERE カート.セッションID = カート詳細.セッションID
AND カート.セッションID
IN (SELECT tmp.セッションID
FROM (SELECT セッションID FROM カート
WHERE カートに入れた時刻 < unix_timestamp() - 12 * 60 * 60)
AS tmp)
カート.セッションID IN (SELECT tmp.セッションID FROM (SELECT セッションID FROM カート WHERE カートに入れた時刻 < unix_timestamp() - 12 * 60 * 60) AS tmp) って カート.セッションID IN (SELECT セッションID FROM カート WHERE カートに入れた時刻 < unix_timestamp() - 12 * 60 * 60) でいいんじゃないの
>>327 SELECT文ならそれでいいんですが、DELETE文でやると
>>325 の
You can't specify target table 'xxx' for update in FROM clause
というエラーが出るので、同じ内容の一時テーブルを作る必要があります。
・DBMS名とバージョン MySQL 5.1 InnoDBのトランザクションを使ってオートインクリメントをすると 連番にならず、番号が飛ぶのですが、仕様ですか? INSERTする行数だけ飛びます。 1,2,3,4,5の5行をINSERTすると、5個欠番で次のデータが11,12,13となり、 3個欠番で次は14からスタート。 飛んでも問題はないので気分の問題ですが。 書いてる文はこのような感じです。 BEGIN; REPLACE INTO カート詳細 VALUES ('default', いろいろ); INSERT INTO カート VALUES ('default', いろいろ) ON DUPLICATE KEY UPDATE いろいろ; COMMIT; 'default'は連番の入っているカラムです。 上の文はINSERT INTO ... ON DUPLICATE KEY UPDATEも試しましたが同様です。 下の文はREPLACEでは都合が悪いです。 REPLACEだとDELETE権限が必要なので、できればINSERT ... ON DUPLICATE KEY UPDATEの方が好ましいです。
>>323-328 そもそも一つのDELETE文で複数テーブルから削除できるのって、標準的な動作なのか?
delete from カート詳細 where セッションID in (select セッションID from カート where 省略)
delete from カート where あと同じ
の二つのSQL流せば良いんじゃ(REPEATABLE READ以上の分離レベルで)
>>329 それはSQLの問題じゃなくてMySQLの仕様の問題なんで、MySQLのスレで聞け
>>330 そうか、その順番で2つのSQLを流せば無事に全部消えてくれますね。
一つで一気にやろうとばかりしていました。
ありがとうございました。
oracleです。 ・テーブルデータ テーブルA ID |日付 100|10/1 100|10/2 100|10/5 101|11/1 102|11/1 102|11/2 103|12/1 テーブルB ID |期間(自)|期間(至) 100|10/1 |10/4 101|10/1 |10/30 102|11/1 |11/5 103|12/1 |12/1 ・欲しい結果 ID |期間内のカウント 100|2 101|0 102|2 103|1 ・説明: IDをキーに、期間内のIDごとのカウントをとりたいです。 SQL1本で取得する方法はありますでしょうか? 列は増やしたくないです。
select t.ID, (select count(*) from テーブルA where ID=t.ID and 日付>=t.期間(自) and 日付 <=t.期間(至) ) as 期間内のカウント from テーブルB t
334 :
NAME IS NULL :2011/12/17(土) 03:04:07.64 ID:mcufmMSb
mysqlで質問です。 | col1 | col2 | col3 | col4 | col5 | col6 | | 3 | 1 | 0 | 5 | 4 | 12 | | 2 | 5 | 6 | 0 | 1 | 8 | のようなテーブルで 複数の条件、例えばA,B,C,D,E,Fで このうちの3つの条件がいずれかでもあえば そのレコードを取得するというような クエリは可能でしょうか。 イメージ的にはLOTO6で5等に該当するレコードは全て取得するといった 感じなのですが。
A and (B or C or D or E or F) or B and (C or D or E or F) or C and (D or E or F) or D and (E or F) or E and F
336 :
NAME IS NULL :2011/12/17(土) 15:09:53.77 ID:6xQtD/Up
下の処理をTRANSACTIONにした場合に、(f)のLinkTableの登録で、 以前はlast_insert_rowid()で取得していたarticleIDとcategoryIDの値が分からず困っています。どうしたら出来ますか? こういう場合は、AUTOINCREMENTのlast_insert_rowid()をあてにせずに、自分でIDTable.idの値を管理するべきですかね? insert into IDTable (type) VALUES (0); //(a)articleID登録 insert into ArticleTable (articleID,name,contents) VALUES (last_insert_rowid(),"..",".."); //(b)記事を追加 insert into IDTable (type) VALUES (1); //(c)categoryID登録 insert into CategoryTable (categoryID,name) VALUES (last_insert_rowid(),".."); //(d)カテゴリ追加 insert into IDTable (type) VALUES (2); //(e)LinkTable用のID登録 insert into LinkTable (id,articleID,categoryID) VALUES (last_insert_rowid(),articleID,categoryID); //(f)記事とカテゴリのリンクを追加
case when col1 in (A, B, C, D, E, F) then 1 else 0 end + case when col2 in (A, B, C, D, E, F) then 1 else 0 end + case when col3 in (A, B, C, D, E, F) then 1 else 0 end + case when col4 in (A, B, C, D, E, F) then 1 else 0 end + case when col5 in (A, B, C, D, E, F) then 1 else 0 end + case when col6 in (A, B, C, D, E, F) then 1 else 0 end >= 3
>>336 rowid変えない、変わらない自信があるならいいのかもしれないけど。
シーケンス使ったほうがいいと思うよ。
特定のDBMSの実装にかかわる問題はそのスレで聞けよ
実装に依存しないように書き換えればいいじゃん
341 :
336 :2011/12/18(日) 05:32:44.68 ID:???
>>338 参考になりました。ありがとうございます。
自己レスですが、とりあえず以下のようにTEMPORARY TABLE使って処理しました。
CREATE TEMPORARY TABLE IF NOT EXISTS categoryArticle(categoryID INTEGER, articleID INTEGER);
DELETE FROM categoryArticle;
INSERT INTO categoryArticle(categoryID,articleID) VALUES (-1,-1);
insert into IDTable (type) VALUES (0);
UPDATE categoryArticle set articleID=last_insert_rowid();
insert into ArticleTable (articleID,name,contents) VALUES (last_insert_rowid(),"..","..");
insert into IDTable (type) VALUES (1);
UPDATE categoryArticle set categoryID=last_insert_rowid();
insert into CategoryTable (categoryID,name) VALUES (last_insert_rowid(),"..");
insert into IDTable (type) VALUES (2);
insert into LinkTable (id,articleID,categoryID) VALUES (last_insert_rowid(),(select articleID from categoryArticle),(select categoryID from categoryArticle));
DROP TABLE categoryArticle;
344 :
NAME IS NULL :2011/12/19(月) 23:18:14.97 ID:bmyt5mT+
MySQL 5.1 使用しています。 出勤カレンダーを作って、工程表を作りたいのですが、出勤日テーブルに 出勤日テーブルは以下のようにして T_出勤日 日にち, 出勤 ---------------- 1月5日 ○ 1月6日 ○ 1月7日 × 1月8日 × 1月9日 ○ 「今日」が出勤日(○)として、「今日の前の出勤日からはじめて、 今後の出勤日」を抜き出すSQL文はどう書いたらよいのでしょう? つまり、「今日」が2番目に来るような抜き出し方です。 一応、考えたのは (SELECT 日にち FROM T_出勤日 WHERE 出勤='○' AND 日にち<DATE() LIMIT 1) UNION (SELECT 日にち FROM T_出勤日 WHERE 出勤='○' AND 日にち>=DATE() ORDER BY 日にち ASC); これより簡潔に書けるでしょうか?
select 日にち from T_出勤日 where 出勤 = '○' and 日にち >= (select MAX(日にち) from T_出勤 where 出勤 = '○' and 日にち < date()) たいしてかわらんか。
346 :
NAME IS NULL :2011/12/19(月) 23:59:04.63 ID:bmyt5mT+
なるほど… LIMIT が使えないDBでもいけそうですね。 ありがとうございます。
>>346 ああ、
>>344 はLIMITつかってるから、1個目のサブクエリにもORDER BYいるよ
348 :
NAME IS NULL :2011/12/21(水) 22:08:24.22 ID:J0OL2EsB
(質問) チェックボックス値による検索を行いたいと思っています。 MYSQL5.1 T1 マスタテーブル ID | DATE | DATA --+----------+----- 1 | 2007-11-11 | aaa 2 | 2007-11-11 | bbb 3 | 2007-11-10 | ccc T2 チェックボックステーブル1 ID | cate1 | --+--------- | 1 | 201 | 1 | 202 | 1 | 205 | 2 | 202 | 2 | 203 | 3 | 203 | 3 | 204 | T3チェックボックステーブル2 ID | cate2 | --+--------- | 1 | 401 | 1 | 403 | 1 | 404 | 3 | 403 | 3 | 404 | 3 | 405 | このような3つのテーブルから、下記のように出したいがどうすれば T2で 201、202、を含み 且つ T3で 403 を含む 結果 T1のIDレコード 1 | 2007-11-11 | aaa 試した事 select * from `T1` join `T2` using(ID) join `T3` using(ID) where cate1 in(201,202) and cate2 in(403) group by ID having count(*)=?? 絞るのにカウント数がT1、T2のチェックレコード数で 可変するので詰まっています。 そもそも、考え方がおかしいのかもしれません。 良い方法をご教示ください。
そのまま having count(*)=2 でいいんじゃないの?
351 :
NAME IS NULL :2011/12/22(木) 11:41:54.44 ID:UVOXMIfK
解決気味です。 上記を諦め、 T1 マスタテーブル ID | DATE | DATA |ckbox --+----------+----- |------ 1 | 2007-11-11 | aaa | 201,202,205,401,403,404 2 | 2007-11-11 | bbb | 202,203 3 | 2007-11-10 | ccc | 203,204,403,404,405 上記の形式にして select ID,DATE,DATA from `T1` where CONCAT(',',chkbox,',') like '%,201,%' and CONCAT(',',chkbox,',') like '%,202,%' and CONCAT(',',chkbox,',') like '%,403,%' こういった形で取得。 チェックボックスは計300個程ありそれぞれユニークを振っています。 チェックされている数は平均50個程。 レコード数は約1万程なのですがこの方法で大丈夫かどうか心配です。
352 :
NAME IS NULL :2011/12/22(木) 12:06:22.77 ID:UVOXMIfK
>>349 3テーブル分の重複があり2ではありませんでした。
2テーブルであれば送ったINのカンマ割り分だけで
大丈夫だったのですが
>>350 この機会にexists勉強してみます。
見当が付かないですが;;
MySQL 5.1 株価テーブル kabuka stock_code ←銘柄コード vol_date ←出来高年月日 sp hp lp cp vol 銘柄マスタ stock_info stoc_code ←銘柄コード shkbn ←商品区分(0,1,2,3,4) stk_name ← 銘柄名 delete_flg 削除区分 〜その他いろいろな項目 銘柄マスタの商品区分0及び1は除外して銘柄名を付けて株価テーブルから銘柄ごとの最古登録日と最新登録日の一覧を出したい select a.stock_code,stk_name,shkbn,min(vol_date),max(vol_date) from kabuka a inner join stock_info b on a.stock_code = b.stock_code where a.stock_code in (select b.stock_code from stock_info where delete_flg=0 and shkbn not in(0,4)) group by a.stock_code order by shkbn,a.stock_code; で、上記のSQLを書いてみたんですが、shkbnが0及び4のもでてしまいます 出さないようにするにはどうすればいいのでしょうか?
>>351 existsつかうとこんなん。
select * from T1 where
exists (select * from T2 where T2.ID = T1.ID and T2.cate1 = 201)
and exists (select * from T2 where T2.ID = T1.ID and T2.cate1 = 202)
and exists (select * from T3 where T3.ID = T1.ID and T3.cate1 = 403)
>>353 > where
> a.stock_code in
> (select b.stock_code from stock_info
> where delete_flg=0 and shkbn not in(0,4))
これって
where
b.delete_flg=0 and b.shkbn not in(0,4)
じゃだめなん
356 :
NAME IS NULL :2011/12/22(木) 18:06:30.45 ID:MkKdS3zo
>>355 ありがとうございます!
こういうのは、明示的にしておかないといけないってことなんですかね?
>>356 銘柄テーブルのstock_codeがユニークならそうならない気もするけれど、レイアウトが不明なのでちょっとわからんです
358 :
348 :2011/12/22(木) 21:06:34.01 ID:UVOXMIfK
>>354 サブクエリの中で全部行う事が必要かと思っていました。
通常クエリでexistsサブクエリ群をANDで繋げるだけだったのですね!
今後はご教示頂いたSQLコードで作っていきます!。
何か道が開けたような気持ちです。有り難う御座います。
聞いてみようと思ってきたら、答えがよくある質問1でワロタ
360 :
354 :2011/12/22(木) 22:36:51.23 ID:???
>>358 やったことないけど、これでも出来そう。
select * from T1 where ID in (
select ID from T2 where cate1 = 201
intersect
select ID from T2 where cate1 = 202
intersect
select ID from T3 where cate2 = 403
)
もしかすると intersect all の方がよいかも。
( ´Д`)y━・~~
365 :
NAME IS NULL :2011/12/27(火) 19:24:21.52 ID:P41//Np9
・DB名:Firebird1.03 ・テーブル ■メイン 受注番号 受注日 注文社 11 2011/12/20 A社 12 2011/12/21 B社 ■サブ 連番 受注番号 商品コード 数 50 11 A10 100 51 11 C30 20 52 12 A10 10 ■商品 商品コード 商品名 カテゴリ 納品番号(商品ごとで重複していません) A10 コート 洋服 100 C30 帯 和服 504 メインの受注番号とサブの受注番号、サブの商品コードと商品の商品コードで リンクしています。 欲しい結果 受注日の期間(いつからいつまで)と、商品のカテゴリと納品番号で、 受注の全内容(商品)が知りたいです。 受注日:2011/12/01から12/31まで カテゴリ:洋服 納品番号:100で検索をして 受注番号 受注日 注文者 商品コード 商品名 数量 11 2011/12/20 A社 A10 コート 100 11 2011/12/20 A社 C30 帯 20----★ 12 2011/12/21 B社 A10 コート 10 ★受注の全内容が知りたいので、該当する受注番号のサブはすべて表示 したい。メインの内容は重複表示となります。 丸投げですみませんが、どなたかSQL文をお願いできませんでしょうか。 テーブルが3つになるとどうしてよいものかわからないです。 よろしくお願いします。
2つだったらわかるのか?
たしかに、3つになるとわからないって理由で教えちゃまずい気がする
括弧でくくったことないかもしれん
370 :
365 :2011/12/27(火) 23:43:48.20 ID:P41//Np9
変な言い回しをしてすみません。 2つの場合、サブの商品コードで検索するのであれば SELECT * FROM メイン M WHERE M.受注番号 = (SELECT S.受注番号 FROM サブ S WHERE S.商品コード = ?); とかで、いけそうに思うのですが・・・。
>>370 2つのテーブルでうまくいってるという表現が誤解を与えたかもしれない。
サブの商品名出せないでしょ
とりあえずjoinを学ぶこと
372 :
365 :2011/12/27(火) 23:59:07.97 ID:P41//Np9
>>368 私が勘違いしてるのかもしれませんが、自分の解釈でそのページのやり方
をすると、カテゴリ・納品番号で検索だと、例えば、それぞれ洋服、100
だと、商品コードA10のデータしかでてこなくなります。
A10を含む、受注データを検索したいので、その方法がわかっていません。
>>370 で書いたコードだと、速度的にも問題がありそうに思いもっと
スマートな方法があるようにも思っています。
ご指導よろしくお願いします。
373 :
365 :2011/12/28(水) 00:08:00.65 ID:NV8y9xjw
>>371 そうですね。サブのデータを引っ張ってないですね。
JOINだと、メインとサブと商品をくっつけても、
>>372 の例のように
受注番号 受注日 注文者 商品コード 商品名 数量
11 2011/12/20 A社 A10 コート 100
12 2011/12/21 B社 A10 コート 10
しか該当しないんじゃないでしょうか?私は誤解してますでしょうか?
該当する受注番号のデータすべてを抽出したいのですが・・・。
11 2011/12/20 A社 C30 帯 20
のデータも必要なんです。
JOINのしかたはわかってるんだ?
じゃあ、あとは
>>370 のサブをさらに商品.納品番号で絞ればいいんじゃね?
>>373 まっすぐ考えるとこんな感じ。
select 受注番号, 受注日, 注文者, 商品コード, 商品名, 数 as 数量
from ほしい情報があるテーブル
where 受注日 between '2011/12/01' and '2011/12/31'
and 受注番号 in (対象となる受注番号)
ほしい情報があるテーブルを作る
main join sub using (受注番号) join 商品 using (商品コード)
対象となる受注番号は商品コードを元に得られる。
select 受注番号 from サブ where 商品コード in (対象となる商品コード)
商品コードを得るためには、商品テーブルを見ればよい。
select 商品コード from 商品 where カテゴリ = '洋服' and 納品番号 = 100
(納品番号がユニークだということなので、カテゴリで絞り込む意味はないかもしれない)
商品コードを得たので、組み合わせる。
select 受注番号 from サブ where 受注番号 in
(select 商品コード from 商品 where カテゴリ = '洋服' and 納品番号 = 100)
受注番号を得たので、全部組み合わせる。
select 受注番号, 受注日, 注文者, 商品コード, 商品名, 数 as 数量
from main join sub using (受注番号) join 商品 using (商品コード)
where 受注日 between '2011/12/01' and '2011/12/31'
and 受注番号 in (
select 受注番号 from サブ where 受注番号 in
(select 商品コード from 商品 where カテゴリ = '洋服' and 納品番号 = 100)
)
他にもいろいろ書き方はあるけれど、まずはこれから。
それから、速度的に問題があると思うと書いているけれど、時期尚早。
正解を教えてるフリをして嘘を教える いやらしいな
379 :
NAME IS NULL :2011/12/29(木) 01:00:28.56 ID:SVpsIQoX
CREATE TABLE `comment` ( `comment_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `entry_id` int(11) unsigned NOT NULL, `user_id` int(11) unsigned NOT NULL, PRIMARY KEY (`comment_id`), KEY `entry_id` (`entry_id`), KEY `user_id` (`user_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ブログのどの記事(entry_id)にどのユーザー(user_id)がどのコメント(comment_id)を投稿したかを記録するテーブルで、 同じユーザーが同じ記事に複数のコメントを投稿できます。 ここから「コメントを投稿した記事の数」が多い順にユーザーを取得したいのですが、どう書けばいいですか? SELECT * FROM comment ORDER BY GROUP BY user_id ORDER BY COUNT(DISTINCT(entry_id)) desc としてみたのですが上手くいっていないみたいで… よろしくお願いします。
>>378 それが高専卒IT下請けドカタっちゅうもんやろ( ´Д`)y━・~~
>>379 いらんとこにORDER BYがあるのは置いといて
GROUP BYするSELECTに*は使えないのが普通
グループしてる項目か集計関数つかえ。この場合はuser_idだな
383 :
365 :2011/12/29(木) 22:43:38.47 ID:MUHtF/FL
>>376 考え方はわかります。370の延長なので。
typo修正すれば動作します。378,381のような知ったかぶりは気にしないでください。
ありがとうございました。
速度は時期尚早とのコメントもいただきましたが
実際は、360万件の受注データで実行すると、数分かかります。
(5件くらいのデータなら即答します。)
WEBからの利用なのでタイムアウトの可能性がでてきます。
利用DBでは、usingは使えないのでonで書き換えましたけれど。
他の書き方はとはどんなものなのでしょうか。
私の質問の仕方が良くなかったせいか、JOINについてのアドバイスをいただいて
いますが、JOINの使い方程度はわかっています。(WHERE =だと複数が通らない
のを忘れていたのは凡ミスでした。反省。)
>>383 まずは納品番号にインデックスをはる。
カテゴリを抽出条件に使う必要があるのなら、それも考慮する。
で、クエリプランを見る。
385 :
365 :2011/12/30(金) 09:43:06.53 ID:???
>>384 納品番号・カテゴリのあるアイテムテーブルは即答するのでどうなんでしょう。
恐らく、ネックになっているのは、
受注番号のサブクエリからの検索と、
どうも一番最後に日付の検索をしているところだと思うのですが
具体的にどうすればいいのか検討がつかないです。
>>385 おそらくじゃなく、プランを見る
日付にインデックスをはる
Firebirdでインデックスのマージが行われるかどうかは知らないので、その辺は適宜がんばれ
388 :
365 :2011/12/30(金) 15:53:48.84 ID:???
>>386 クエリプランを見るとは具体的にどうすることでしょうか?
各クエリ毎に分割して感覚として掴んでいるのですが・・・。
日付のインデックスは別のパフォーマンスが落ちるので残念ならが付けられません。
(トランザクションの日付データってインデックス張らないと思うんですが)
>>387 私も解りませんが、結合している項目はすべてインデックスがあるので
その辺りは余地があまりないかと。
WHERE XXX IN (subQuery)のパフォーマンスがこんなに悪いとは・・・。
バージョンが古いのもあるんでしょうね。
>>388 inがおそいDBはexistsに置き換えたほうがはやい場合も。昔のPostgreSQLもそうだった。
でもプランを見ないことには話にならない。
統計情報が更新されていないのかもしれないし、オプティマイザに対してヒントを与えるべきかどうかも判断できない。
firebirdよくしらないけど、こういうのでてきたよ。
http://blog.kimuradb.com/?eid=877186 時期尚早だといったのは、目的のデータを抽出できない段階で速度云々言ってることに対して。
> 日付のインデックスは別のパフォーマンスが落ちるので残念ならが付けられません。
> (トランザクションの日付データってインデックス張らないと思うんですが)
やってみてから言おうよ。
すんません、質問です。 高専卒IT下請けドカタの方いらっしゃいますぅ〜?( ´Д`)y━・~~
おっさんは回答もしなければ質問もしない、何のためにスレにくるんだ
>>392 いま質問しとるやんけ(爆笑)
ちなみにマジで疑問に思っとるんやけど、ホンマどうして高専卒とか専門卒のドカタどもはプライド高いん?
ホンマにこれには答えて欲しい
そりゃスレ違い
あんたら意地悪やなぁ。
365とか370みたいなんにわざわざサブクエリなんて要らん、単純なjoinだけでええ
ということを誰も言うてやらんやなんて。
>>365 みたいな丸投げ希望に応じてやる気は無しで、
自分で学んで考えろ方針はええとして、それなら最低でもサブクエリみたいな
(今回の場合は)馬鹿げたとこ迷い込んでるのは指摘したらんと。
とりあえず
>>370 なんか
SELECT tm.受注番号, .... , ts.商品コード, ...
FROM
メイン tm,
サブ ts
WHERE
ts.商品コード = 検索したいコード
AND ts.受注番号 = tm.受注番号
これでええんちゃうの?
その指摘は一周遅れてる
正解を教えてるフリをして嘘を教える いやらしいな
398 :
365 :2011/12/31(土) 10:13:27.83 ID:???
>>395 それだと、一つの商品しか検索できないんじゃ・・・。
あまりいいたくはないんですが、要件を理解されていますか。
私の質問が言葉足らずだったり、誤解が生じるものだとしても、
本質を理解いただけないのは、私の能力不足だけではないと思います。
399 :
365 :2011/12/31(土) 10:20:46.26 ID:???
>>389 firebirdについて調べてくれてありがとう。お手間を取らせました。
そっち方面は調べてみます。
ところで、existsってレコードが存在する、しないくらいしか使ったことが
ないのですが、inを置き換えるというのはどうするのでしょうか。
・・・日付の件は、受注データの登録・更新作業のプログラムで
速度が遅くなるという判断がなされたので不可なのです。
365の要件だとどんな書き方をしても select * from main where 受注日 between '2011/12/01' and '2011/12/31' というクエリ単体の速度を超えることはないだろう このクエリの速度でなんとか我慢できるなら そこを先にやれば全体としてもどうにか我慢できる速度にはなるかもしれない select 受注番号, 受注日, 注文者, 商品コード, 商品名, 数 as 数量 from (select * from main where 受注日 between '2011/12/01' and '2011/12/31') join sub using (受注番号) join 商品 using (商品コード) where 受注番号 in ( select 受注番号 from サブ where 受注番号 in (select 商品コード from 商品 where カテゴリ = '洋服' and 納品番号 = 100) )
いや、納品番号のカーディナリティがメインに対して比較的高ければ メインのfull scanは必要ない可能性もあるよ。 Firebirdのプランナがどのくらい賢いかはわからんけど。
特定の商品カテゴリが特定の期間にしか売れないとか、 商品カテゴリが大量にあるとかならそれもありえるかもしれんけど、 いずれの場合でも指定する商品カテゴリによって 処理速度がかなり左右されることになるだろうねえ
403 :
NAME IS NULL :2011/12/31(土) 20:47:19.60 ID:1ddnDqlq
mysql Ver 14.14 Distrib 5.5.8, for Win32 (x86) mysql> insert question_tb (question_id,purchase_date,purchase_price,star) values (1,2011/11/10,1000,4); と購入日2011/11/10と入力すると、購入日が 18.2818181となってしまいます。 phpでやると2011/11/22のように登録されます。/の記号がダメなのでしょうか?
>>403 insert question_tb (question_id,purchase_date,purchase_price,star) values(1,'2011-11-10',1000,4);
>>403 それだと、2011を11で割って、さらに10で割った答えを入れてしまってる。
'2011/11/10' みたいにシングルクオートで囲むべし。
406 :
NAME IS NULL :2011/12/31(土) 21:31:34.01 ID:1ddnDqlq
>>404 >>405 ありがとうございました。/で割り算になってたんですね。
全く気づきませんでした。うまくいきました。
407 :
NAME IS NULL :2011/12/31(土) 22:06:02.20 ID:1ddnDqlq
mysql Ver 14.14 Distrib 5.5.8, for Win32 (x86) masql> create table question_tb >(question_id int(4) primary key auto_increment, 中略, ); において、question_id=1〜10を持つデータを登録した場合。 mysql> delete from question_tb where question_id=〜; で1〜10のデータを消し、 mysql> insert question_tb (purchase_date,purchase_price,star) values('2011/11/10',2900,5); question_id=1〜10がないにもかかわらず、question_id=11から登録します。 primary key auto_incrementで登録したid=1〜10という情報を消すことは 可能ですか? 登録したデータを全て消した場合 mysql> insert question_tb (purchase_date,purchase_price,star) values('2011/11/10',2900,5); でquestion_id=1から登録することは可能ですか?
409 :
NAME IS NULL :2012/01/01(日) 00:19:04.86 ID:+bqRnP5t
411 :
NAME IS NULL :2012/01/05(木) 05:14:08.00 ID:0uRuYpTO
質問です。DBはSQLite3です。
構成が同じなので
>>244 のテーブルを説明に使わせてもらいます
北海道なら、Bカンパニー・Cカンパニー
青森なら、無し
岩手なら、Bカンパニー
秋田なら、Aカンパニー・Cカンパニー
北海道・秋田なら、Cカンパニー
除外検索の要領で、対象の支社が無い会社を呼び出したい時はどうすればよいのでしょうか
not exists
NoSQL系のスレが見つからなかったのでここで質問させてもらいます 初心者的な質問なのですが、3台のサーバがあって、サーバAがサーバB又はサーバCのmemcachedに何かリストを書き加え、それをサーバBが利用するというような、機器間の連携は出来るのでしょうか? もし出来るとした場合、ネットワークを通じることになるので、やや速度的には落ちるのでしょうか? 宜しくお願いします
NoSQLがこのスレと何の関係があるの?
もっとも関係ないスレに、思想の根底近辺にある内容を聞くとかどうかしてるわ 適当にぐぐれよ
416 :
NAME IS NULL :2012/01/10(火) 14:40:12.23 ID:i/UShvc5
DB:SQL SERVER 7.0、クエリアナライザー DBのレコードが膨大なのでTOPで範囲を区切ってレコードを削除したいのですが、 DELETEの時にエラーが出てしまいます。何かミスしてしまっているのでしょうか? SELECT TOP (10) * FROM table_name WHERE field LIKE '2006%' → OK DELETE TOP (10) FROM table_name WHERE field LIKE '2006%' → NG
バージョンが古いからじゃね? delete from table_name where key in (select top (10) key from table_name where field like '2006%') だといけるのかね?
>>417 とりあえずテスト環境作って
最新版のSQL Serverでdelete top出来るか確認してみます。
主キーが複数あるテーブルなので
inでのやり方がうまく書けない(汗
7.0とか古すぎてわからんな
order by書かないTOPとか恐ろしくて使う気しないが 何順で消したいんだ 普通に項目で範囲指定すれば良いだけだと思うんだがな '200601%'けして'200602%'けして....で行けるんじゃねえのか そもそも何のエラーでてるんだよ?
最終的には全部消したいけど、なんとなく不安だから小分けにしてるって感じ
ヽ(・ω・)/ズコー DBのりかえろよもう!
424 :
422 :2012/01/11(水) 23:23:37.88 ID:???
あああ、本人(
>>416 )じゃないよ!
なんとなくそんな気がしたっていうだけ。
ますますズコーってなりそうですまん
truncateしろよ
全部は消したくないんだろうよ
like '2006%' に該当するのが500万件ぐらいあって、 一括で削除しようとすると時間がかかって不安だからちょっとずつ消してみよう! というわけのわからないアレ。
とおもったけど、ごくまれにそうせざるを得ない場面があるかもしれんなぁと思ったりした、が、きっと当てはまらないだろう
条件が日付だけだったら like '200601%' みたいな感じでいいんでね
DELETEに時間がかかってロック待ちが大量に発生するのを避けたい、 というのはあるかもしれない。
ロックエスカレーションか メンテ時間にやれば。
条件が日付ではないものだとして,
ROWNUMで消したいデータ数をしていすればいいんじゃないかな
DELETE FROM table_name WHERE ROWNUM <= 10
もし条件が日付だけなら
>>421 >>429 にすべきと思う
それオラクルや
ROWNUMってオラクル限定なの?
mysql 5.1.44 table datatbl inputdate data1 data2 data3 で月単位でまとめるときは GROUP BY DATE_FORMAT(日時, '%Y%m') で出せますけど、週間単位の時はどうするんでしょうか?
437 :
436 :2012/01/18(水) 18:29:35.50 ID:???
日時→inpudate でした
WEEKOFYEARが気楽かも
ありがとうございます '%Y%u'で出来ました。
441 :
NAME IS NULL :2012/01/18(水) 21:03:50.93 ID:HEQZTiH1
データベース内の複数のテーブル(テーブルAAA,テーブルBBB)から データを取得することはできますか。 AAAの中には1,2,3、BBBにはa,b,cというデータが入っていて select * from AAA;、select * from BBB;とやれば両方のデータを表示 させることはできますが、それを一文で行いたいです。
とりあえず、初心者向けのSQLの本を読め
できなかったらリレーションしてないww
444 :
NAME IS NULL :2012/01/18(水) 21:24:44.43 ID:HEQZTiH1
select * from AAA,BBBでいいんぢゃない?
ああ、ちゃんとこっちに来たのか、と思ったら何この自演
二行でいいぢゃん。 どうしても一行にしたいちゃんとした理由があるんならそれを説明しろ。
つかunionしたいってことじゃ?
よくselect文でDUALって見かけますがこれは何ですか?
ORACLEの仮想表です。とくに意味はありません。
データセット date 2001-10-19 2001-10-19 2003-12-7 2004-9-7 .... といったidと日付の集まりがあります。日付は重複しています。 ここから,SELECT count(date) FROM table GROUP BY dateで日付ごとの集計がとれたのですが、さらにmaxを使って集計が最大の日の日付とカウント数を出したいのですがうまくいきません。 上の例では、2001-10-19,2というのを取りたいのですが、どうやったらいいんでしょうか?
まあ王道で行けばこうだよなあ select A.date, A.cnt from (select date, count(date) cnt from table group by date) A inner join (select max(cnt) max_cnt from (select count(date) cnt from table group by date)) B on A.cnt = B.max_cnt ; limitが使えるDBMSならこんなんでも select date, count(*) cnt from table group by date order by cnt desc limit 1; どっちにしてもcountが最大の日付が複数あるときどうするか考えとかないとね
ありがとうございます! まだ呪文が長すぎて理解しきれませんが、希望通り動きました 最大値が二件以上の場合も考えておく必要がありますね 前者はすべて抽出し後者はidの若いもの一件がでてくるのでしょうね order by date desc limit 1 を全体につけときます
>>452 >前者はすべて抽出し後者はidの若いもの一件がでてくるのでしょうね
>>450 の時から思っていたんだが、id ってなんのことだ?
質問するときにDBMSを明記しないやつが多くてこまる
テーブル メニュー メニュー番号, メニュー 1 ステーキ 2 ハンバーガー 3 ビーフシチュー テーブル 注文 社員番号,名前,第1希望,第2希望,第3希望 1 鈴木 3 1 2 2 川本 1 2 3 3 山田 1 3 2 ここから 1 鈴木 ビーフシチュー ステーキ ハンバーガー と出力するにはどうすればいいでしょうか。 第1希望だけなら where メニュー.メニュー番号=注文.第1希望 で出るのですが。
457 :
456 :2012/01/24(火) 15:55:40.46 ID:+XGx9Ps2
>>456 DBMSはMySQL 5.0です。よろしくお願いします。
SELECT 社員番号,名前,menu1.メニュー,menu2.メニュー,menu3.メニュー FROM 注文 JOIN メニュー AS menu1 ON (注文.第1希望=menu1.メニュー番号) JOIN メニュー AS menu2 ON (注文.第2希望=menu2.メニュー番号) JOIN メニュー AS menu3 ON (注文.第3希望=menu3.メニュー番号) こんな感じ?
459 :
456 :2012/01/24(火) 16:36:36.54 ID:+XGx9Ps2
>>458 個別にJOINするんですね。
ありがとうございました。精進します。
なるほど!
>>458 ON (... OR ... OR ...) でよくね?
>>461 じゃあそれで動くSQLをどうぞ。
ちなみに
SELECT 社員番号,名前
,(select メニュー from メニュー where メニュー番号 = 第1希望)
,(select メニュー from メニュー where メニュー番号 = 第2希望)
,(select メニュー from メニュー where メニュー番号 = 第3希望)
FROM 注文
でもできる
463 :
456 :2012/01/24(火) 18:40:36.90 ID:+XGx9Ps2
>>458 これでできました!
ASでmenu1, menu2, menu3に分けるところがミソなんですね。
ありがとうございます。
DBMSはMySQL 5.0です。 テーブル 合否 社員番号,結果,エラーコード 1,合格,0 2,合格,0 1,合格,1 1,不合格,0 3,合格,0 2,合格,0 2,不合格,1 こういうテーブルがあります。 社員は一人で複数回受験できて、合格か不合格の結果を記録します。 但し、特定の条件だとエラーになって結果は出るけどエラーコードに1がつきます。 (1)エラーコードが0のものの、合格と不合格の件数が知りたいとき SELECT 結果,COUNT(結果) FROM 合否 WHERE エラーコード=0 GROUP BY 結果 結果 合格,4 不合格,1 (2)エラーコードにかかわらず、合格と不合格の件数が知りたいとき SELECT 結果,COUNT(結果) FROM 合否 GROUP BY 結果 結果 合格,5 不合格,2 そこで、 (1)と(2)を同じ表に出力したいときはどう書けばいいでしょうか。 このような表になればいいです。よろしくお願いします。 合格,4,5 不合格,1,2
その二つをjoinすればいいかと
union allでしょ
>>466 union all だと縦につながりました。
合格,4
不合格,1
合格,5
不合格,2
>>465 どういう風にjoinを使えばいいでしょう?
>>467 単に結果列で結合すればいいだけじゃないからそう聞いているのか、結合を知らないだけなのかがわからない
>>468 一応結合は知ってるのでたまに使うんですが、
selectの結果同士の結合はやったことがありません。
サブクエリの結果はテーブルと同じように扱えるよ
>>470 ありがとうございます。
こんなのを書いてみましたが、思うような数字が出てきません。
SELECTを2つJOINするのはうまく出ませんでした。
SELECT a.結果,COUNT(a.結果),cb FROM 合否 AS a
JOIN (SELECT 結果,COUNT(結果) AS cb FROM 合否 GROUP BY 結果) AS b
WHERE a.結果 = b.結果 AND エラーコード=0 GROUP BY 結果
>>462 みたいなのはサブクエリの結果が複数行だと出ないみたいですね。
>>471 二つをjoinすればいいっていうのはこういうこと。
select 〜 from
(select 〜 ) join (select 〜 )
>>462 のはそう。複数行だったときに出力しようがないからね。
473 :
NAME IS NULL :2012/01/26(木) 12:50:13.67 ID:49RPcyCy
DBはMysql5です 記事 entry user_id , blog_id , title ,body ユーザー user status 友人 friend send_user_id , get_user_id(sendが自分で、getが他人) があるとして user.statusが管理者の時は無条件で記事を表示 それ以外は友人と、自分の記事のみ表示 という状況を考えてます SELECT * from ( ( entry join user on entry.user_id = user.id ) join friend on user.id = friend.get_user_id ) where user.id = "自分のID" OR user.status = "管理者" OR friend.send_user_id = "自分のID" これでいけるかと思ったのですが、同じ記事が20個も30個も表示されてしまいます どのように書けばいいでしょうか?よろしくおねがいします……
friendの数だけ出てるんじゃないのかな。 where existsにかえるとか。 あと、そのwhere句なんかあやしい
>>473 user user_id status
の間違いではないのだろうか。
>>475 user id status の間違いだと思うよ。
user.idってかいてるから。
mysql 5.5.? 株式の出来高テーブルがあります code,vdate,startingprice,highprice,lowprice,closingprice,volume 一定の期間中の4本値(例えば月次、週次)を取得したい時、高値、安値は select max(highprice) as takane, min(lowprice) from kabukatbl where code= xxxx and vdate between 'yyyy-mm-dd' and 'xxxx-zz-bb'; で取得できますけど、一気にその期間の最初の日のstartingprice, その期間の最後の日のclosingpriceを取得することは出来ないでしょうか? (この際、出来高 volumeは無視で)
max(case vdate when min(vdate) then startingprice else startingprice+1 end) でできそうな気はする。
max(case vdate when min(vdate) then startingprice else startingprice-1 end) の間違い
481 :
478 :2012/01/28(土) 09:20:31.91 ID:???
>>479 ,480
ありがとうございます。ただ文法エラーになってしまいました。
そこで自分なりに書き換えてみたんですが、
select
case (vdate) when min(vdate) then startingprice
end as hajimene,
max(highprice) as takane,
min(lowprice) as yasune,
case (vdate) when max(vdate) then closingprice
end as owarine
from kabukatbl
where stock_code= 998407 and vol_date between '2011-12-26' and '2011-12-30';
owarineだけが何故かNULLになってしまいます。(上記の例は日経平均です)
+----------+---------+---------+---------+
| hajimene | takane | yasune | owarine |
+----------+---------+---------+---------+
| 8504.46 | 8516.53 | 8330.87 | NULL |
+----------+---------+---------+---------+
case (vdate) when max(vdate) then closingprice
end as owarine
ここの部分を単独でやってみてもNULLになってしまうのですが、hajimeneは出来て、なぜowarineではだめなんでしょうか?
482 :
478 :2012/01/28(土) 09:24:51.83 ID:???
vol_date は vdate、 stock_codeは codeに置き換えてください すいません
単純に1個1個取得していったらどう?試してないけどこんな具合に select 初日.startingprice as 始値, 最終日.endingprice as 終値, 通算.highprice as 高値, 通算.lowprice as 低値 from (select max(highprice) as highprice, min(lowprice) as lowprice from kabukatbl where code= xxxx and vdate between 'yyyy-mm-dd' and 'xxxx-zz-bb')) as 通算, (select startingprice from kabukatbl where vdate = (select min(vdate) from kabukatbl where code= xxxx and vdate between 'yyyy-mm-dd' and 'xxxx-zz-bb')) as 初日, (select endingprice from kabukatbl where vdate = (select max(vdate) from kabukatbl where code= xxxx and vdate between 'yyyy-mm-dd' and 'xxxx-zz-bb')) as 最終日
>>481 owarineが取れないと言うより、hajimeneが取れたのもたまたまだな。他のデータベースだとエラーになる。
SELECT
(SELECT startingprice FROM kabukatbl WHERE vdate=T1.startingdate) AS hajimene,
takane,
yasune,
(SELECT closingprice FROM kabukatbl WHERE vdate=T1.closingdate) AS owarine
FROM
(SELECT min(vdate) AS startingdate , max(highprice) AS takane , min(lowprice) AS yasune , max(vdate) AS closingdate FROM kabukatbl
WHERE code=998407 AND vdate between '2011-12-26' AND '2011-12-30') AS T1
やっていることは
>>483 さんとほぼ同じだけど、WHERE句が1箇所で済むってことで。
間違えた SELECT (SELECT startingprice FROM kabukatbl WHERE code=T1.code AND vdate=T1.startingdate) AS hajimene, takane, yasune, (SELECT closingprice FROM kabukatbl WHERE code=T1.code AND vdate=T1.closingdate) AS owarine FROM (SELECT min(code) AS code , min(vdate) AS startingdate , max(highprice) AS takane , min(lowprice) AS yasune , max(vdate) AS closingdate FROM kabukatbl WHERE code=998407 AND vdate between '2011-12-26' AND '2011-12-30') AS T1 サブクエリのWHERE句にcodeが抜けてたが、それを引っ張るためのmin(code)は面白くない。
486 :
478 :2012/01/29(日) 06:51:59.61 ID:???
むっ難しいぃ w
>>483 ,484
たまたま取れたというだけだったんですか。
484氏のやり方で出来ました。
483氏の方法はエラーが出るんでまた少し勉強してみます
ご教授していただき本当にありがとうございました。
質問です。 ORACLE 11gです。 SQL Plus上では、以下の文が実行できてしまいます。 UPDATE エーテーブル AT SET ( AT.20計, AT.30計 ) = ( SELECT SUM(DECODE(MT.集計用コード, '20' , BT.本数,0)), SUM(DECODE(MT.集計用コード, '30' , BT.本数,0)) FROM ビーテストテーブル BT, マスタ MT WHERE BT.コード = AT.コード AND BT.番号 = AT.番号 AND BT.サイズコード = MT.サイズコード ) WHERE AT.コード = 'LNL' AND AT.番号 = '0101278' ; 良くわからないのが、サブクエリ内でなぜエーテーブルの別名AT が使用できるのかという事です。 (というかFROMに書いていないエーテーブルが参照?出来るのかです) どうしてなのでしょうか?
相関サブクエリでぐぐれ まあ本来なら(SQL標準としては)UPDATE対象テーブルに 相関名は指定できないはずなんだけど
MySQLです Year | Month ------------ 2012 | 1 2012 | 2 2012 | 3 2012 | 4 〜 略 〜 2012 | 10 2012 | 11 2012 | 12 の様なテーブルから「年度」を取得したいです。 この場合は2011と2012を取得するにはどんなSQLを書けばよいでしょう? IF文とか書く必要があるのであればプロシージャ作るのもOKです。
select distinct Year from テーブル名;
実機ないからテストできないが、これでイケるんじゃね? SELECT year + (CASE WHEN month <=3 THEN -1 ELSE 0 END) AS nendo, year, month FROM table_name;
ああ、年度ってそういうことね
493 :
NAME IS NULL :2012/02/01(水) 13:20:56.00 ID:MbnB8W1W
SQLでの検索について教えてください あるテーブルAに日付時刻といろいろなデータを格納します。 データを検索するときに日付時刻で検索しますが テーブル構造をどのようにするのが普通ですか? たとえば2012年1月12日13時5分〜2012年2月11日11時16分までのデータを検索するときに テーブル構造が以下のようになってるとどういうSQL文になるんでしょうか? <テーブル構造:Oracle> Year Number(10), Month Number(10), Day Number(10), Hour Number(10), Minute Number(10),... これだと検索できないですよね? ↓ Select * from テーブルA Where _ Year >= 12 AND Year <= 12 AND _ Month >= 1 AND Month <= 2 AND _ Day >= 12 AND Day <= 11 AND _ Hour >= 13 AND Hour <= 11 AND _ Minute >= 5 AND Minute <= 16 ;
date型にすればいい
YYYYMMDDの文字列とHHMMSSの文字列
496 :
493 :2012/02/01(水) 15:57:00.10 ID:MbnB8W1W
色々情報ありがとう なんとなくわかってきました
497 :
NAME IS NULL :2012/02/05(日) 01:53:34.14 ID:79atCtq1
select文でデータ取得する場合はどちらが早いんですか? (a)2つのテーブルをJoinして条件指定してデータを取得する (b)1つずつテーブル取得してメモリ上でJoinの条件指定する
メモリ上でJoinの条件指定するってのがよくわからんが 一般的にDBMSの速度はどういう指定をしたかではなく、 どういう風にデータを取得したかによる 指定した通りにデータを取得するとは限らない 実際にデータを取得する方法を実行計画っていうんだが どっちが早いか比べるなら実行計画比べないとダメ
>>498 >メモリ上でJoinの条件指定するってのがよくわからんが
アプリ側でフィルタとマージするって事だろう
同じ事をDBMSがメモリとCPUを浪費しないように苦労してるんだけどね〜
一旦全部キャッシュに載せるっていみじゃね? そらそっちが早いよ。 だが苦肉の策だからよくわからんならやっちゃダメ。
とりあえずメモリ128MB載せる。 そのうち96MBぐらいをバッファプールに割りあてる。 これが大人のやり方だw
大人っていうかジジイ。
あんだと小便小僧が まだアラフォーだぞ もう爺かよ! 出てこい( ゜Д゜)オラ
やっぱ 爺でいいや。
>>503 アラフォーって孫がいる可能性も十分ありえる年齢
ていうかいまどきメモリ128MBでDBサーバとか
DELETE FROM seihin WHERE buhin1Id NOT IN (SELECT id FROM buhin) DELETE FROM seihin WHERE buhin2Id NOT IN (SELECT id FROM buhin) ↓1行にまとめてみたら DELETE FROM seihin WHERE (buhin1Id OR buhin2Id) NOT IN (SELECT id FROM buhin) うごかん。なんで?
SQLではどうかわからんけど普通のプログラム言語の感覚では (buhin1Id OR buhin2Id) のOR演算が優先されると思う であれば期待する結果にならないのは当然かと。 素直にというか単純に DELETE FROM seihin WHERE (buhin1Id NOT IN (SELECT id FROM buhin)) OR (buhin2Id NOT IN (SELECT id FROM buhin)) ではだめなのかな
だめなのかな、とか言われても・・・わかんないんです DELETE FROM seihin WHERE buhin1Id NOT IN (SELECT id FROM buhin) DELETE FROM seihin WHERE buhin2Id NOT IN (SELECT id FROM buhin) と DELETE FROM seihin WHERE (buhin1Id NOT IN (SELECT id FROM buhin)) OR (buhin2Id NOT IN (SELECT id FROM buhin)) どっちがイケてますでしょうか?
わからないクエリを書くぐらいだったらわかる前者で済ませておけばいい
ありがとうございます。最初の2行のやつでやってみます。 DELETE FROM seihin WHERE (buhin1Id OR buhin2Id) NOT IN (SELECT id FROM buhin) これ書いたのは自分じゃなくてチームリーダーなんです。ちなみにチリ人です。 自分は部外者でタダでソフトをもらってるだけなので文句は言えないんです。 でも「動かん」ってバグ報告したらチームリーダーやらシニアデベロッパー(ちなみにスペイン人)やら あと、ロシア人とハンガリー人がよってたかって「ちゃんと動く。動作テストした。エラー出ない」と言い張るんです。 こっちで試したらデータが全部吹っ飛んでしまって困ってるんです・・・ あ、内輪の話で申し訳ありません。 自分は工業高卒で英語が話せないのですが、なんとかがんばってヤツらを説得してみます。
笑うしか無い がんばってね w
そんな構文が通るDBMSって何だ? とか思って試してみたらMyなんちゃらでは通った。
>>511 そういう時は、クエリのどこがどうおかしいかを伝えるのではなく、
このデータのときに結果がおかしいよ、というのを伝えるようにすれば、言葉の壁はなくなる
513だけど通ったって言っても意図どおりに動作したって意味じゃなくて 構文エラーにならなかったって意味ね。 select buhin1Id, buhin2Id, (buhin1Id OR buhin2Id) from seihin を実行してみると何が起きているか分かると思う。
>>515 わかった〜!なんでデータが全部吹っ飛んだのか。
自分の操作ミスだと思ってたら、やっぱバグだった。
(buhin1Id OR buhin2Id) の値は常に 1 なんですよ。
たとえば、buhin1Id が 472536 で buhin2Id が 726666 だとすと
"SELECT 472536 OR 726666" を実行すると、1 が表示されるんです。
たったひとつの例外は、buhin1Id が 0 で buhin2Id も 0 のときだけ、0 になるんですけど
そんな部品は無いので、実質、ぜんぶ 1 になるんです。
ということは、
DELETE FROM seihin WHERE (buhin1Id OR buhin2Id) NOT IN (SELECT id FROM buhin)
これは
DELETE FROM seihin WHERE 1 NOT IN (SELECT id FROM buhin)
と等価なんです。
部品番号 1 以外は全て消去しなさい、って命令を実行してたんだ〜
チリ人のチームリーダーめ、呪ってやる!
>>516 真偽値として解釈されるDBMSなら、そらそうよ。
0が偽、それ以外は真。DBMSは3値論理なので、NULLは除いて。
そんなことよりデータの復旧はできるのか?
>>511 念のため確認するが、開発者がテストしたというDBMSと違うDBMSを使っているということはないよな?
部品番号 1 以外は全て消去しなさい じゃなくて (SELECT id FROM buhin) の結果に1がなければ全削除、あれば1件も削除しない になるな
>>519 性格に言うと、そうですね。私が少し勘違いしてました。
でも結果は同じです。データが全部消えるんです。
消えたデータはテスト用(本番用のコピー)なので実害はありません。
(buhin1Id OR buhin2Id) という、あまり見慣れない式が出てきたんで
「なんじゃこりゃ?」と思い、テスト環境で動作チェックしてたところです。
チリ人のチームリーダー、まだ自信満々です。絶対に間違って無いと言い張ってます。
MySQL 5.5 です。もしかしたらMySQLのリビジョンによって OR の動作が異なるのかしらん。
もしかしたら俺の方が間違ってるのかな・・・だんだん自信がなくなってきた。
>>520 サンプルSQLとサンプルテーブル使って
動作を見せてやりゃいいじゃん。
多対多のテーブルがあって、それらを繋ぐためのテーブルって、なんて呼ばれてますか? たとえば books と writers があって、この両者をつなげるためのテーブルです。 create table books_writers ( book_id integer not null references books(id), author_id integer not null references authors(id) ) あと、このようなテーブルの命名規則ってどうしてますか。 今は単純に2つのテーブル名をつなげただけなんですが、もっといい命名方法があれば教えて下さい。
>>522 質問の意図がわからないんだけどなんか不都合があるの?
Railsとかは決まってるけど
>>523 >>522 じゃないけど、質問の意図は
「(今の方法で困ってるわけじゃないけど) よりよい命名方あるか?」
でしょ。
俺には、思いつかないけど。
まあスレ違いっぽいなぁ。 世間でどう言ってるかは知らないが、俺はブリッジと呼んでいる。 命名に関してはあなたと同じ。 例えば石橋表面に対してタイヤの滑り易さ係数収めたテーブルは、 bridge_stone_tyre とか。
完全に勝手命名だろうけどクロステーブルって呼んでる 他人と話すとクロス集計表と間違える人間がいるかも
>>524-527 ありがとうございます。
結合するためのテーブルに、決まった呼び名はないのですか。驚きました。
命名規則も、もっといいのがあるといいのですが。
じゃっかん乗り遅れたが、自分ルールではバインダー テーブル名のプレフィックスは bind_[テーブルA]_[テーブルB] そしてテーブルABの並びは ascii 順
507 です。無事、解決しました。無事・・・ではないですけど。 seihinデータがまるごとぜんぶ消える現象をやっと認識してもらって、SQL文を元の正しいのに戻してもらいました。 チリ人のリーダーは、まだ理屈を理解してなさそうですけど。 でも、私のアカウントは停止されてしまいました。 英語の話せない日本人(私)が、dangerとかdatabase will brokeとか、さんざん騒いだせいです。 だって、緊急を要する最優先事項でうから。 アカウントくらい捨てメアドでいくらでも作れるので痛くもなんとも無いんですけど 2つめのアカウントも停止されてしまいました。いま3つ目をつくったところです。 日本のIPからのアクセスも禁止されてしまいました。いま海外からのプロキシでアクセスしてるところです。 この一部始終を皆さんに見せてあげたいところですが、いま掲示板を見たら、 データ消失事件のやりとりの一部始終がすべて削除されていました。 あの件は無かったことにされてしまいました。 ちゃんちゃん
ちょ、チリ人連絡拒否とかひでえ もうそこには仕事やらんでよろし
>>530 dangerはまずいよ。
作った人を犯罪者扱いしてるようなもんだ。
そりゃ気を悪くするよ。
英語のわかる人に相談して、柔らかい物言いを
すりゃよかったのに。
でも、どういう体制の職場?
同じ会社の同僚じゃないの?
アカウント停止とかちょっと意味わかんない。
会社じゃなくて、オープンソースかなんかの趣味(と言っちゃ悪いか?)プロジェクトだったん?
なんか英語がわからなくて勘違いしちゃったんじゃないの? オープンソースの開発者達がそんなレベル低いとは思えん。
言葉が判らずとも再現手順があれば間違えようがないよな
>>534 オープンソースも色々だし、コアの部分はともかく、端っこの部分は結構いい加減だったりするよ。
しかし、出禁くらってんのに何度も入り直すのはよくないわ オプソなら自己責任でやれよ
またアカウント凍結されたんでこんどは buhin1IdORbuhin2Id というアカウント名を作ってみたら 翌日にはアカウント凍結されてた。 掲示板を閲覧だけして、まだ何も書き込んでないのに。 理由は、不正なアカウント名です、だって。
スレ違い
これは性格悪そう
・DBMS名とバージョン Oracle 11gR2 ・テーブルデータ テーブル名:受注テーブル 列名:受注ID,受注数, 日付 ・欲しい結果 前日から1週間前までさかのぼり、 日毎の受注数を取得する。 受注数が0の日も検索結果として表示したいです。 イメージは↓です。 ○元となるデータ 受注ID, 受注数, 日付 1, 10, 2012/2/26 9:00 2, 20, 2012/2/27 9:00 3, 25, 2012/2/27 9:30 4, 30, 2012/2/29 9:00 … ○抽出結果 日付, 受注数 2012/2/23, 0 2012/2/24, 0 2012/2/25, 0 2012/2/26, 10 2012/2/27, 45 2012/2/28, 0 2012/2/29, 30 ・説明 次のSQLで受注がない日については、 望んだデータが抽出できました。 受注がない日の扱いを教えてください。 select 日付, sum(受注数) from 受注テーブル where trunc(日付) between trunc(sysdate - 7) and trunc(sysdate - 1) group by trunc(日付); よろしくお願いします。
存在しないデータを"select"することはできませんよ。
>>8
間違ってたらごめんだけど、model句使えばできない?
あ、と。Oracle使いではないので、そんなことはなく、
>>8 の方法のほうがよいとかあるならご指摘を。
mode句が標準SQL(もしくは事実上標準)ならばそれでテンプレにすれば良いけど 特定のDBMS実装にかかわるものをテンプレに入れるのは反対
Master Table id | type id ------------ 01 | 1 02 | 2 03 | 2 04 | 1 05 | 1 06 | 2 ・DBMS名とバージョン mysql 5.1.44 ・テーブルデータ Table A id | name a ------------ 01 | aaa 04 | bbb 05 | ccc Table B id | name b ------------ 02 | ddd 03 | eee 06 | fff ・欲しい結果 Master Tableのtype idが1だとTable Aと、2だとTable BとJOINしたいんですけど、どう書けば良いんでしょうか?
>>548 MySQLで動くかどうか試してないけど、
SELECT MasterTable.*,
CASE WHEN type_id=1 THEN Table_A.name_a WHEN type_id=2 THEN Table_B.name_b END AS name
FROM MasterTable
LEFT JOIN Table_A USING (id)
LEFT JOIN Table_B USING (id);
550 :
NAME IS NULL :2012/03/07(水) 06:05:26.24 ID:SbjMyYjx
掲示板をつくっています。 ・親投稿 └ 子投稿 └ 子投稿 のように1つだけコメントができる仕様で、 親・子投稿は以下のテーブルに格納されます。 post - id(PK) - parent_id(postのIDでこれが0なら親、その他INTなら子) - その他、投稿に関する情報(タイトル、本文など) 上記のようなテーブルから、 親投稿にぶらさがる子投稿をまとめて取得するのはSQLではどう書けばいいでしょうか? ちなみに現在は、WHERE parent_id = 0 で親を取得して、 その後取得した各レコードのidがparent_idに入っている投稿をループして取得しています。 なので、20個の投稿とコメント取得する場合、21個のSQLを発行してしまっています。 これを1回で取ってきたいです。
>>550 木構造の情報を1回のSQLの発行で全部取り出す?
親子だけで孫を許さないようになっているならこれだけでいいような select * from post T1 left outer join post T2 on T1.id = T2.parent_id ; 孫以下、多階層を許すなら再帰問合せを使わなきゃなんない
親投稿をひとつのファイルにして、子を追記していく、でいいな。
>>550 「一つだけコメントができる仕様」の意味が不明だったが、
Amazonの書評のような構造かな。
556 :
550 :2012/03/07(水) 09:20:25.90 ID:SbjMyYjx
いや、孫はいりません
>>552 の方法でいけそうですけど、
親レコード+子レコードのレコードが1行になるので
アプリケーション側で工夫が必要ですね
ありがとうございます。
>>556 order byにcase使えるDBMSなら
1.親IDが0ならID、そうじゃないなら親ID
2.ID
の順で並び変えるだけで良いんじゃないのか?
設計スレで設計してもらい、SQLスレでクエリを教えてもらう、と。 アプリケーション側の工夫が必要だとわかったってことは、次はどこのスレだろ。
うちの会社ブラックなんだがスレ
アプリケーション側の工夫が必要らしいのですが、これに対応しているアプリケーションはありますか? or アプリケーションとはどうやれば作れますか?
561 :
NAME IS NULL :2012/03/07(水) 15:01:29.71 ID:sPFfC/0l
初歩的な事ですいません 名前の後ろにさんや様を付けたい場合はどうすればいいのでしょうか? 先ほどupdate"社員表" set "氏名" = 'さん'; とした場合みんなの名前が全員さんになってしまいました・・・
初歩的なことだと思うなら初歩的なサイトを見ればいいと思うのに。 文字列の連結の仕方知ってる?
>>561 update"社員表" set "氏名" = "氏名"+'さん'
とか
+の所は文字列を結合する演算子なんだが、DBMSによって違うので自分で調べてくれ
まあ普通は ||
でもさんをつけるのはSELECT時にしてデータに入れなくていいような
データにいちいち敬称なんかつけるなよ w
567 :
566 :2012/03/07(水) 18:50:32.28 ID:???
登録(更新)する時にということね 更新とか登録とかの時に敬称なんかつけてたらそれを取り除く作業が発生してしまうw
敬称がデータとして必要な場面もあるけどな。まあその場合は敬称は別項目でもつべきだが 住所録ソフトの宛名とかそうなってるだろ
code | val ------------ A | 11 A | 23 A | 34 A | 42 B | 321 B | 112 B | 23 B | 245 というようなテーブルがあり、ここから 同じcodeを持つ行が4行以上ある場合、val順で小さい方から3行残してのこりを削除 したいのですが、SQL一発でできますか?DBMSはMySQLです。 ↓ほしい結果 code | val ------------ A | 11 A | 23 A | 34 B | 112 B | 23 B | 245
limit句がdeleteやupdateでも使えたはず
select T1.code, T1.val from TableName T1 inner join TableName T2 on T1.code = T2.code and T1.val >= T2.val group by T1.code, T1.val having count(*) <= 3 order by T1.code, T1.val ;
ああ、deleteしたいのか まあいいや
ありがとうございます。これで削除ができました。 DELETE FROM t WHERE EXISTS ( SELECT * FROM ( SELECT t1.code,t1.val FROM t t1 INNER JOIN t t2 ON t1.code = t2.code AND t1.val >= t2.val GROUP BY t1.code,t1.val HAVING COUNT(*) > 3 ) d WHERE d.code = t.code AND d.val = t.val );
MySQLかPostgreSQLかMongoDBかSQLiteのいずれかで以下のことを実現するSQLを伝授してください やりたいこと: id10とid11の間に新しいカラムを挿入する id 10のカラム みかん id 11のカラム りんご ↓ id 10のカラム みかん id 12のカラム 新しく挿入した箇所 id 12のカラム りんご
575 :
574 :2012/03/16(金) 12:57:25.19 ID:???
訂正 id 10のカラム みかん id 11のカラム りんご ↓ id 10のカラム みかん id 12のカラム 新しく挿入した箇所 id 13のカラム りんご ←ここ以降idをずらす
なんかExcel等の表計算ソフトの発想っぽく見えるな、 カラム(じゃなくてロウだな)を挿入するってのが。 そもそもIDの付け替えってこと自体がなぁ… ID体系の変更なんかで、全部えいやっと付け替える以外では そうそうやるもんじゃないと思うんだが。
577 :
574 :2012/03/16(金) 13:17:00.08 ID:???
カラムの内容は重複しても構わないのでidがなくても構いません この場合で考えていただいた場合でも難しいですか?
>>577 問題になるのはそのidの方で、'10'と'11'の間に挿入しなさいと言われれば
'10' みかん
'11' 新しい挿入
'12' りんご
が普通。
新たに追加する場合に取得するidで追加しておいて、
そのあとにりんご以下をidを変更しながらコピーする
というのは相当にクレージー。
>>574 はシステム開発の仕事をやめるべきだと思う。
>>574 idが11以上のものに1足して、id11を挿入する。
updateして、insertする。
581 :
574 :2012/03/17(土) 00:40:03.84 ID:???
>>580 updateとinsertだと、
id 10のカラム みかん
id 13のカラム りんご ←ここ以降idをずらす
id 14
:
id 12のカラム 新しく挿入
こんな風に順番が崩れてしまいませんか。
insertとは言っても、空いたところが無いでしょうから、
後ろに付け足されそうで…
>>581 あー、それを気にしてるのか。
レコードの順番ってinsert順とは限らないよ。
だから、updateとinsertでいい。
idの順番で取り出したいのならorder by idをつけないとだめ。常に。
MySQL 5.5.19 . 長くなりますので
テーブルの定義・内容と欲しい結果はここに
http://codepad.org/oe1jhVrF で、
select a.input_date,b.input_date,a.data1,a.data2,b.data2
from a_tbl a
right join b_tbl b
on a.input_date = b.input_date; とすると、結果が
+------------+------------+-------+-------+-------+
| input_date | input_date | data1 | data2 | data2 |
+------------+------------+-------+-------+-------+
| 2012-02-01 | 2012-02-01 | 10 | 12 | 13 |
| NULL | 2012-02-03 | NULL | NULL | 18 |
| 2012-02-04 | 2012-02-04 | 13 | 15 | 14 |
| NULL | 2012-02-05 | NULL | NULL | 95 |
| 2012-02-06 | 2012-02-06 | 13 | 10 | 10 |
+------------+------------+-------+-------+-------+
なんですが、実際にはいろんなコードが入っているので、コードも抽出条件に入れたら
select a.input_date,b.input_date,a.data1,a.data2,b.data2
from a_tbl a
right join b_tbl b
on a.input_date = b.input_date
where
a.code=1111 and b.code='ddd';
+------------+------------+-------+-------+-------+
| input_date | input_date | data1 | data2 | data2 |
+------------+------------+-------+-------+-------+
| 2012-02-01 | 2012-02-01 | 10 | 12 | 13 |
| 2012-02-04 | 2012-02-04 | 13 | 15 | 14 |
| 2012-02-06 | 2012-02-06 | 13 | 10 | 10 |
+------------+------------+-------+-------+-------+
になってしまいました。
コードを抽出条件に入れた状態で望ましい結果または上の方の結果になるようなSQLを教えて下さい。
抽出してからjoin。
ありがとうございます。 select a.input_date,b.input_date,a.data1,a.data2,b.data2 from ( select input_date,data1,data2 from a_tbl where code=1111) a right join ( select input_date,data2 from b_tbl where code='ddd') b on a.input_date = b.input_date; で上の方の結果になることが出来ました。
>>584 のを a.code=1111 or b.code='ddd'; にするだけでよくね?
>>584 つ or a.code is null
3行目と4行目のデータを入れ替えるというのはどのようにやるのでしょうか?
>>589 リレーショナルデータベースでは表内の行に順序はありません
select文でorder by句を指定したとき初めて順序が生まれます
order by句を指定せずにselectしたときは
仮に実行するたびに順序が違っても文句は言えません
ここまで理解できたらもう一度質問してください
591 :
NAME IS NULL :2012/03/28(水) 16:14:27.69 ID:MsrxUF32
・RDBMS MySQL 5.1.6 ・テーブルデータ aji_table //調味料テーブル rank int(3) //表示順位 NULL許可 name varchar(16) //調味料の品名 price int(5) //調味料の値段 ・インサートされているデータ NULL|さとう |100 0 |しお |200 3 |こしょう |300 NULL|みそ |400 NULL|みりん |500 ・欲しい結果 0 |しお |200 NULL|さとう |100 NULL|みそ |400 3 |こしょう |300 NULL|みりん |500 ・説明 お世話になります。 上記にある調味料値段データベースにおいて 表示順をソートする際に ・順位に数字が入っているものは、一覧表示を行う際にその数字に応じた順位に出す。 ・それ以外は、値段昇順で出力する。 というSELECT文が組めないものかと思っております。 単純に値段順で表示したいんですけど、いくつかの商品は 表示結果におけるその順番の位置を固定したい!という内容でして 順位のフィールドをおいてなんとか解決しようとしているのですがうまく組めません。 対応策を是非、ご教授頂ければと思います。 なお、そんなテーブルの組み方はダメだ、そういうときはこう組め!等もありましたら ご教授お願いいたします。 よろしくお願いいたします。
質問です。 phpが絡むんですが、 $se = $_POST['search']; $res = mysql_query('SELECT COUNT(*) FROM fx WHERE day LIKE "%{$se}%" AND game LIKE "%勝ち%"'); $game_s = mysql_fetch_assoc($res); $seの中には年月が入っています。 特定の月の勝ちの数を出したいんですがうまく行きません。 ちなみに$seの中身がちゃんと入っている事はprintで確認しています。 たぶん変数の入れ方に問題があると 思うのですが、 誰か指南を御願いします。 初歩的すぎてすぃません。。
>>592 $seに受け取っている値は、定型なフォーマットの値で受け取っておりますでしょうか。
そこに受け取っている値例を出してください。
>>593 自分のレベルが低すぎて
せっかくお答えいただいているのに
どう返していいかわかりません。(笑
情報が少なすぎると思いますので
流れを書きます。
input_s.htmlに以下の記述
<form method="post" action="input_s.php">
<select name="search">
<option value="2012/03/">2012年3月</option>
<option value="2012/04/">2012年4月</option>
<option value="2012/05/">2012年5月</option>
<option value="2012/06/">2012年6月</option>
<option value="2012/07/">2012年7月</option>
<option value="2012/08/">2012年8月</option>
<option value="2012/09/">2012年9月</option>
<option value="2012/010/">2012年10月</option>
<option value="2012/011/">2012年11月</option>
<option value="2012/012/">2012年12月</option>
</select>
<input type="submit" value="検索する" />
</form>
>>593 input_s.phpに以下の記述
<?php
$url = "***";
$user = "***";
$pass = "***";
$db = "***";
// MySQLへ接続する
$link = mysql_connect($url,$user,$pass) or die("MySQLへの接続に失敗しま
した。");
// データベースを選択する
$sdb = mysql_select_db($db,$link) or die("データベースの選択に失敗しまし
た。");
mysql_query('SET NAMES UTF8');
$se = $_POST['search'];
$recordSet = mysql_query("SELECT * FROM fx WHERE day LIKE '%{$se}%'");
//勝ち絞込み検索結果
$res = mysql_query('SELECT COUNT(*) FROM fx WHERE day LIKE "%{$se}%" AND
game LIKE "%勝ち%"');
$game_s = mysql_fetch_assoc($res);
?>
<?php print "{$se}の集計"; ?>←ここは表示OK
<?php print $game_s['COUNT(*)']; ?>勝 ←ここの表示ができない
>>593 mysqlの登録部分
フィールド/種別/照合順序/属性/ヌル(NULL)/デフォルト値/その他
day/text/utf8_general_ci/属性なし/いいえ/None/その他なし
game/text/utf8_general_ci/属性なし/いいえ/None/その他なし
こんな感じなのですが
どうでしょうか?
よろしくお願いします。
597 :
593 :2012/03/28(水) 18:09:37.07 ID:???
データ型だとか、$recordSetはどこ行っただとかいくつか突っ込むべき点が あるのですが、そこらは割愛します。 大体やりたいことはわかりましたので すでに入っているデータの中身の例を複数件、教えてください。 もし、可能でしたら、勝ち絞込み検索結果のSQL文を適当にechoして phpmyadminか何かで直接MySQLに叩き込んでエラーを拾ってください。
>>597 すいませんお世話になります。
$recordSetは繰り返し処理で処理しをしようと思っています。
今後です(笑
2件しかデータは入れていないですが、
idオートインクル
id/day/game
1 / 2012/03/26 / 勝ち
2 / 2012/04/26 / 負け
です。
ちなみに
SELECT COUNT(*) FROM fx WHERE day LIKE "%2012/03/%" AND game LIKE "%勝ち%"
で実行すると
COUNT 1 と出ます。
SELECT COUNT(*) FROM fx WHERE day LIKE "%2012/04/%" AND game LIKE "%勝ち%"
で実行すると
COUNT 0 と出ます。
これを踏まえて %ここ% この中身に変数を入れたらいいんだという
安易な考えなのですが、
<?php print "{$game_s}"; ?>
これを実行したら Arrayと出ました。
どうでしょうか?
>>591 SELECT一発じゃ無理だな
select * from aji_table where rank is not null order by rank;
select * from aji_table where rank is null order by price;
を別々に取得してアプリ側でマージしたほうがいいかと
>>591 mysqlは知らないけど、オラクルだとこんな感じでできないかな
動くかわかんないけど。
select
rank,name,price
from (
select
rank,name,price,
row_number() over(order by price) as num
from aji_table
)
order by nvl(rank,num), nvl2(rank,0,1)
601 :
591 :2012/03/28(水) 21:48:30.04 ID:SAJaqLDy
>>599 回答ありがとうございます。
やはりムリな背伸びはしないほうがいいですかねぇ…。
変数を与えながら行番号を与えて値段順にソートしたテーブルと
元のテーブルでrank is not nullかけたものをマージして
うまくrankと行番号つき合わせて処理できないかとか思っているのですが
SELECT文組む能力の足りなさを露呈して困っておりました。
>>600 ご回答ありがとうございます。
申し訳ございませんが不勉強なもので、
OVER()やORDER BYにNVLがあるとどうなるですとか
すぐには理解できなかったので
一晩かけて理解できるようまずそのSQL文から学んでみたいと思います。
そこからうまく期待のものが組めないかと思っております。
ありがとうございました。
>>600 rankがnullでないものが途中に入ったら
それ以降のnumを繰り下げないといけないから
それじゃあ無理
603 :
NAME IS NULL :2012/03/28(水) 22:24:52.54 ID:2iS1ICMl
MySQL テーブルデータにNo int(255)があります。 現在Noには10000件のデータがあり追加や削除を繰り返しているので 既にNo連続した数字にはなっていません。 今回、取得したいのはNoが5000以上でNo小さい方から30件取得して Noが大きい順に並べ替えて取得したいです。 この場合のSQLはどう書けばいいでしょうか?
SELECT No FROM (SELECT No FROM tabName WHERE No >= 5000 ORDER BY No ASC LIMIT 30) AS otherTab ORDER BY No DESC かな?
>>604 なるほど参考になります。
試してみます。
>>604 上手くいきました^^有難うございました
>>598 それならば、mysql_result($res,0)で受け取ってみてください。
>>595 が正解なはずなんだけど。
それでダメならば、mysql_error()してみたり、arrayと表示されたその変数をprint_r()してみて
中身をじっくりみて理解を進めてみるとよいと思われます。
なお、WHERE句は、適切に%を使う数を適切に制限したり、=でいいところは=にして明示的に絞り込んだりすることで
問題の切り分けもしやすくなるので、そこも含めて実行してみてください。
>>607 resultでもうまくいかないっすね。
うーん、
もうちょっと調べてみます。
また結果報告いたします!
607さん付き合ってくれてありがとうです( ´ ▽ ` )ノ
いいかげんホスト言語の問題はその言語のスレで聞いてくれ
>>522 ORM界隈ではjoin tableって言ってる。
>>601 これでどうかしら
select * from aji_table order by
if (rank is null,
(select count(*) from aji_table as t2 where t2.rank is null and t2.price < aji_table.price),
rank - (select count(*) from aji_table as t2 where t2.rank is not null and t2.rank < aji_table.rank)
), rank is null, rank;
612 :
601 :2012/03/30(金) 10:42:12.28 ID:???
>>611 ばっちり動きました…。
ORACLEのNVLでまさかと思っておりましたが
ORDER BY でもIFかけられるんですね。
今後の参考にもさせて頂きます。
どうもありがとうございました!
>>612 じゃあ、もののついでに、case文もかけるのを知っておくと何かの役に立つかも。
インデックス使えないとかの問題は出てくるけどね
・DBMS名とバージョン MySQL ・テーブルデータ 店舗(店舗ID 店舗名) 商品(商品ID 店舗ID 商品名) (※同じ名前の商品が複数の店舗にあっても、別の商品として扱う) 売り上げ(売り上げID 商品ID 個数) ・欲しい結果 店舗名 商品名 売り上げ個数合計 (※店舗名、商品名でソート) ・説明 SELECT * FROM `店舗` ORDER BY `店舗名`; この結果をプログラム側でループ SELECT * FROM 商品 WHERE 店舗ID=? ORDER BY `商品名`; さらにこの結果をループ SELECT SUM(個数) FROM 売り上げ WHERE 商品ID=? これだと時間がかかりすぎるので、これを1つ、または2つのSQLにまとめたいです。 SELECT *, SUM(`売り上げ`.個数`) AS `売り上げ個数合計` FROM `商品` LEFT JOIN `売り上げ` ON `商品`.`商品ID` = `売り上げ`.`商品ID` WHERE `商品`.`店舗ID`=? とりあえず下2つだけでもまとめようとしてみたのですが、合計が商品毎ではなく店舗毎の合計になってしまいます。
group by 店舗ID, 商品ID でも、商品はいずれかの店にしか配置されないわけだから、商品のgroupだけでいいかもね。
>>592 game LIKE "%勝ち%" の部分だけど、本来は
game LIKE '%勝ち%' ですよね。
"%勝ち%" というフィールドを探しに行っているのではないの。
シングルクォーツの中にシングルクォーツを書くPHPの書き方を知らないから
どうすればいいとか言えないけど。
なんで複数形なんだよw
前と後で2つあるからとか?
ん? シングルクォートか?www
>>615 なるほど、そんな手が…。
ありがとうございます。
621 :
NAME IS NULL :2012/04/01(日) 21:12:09.01 ID:Lb+ordGT
■DBMS名とバージョン MySQL 5.0 ■テーブルデータ 店舗テーブル AreaID int(1)←この2つでキーになってます TenpoID int(1)←この2つでキーになってます uriage int(16) 社員テーブル SyainNo int(255) AreaID int(1) TenpoID int(1) SyainName varchar(256) ■欲しい結果 uriageが5000以下の店舗に属してる社員を抜き出す のと その社員をいっぺんに消す どのようにSQL文を書けばいいでしょうか?
exists
売り上げが一定額に達しなかったら全員リストラか 過激だな
624 :
NAME IS NULL :2012/04/01(日) 21:51:10.09 ID:Lb+ordGT
625 :
NAME IS NULL :2012/04/01(日) 23:51:59.00 ID:p/jAjTZq
>>621 ですがexistsを使って考えてるんですが上手くいきません
SELECT *
FROM 社員テーブル
WHERE EXISTS (
SELECT *
FROM 店舗テーブル
WHERE 社員テーブル.AreaID = 店舗テーブル.AreaID
AND 社員テーブル.TenpoID = 店舗テーブル.TenpoID
AND 店舗テーブル.uriage > 5000
)
ってやってみたんですけど 店舗テーブル.uriage > 5000 が効いてないみたいです
何が間違えでしょうか?
>>621 SELECT T2.* FROM (SELECT * FROM TenpoTable WHERE uriage<=5000) AS T1
JOIN SyainTable AS T2 ON T1.AriaID=T2.AriaID AND T1.TenpoID=T2.TenpoID;
DELETE FROM SyainTable AS T1
WHERE EXISTS (SELECT * FROM TanpoTable AS T2 WHERE uriage<=5000 AND T1.AreaID=T2.AreaID AND T1.TenpoID=T2.TenpoID);
MySQLで動くかしらないけどね。
ところでMySQLってUSINGはまだ使えないのでしたっけ?
使えるのならONのところはUSING(AreaID,TenpoID)となって楽。
628 :
NAME IS NULL :2012/04/02(月) 23:09:42.67 ID:jqvkdUXL
Mysql5を使っています。以下のようなテーブルがある時、 ・table_male(カラム:id/name/address) ・table_female(カラム:id/name/address) ・table_X(カラム:id/sex_id/sex/unique_key) ※sex_idはtable_male.idもしくはtable_female.id クエリA select `sex`, `sex_id` from table_X where unique_key = $key limit 1; の結果(sexの値にmaleかfemaleが返る)に応じて table_maleもしくはtable_femaleからaddressを引き出したいと思います 今まではクエリAのあとに以下のようにしていたんですが、両方をまとめてやることはできないでしょうか? select `address` from table_male where `id`=$sex_id limit 1; 最初のクエリの取得結果に応じて、続けて実行するクエリの対象テーブルを変更させるということに なると思うんですが… よろしくお願いします
select ifnull(table_male.address, table_female.address) from table_X left join table_male on (table_X.sex_id = tablemale.id) left join table_female on (table_X.sex_id = table_female.id) limit 1; select address from table_X join (select * from table_male union all select * from table_female) as table_malefemale on (table_X.sex_id = table_malefemale.id) limit 1; とか。
630 :
628 :2012/04/03(火) 04:04:56.20 ID:b2izkOxC
>>629 ありがとうございました、しらない方法で勉強になりました
すみませんがもう一つ質問させてください
SNSみたいなアプリを作ってて、ユーザーのマイページ(
http://example.com/user/taro )に
「プロフィール、写真、イベント、日記、etc…」と複数のテーブルから引き出されるデータを表示する必要があるのですが、
それぞれのテーブルが以下のような構成になっています
t_profile id|accout(このユーザの値はtaro)|name|mailaddress
t_photo id|path_to_file|userId(t_profile.idです)
t_event id|event|day_event|userId
t_diary id|title|body_text|userId
この場合、どのようにデータを引き出すのが良いですか?
URLからt_profile.accountであるtaroを取得して、それをt_photoやt_tweet,t_diaryへのselect文のサブクエリに利用するのが良いのか
例:select t_photo.path_to_file where t_photo.userId = (select `t_profile`.id where `t_profile`.account = 'taro' limit 1)
以降、t_event、t_diaryへも同様に処理
それとも、最初にaccountのtaroを利用してt_profileからt_profile.idを抜き出して、それをキーにselectした方が良いのか
例:select t_photo.path_to_file where t_photo.userId = $profileID
前者で発生するサブクエリ3回の負荷と、後者で発生するID抜き出しクエリ1回の負荷を単純に比較して
後者の方が良いと考えて良いんでしょうか
実現できてから遅いところを直せばいい。 前者でやるにしても、そのlimitのクセはやめたほうがいい。 アカウント名がユニークじゃないならそれはそれで問題だし。
phpmyadmin使うようになったら、お守りのようにLIMIT 1をつける癖がついた件
MySQL 5.1です。 create table staff_list( staff_id int(5) primary key //社員番号 staff_name varchar(8) //社員名 unit varchar(8) primary key //部署名 ) insert into staff_list (staff_id,staff_name,unit) values (1,'範馬','総務'), (2,'愚地','総務'), (3,'花山','総務'), (1,'高津','企画'), (2,'池谷','企画'), (3,'長嶋','企画'), (1,'鳩山','営業'), (2,'野田','営業'), (3,'小沢','営業'), (4,'枝野','営業') このようなテーブルに対してSELECTをかける際、一度のクエリーで 部署別にソートしたうえで、総務だけstaff_id降順で他を昇順で出したいと思っています。 order by unit,IF(staff_name='総務',staff_id desc,staff_id asc) などと試行してみているのですがうまくできません。 どなたかうまい方法をご存じないでしょうか。 よろしくお願いいたします。
総務だけマイナスにしたら?
IF(staff_name = '総務', staff_id * -1, staff_id) とかどう?
>>635 レスどうもです。
select * from staff_list order by if(staff_name = '総務', staff_id * -1, staff_id)
こちらを実行してみたところ
(1,'範馬','総務')の行だけ一番上にきて、あとはすべてstaff_id昇順になってしまいました。
むぅ。
637 :
636 :2012/04/03(火) 17:16:46.37 ID:???
すみません。 すごい凡ミスでして order by unit ,if(staff_name = '総務', staff_id * -1, staff_id) でうまくいきました。 どうも大変失礼いたしました。と同時にありがとうございました。
mysql 5.5.10 table hogehoge inputdate data1 data2 data3 2012-02-16 ssssss wwwww yyyyyy 2012-02-17 xxxxxx xxxxx xxxxx 2012-02-18 null aaaaa vvvvv 2012-02-19 null null null 2012-02-20 null null null 2012-02-21 null null null 2012-02-22 xxxxxx ccccc fffff とある時に、指定日の前日のデータが欲しい 例でいうなら data1について、 2012-02-17を指定することによって2012-02-16のssssssを、 2012-02-22の日付を指定して2012-02-17のxxxxxxが得られ るようにしたいのですが。 よろしくお願いします
mysqlの日付演算詳しくないけど、 where inputdate = DATE_SUB(指定日, INTERVAL 1 DAY) とかでだめかな
あれ、求めてるのがなんか違うね。 select * from hogehoge where inputdate < 指定日 and data1 is not null order by inputdate desc limit 1 とか?
>>640 ありがとうございました。 m(_ _)m
それで期待通りのデータが得られました。
642 :
NAME IS NULL :2012/04/08(日) 14:31:49.62 ID:/RIv7L6k
MySQL 5.0.77 SELECT name, MIN( score ) AS score, time FROM ranking2 WHERE time > SUBTIME( NOW(), '1 0:0:0' ) GROUP BY name UNION SELECT name, score, MAX( time ) FROM ranking2 WHERE time > SUBTIME( NOW(), '1 0:0:0' ) GROUP BY name ORDER BY score LIMIT 50 ゲームのランキングを作っています。 name、time、scoreというカラムがあり スコアの値が小さいほど高得点です。 ランキングには各ユーザ毎に24時間以内の「最新のスコア」と「scoreが一番小さいスコア」を 表示させたいです。 自力で頑張って上記のコードまでたどり着いたのですが どうやらUNION以降のコードが誤っているようで ユーザの最新タイムのレコードを取得してるつもりなのですが 結果は、最新タイムのものが得られるのですが、スコアの値が誤っている状態になってしまします。 よろしくおねがいします。
GROUP BYを使う場合はGROUP BYに書いたカラムと集約関数しか SELECT句には書けないのが普通なんだがMySQLでは書けるんだな・・・
645 :
642 :2012/04/08(日) 15:44:20.18 ID:???
SELECT name, MIN( score ) AS score, time FROM ranking2 WHERE time > SUBTIME( NOW(), '1 0:0:0' ) GROUP BY name UNION SELECT a.name, a.score, b.time FROM ranking2 AS a INNER JOIN ( SELECT name, MAX(time) AS time FROM ranking2 GROUP BY name ) AS b ON a.name = b.name AND a.time = b.time WHERE a.time > SUBTIME( NOW(), '1 0:0:0' ) ORDER BY score 解決しましま! ありがとうございました!
UNIONの前も間違ってるな それと、ORDER BYは普通UNION後にかかる MySQLではどうか知らんが
#インデントが崩れる場合は
http://pastebin.com/26BkXDHs をみてください。
--
-- 商品テーブルと、
--
create table items (
id serial primary key,
name varchar(255) not null,
price integer not null -- 単価
);
--
-- 販売テーブルがあるとする。
--
create table sales (
id serial primary key,
item_id integer not null references items(id),
count integer not null default 1, -- 個数
total integer not null, -- 単価 * 個数
created_at timestamp not null default current_datetime
)
--
-- 日付を指定して、その日の商品別販売金額合計を大きい順に表示したい。
-- どういうSQLを書けばいいの?
-- こんなかんじで書けたらいいんだけど。
--
select items.id, items.name
from items,
(select item_id, sum(total) as sum_total
from sales
where date(created_at) = '2012-04-01'
group by item_id) as totals
where items.id = totals.item_id
order by totals.sum_total desc;
そのSQLで問題ないように見えるけど、どこがダメなの? 強いて言えば最初のselect句にtotals.sum_totalを追加するぐらいか
SQLというよりテーブル設計の質問なんですがいいでしょうか? ユーザごとの日々変化するデータを1日1レコードずつ保存するために 以下のようなテーブル構造を考えました。 USERSテーブル user_no (ユーザ番号 PK) latest_gen_no (最新世代番号) 氏名その他の属性 RECORDSテーブル user_no (ユーザ番号 PK*) gen_no (世代番号 PK*) 日々変化する値 *user_no, gen_no のペアでPK GENERATIONSテーブル gen_no (世代番号 PK) date (日時) 全ユーザの最新世代の値を取得するべく、 select ... from users u, records r where u.user_no=r.user_no and u.latest_gen_no=r.gen_no; というSQLを発行すると、ものすごく時間が掛かります。 PKやインデックスの設定の仕方に問題があるのでしょうか? そもそもテーブルの構成がまずいでしょうか?
遅くならなさそうに見えるよ。
USERS に (user_no, latest_gen_no) のインデックスを張るぐらいじゃない? 「氏名その他の属性」が結構あるなら、そのテーブルを総ナメするよりは速くなるだろう あとは、現在のアクセスパスを調べて、NESTED LOOPになっているようなら どうにかして他のJOIN方法になるように努力するぐらいしか思いつかん
652 :
649 :2012/04/18(水) 20:24:15.04 ID:???
>>650-651 ありがとうございます。
ちなみに、
>>649 のSQLを走らすと、20分以上掛かります。
USERSが10万件、RECORDSが10万×500世代以上あるからでしょうか。
explain(MySQL) を掛けてみると、USERSは全件ですが
RECORDSはtype=eq_ref, key=PRIMARYとなっていて、何となくindexは使われているような感じです。
select count(*) from records where gen_no = 100; の速度を調べてみるとか usersのカラム数がどれくらいあるのか知らんけど、多いならuser_no latest_gen_noのインデックスはるとか スワップが発生してないか調べるとか
654 :
649 :2012/04/18(水) 22:41:12.40 ID:???
>>653 >select count(*) from records where gen_no = 100;
一時間半以上掛かりました。
gen_noだけのindexがないので全件になりますね。
USERSテーブルのインデックスについてちょっと考えてみます。
>>652 同条件で試してみたけど10秒程度で帰ってくるから
チューニングとサーバーのスペックが問題じゃないかな
MySQLスレで聞いた方が良さげ
それでも10秒ぐらいかかるんだなぁという感想
>>657 同条件は語弊があったね
分かっているスキーマとレコード数だけしか考慮してないよ
659 :
649 :2012/04/19(木) 21:32:25.92 ID:???
>>655 10秒ですか。そのくらいで収まってくれるといいんですが。
チューニングの方向を試してみます。
ありがとうございました。
どうにも不思議なんでPostgreSQL(8.2 ←古い)で試したら100msぐらいだったよ。 mysqlとそんな差が出るとは思えないけど、参考になれば。 スペックもたいしたことないはず。 CPU pentium dualcore E2180 メモリ 1G HDD 普通のHDD あと、これもやっぱりおそい? select count(r.*) from users u join records r on (u.user_no=r.user_no and u.latest_gen_no=r.gen_no);
あれ、1万ユーザでためしてたゴメンゴ
MySQL5 開始日、終了日を持ったテーブルを日付単位に表示したいです。 tbl_job は、以下の構造です。 id, name, start_date, end_date --------------------------- 1, JOB1, 2012-04-01, 2012-04-03 2, JOB2, 2012-04-02, 2012-04-04 上記テーブルから以下のように日付単位でJOBを表示するSQLを教えてほしいです。 date, id, name -------------------- 2012-04-01, 1, JOB1 2012-04-02, 1, JOB1 2012-04-02, 2, JOB2 2012-04-03, 1, JOB1 2012-04-03, 2, JOB2 2012-04-04, 2, JOB2
664 :
649 :2012/04/21(土) 09:56:41.04 ID:???
あれから my.ini を編集してメモリをたくさん割り当てたり
DB アクセス時に HDD からカコンカコンと心臓に悪い音がしていたので
データファイルを他のドライブに移動したりしてみたら
>>649 の SQL が20秒ぐらいで帰ってくるようになりました。
皆さん、どうもありがとうございました。
大変助かりました。
>HDD からカコンカコンと心臓に悪い音がしていたので www
666 :
NAME IS NULL :2012/04/24(火) 04:19:16.07 ID:k32ZaufP
SQLite3を使っています。 カラムがなかったらinsert あったらupdateしたいのですが、 どういうSQLをかけばいいのでしょうか? insert into t1(c1, c2) values("hoge",10) update t1 set c2=10 WHERE c1="hoge" このときc1はuniqueです。 よろしくお願いします。
insert or replace
厳密にはSQLの質問じゃなんですが・・・ ER図を書くのにいいツールってないですか。 コードと連携する機能はなくていいですが、できればMacで動くのがいいです。 テーブルやカラムにコメントやメモが書けるとうれしい。
ERwin、ER/Studio、Object Browser ER、、、 フリーならDBDesignerぐらいか? Macは知らん
ERMaster使ってるけど EclipseプラグインだからMacでも動くんじゃね?
>>671 >ERMaster
これよさそうですね。ありがとうございます。
mysqlの記録した内容ってどこにあるのですか? 例えばxamppの場合は、xamppフォルダの中のmysqlフォルダの 中に入ってるのでしょうか? このフォルダの中身をコピーすると別のパソコンでも 記憶したmysqlのデータを扱えるのでしょうか?
スレ違い。
開始日、終了日という項目があって その両者の期間が重ならないような 制約をかけたいんだけど、 どう書けばいいの?
言語がSQLか否かにかかわらず、書けないんだろうw
>>676 制約というのがCHECK制約のことを指しているなら、無理。
CHECK制約では自分の行のデータしか参照できない。
開始日が終了日より前であること、ぐらいなら書けるけど。
別の行のデータを参照して期間が重複していないか調べたいなら、
トリガーを使うしかないかな。
アプリ側でやってもいいと思うけど。
同じレコードの中にある開始日と終了日の関係をチェックしたいと言うことじゃないの?
>>679 >CHECK制約では自分の行のデータしか参照できない
そういうDBもあるかもしれんが、それが標準的な仕様ではないと思うぞ
まあトリガかホストアプリでやった方が良いというのは同意するが
とりあえずSQL Serverでやってみた
CREATE TABLE TEST(
開始日 DATETIME ,
終了日 DATETIME
)
go
CREATE FUNCTION 期間ダブり件数(@開始日 DATETIME,@終了日 DATETIME)
RETURNS int
AS
BEGIN
DECLARE @retval int
SELECT @retval = COUNT(*) FROM TEST
WHERE (開始日 <= @終了日 and 終了日 >= @開始日)
RETURN @retval
END;
go
ALTER TABLE TEST
ADD CONSTRAINT 期間チェック
CHECK (dbo.期間ダブり件数(開始日,終了日) <= 1 ); --自分自身があるので1行はOK
go
これで行けてる気がする
ちがうDB使ってるなら知らん
>>681 スゲー!できるんだ。
でも条件はこれな気がした。
WHERE (開始日 <= @開始日 and 終了日 >= @開始日) or
(開始日 <= @終了日 and 終了日 >= @終了日)
>>682 それだと、たとえば5-10というデータが存在するときに、1-15ってデータが挿入できるんじゃね
いや、1-15は引っかかるけど逆に4-9は取りこぼすな。
どっちにしろ、
>>681 で正解。
postgres9.2では範囲型が導入されるので まさにやりたいことが出来るぞ まだリリースされてないがな
686 :
NAME IS NULL :2012/05/14(月) 11:36:13.64 ID:rmHVUy71
千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一 千歳科学技術大学 グローバルシステムデザイン学科 深町 賢一
687 :
NAME IS NULL :2012/05/15(火) 19:25:05.05 ID:bfF6xyzj
それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか! それよりゴキブリ高専卒どもはワシにさっさと謝罪せんか!
688 :
NAME IS NULL :2012/05/16(水) 04:26:17.61 ID:/ibgSKqe
すみません。 高専機械科卒なんですがお願いいたします。 以下のようなテーブルにて、あかさたなでGROUP BYしてそれぞれの件数を出力できないかどうか悩んでおります。 CREATE TABLE `name_list` ( kanji varchar(64), yomi varchar(64) ) INSERT INTO name_list (kanji,yomi) VALUES ('安部','あべ'), ('井口','いぐち'), ('臼井','うすい'), ('江本','えもと'), ('小川','おがわ'), ('柿本','かきもと'), ('木島','きじま'), ('九条','くじょう'), ('毛森','けもり'), ('小島','こじま'), ('佐藤','さとう'), ('しみず','')・・・・・・ 勿論、各頭文字で一件ずつじゃないのですが これを あ行 5件 か行 5件 さ行 8件 のように集計をかけたいと思っておりますが よい方法が思いつかず… 出力結果は、例でして出力した左側のフィールドはなんでもOKです。 右側のあかさたな行のそれぞれのレコード数がチェックできればOKです。 なにとぞよろしくお願いいたします。
substr(yomi,1,1) 使ってみそ GROUP BY とSELECT両方に
おっと、ここは汎用SQLのスレか。 環境によって変わるので、使ってるDBMS名とかも書いてね
SUBSTRING(yomi FROM 1 FOR 1) これならほとんどいける?
693 :
689 :2012/05/16(水) 14:14:09.84 ID:???
申し訳ないです。テーブル内容書くのに悩んでいてテンプレを忘れておりました。
mysql 5.1です。
>>690 >>692 両方試してみます。
夕方までに再度レスします。
694 :
689 :2012/05/16(水) 14:19:25.55 ID:???
さっそく試してみました。
>>690 ,
>>692 のどちらも共に期待通りの結果が得られました。
あとは、あかさたな行にアプリケーションで整形します。
どうもありがとうございました。
まあ ||'行' とかで連結する手もあるな
696 :
689 :2012/05/16(水) 14:54:12.43 ID:???
あ、いえ、行単位とは 頭文字あ〜おの行、か〜この行という単位でほしかったのです。 説明が足りず申し訳ございません。
濁点半濁点も入れるとSQLだけでは長文になりそう
できないことも無いけど、プログラムで弄れるならそっちのがよさげだね
まず50音表テーブルをつくるんだ!
「い」でもグループ化されそうに見えるけど、それでもよかったぽいね
アクセス権限の付与でききたいことがあります。 GRANT UPDATE ON TABLE TO NANASHI これだとNANASHIにTABLE表の更新を権限を与えるのですが TABLE表の特定の列だけ権限を与える場合は GRANT UPDATE[列名] ON TABLE TO NANASHI でよろしいのでしょうか?
[ ] じゃなくて ( )
>>703 ありがとうございます。カッコが違ってたのですね。
かっこわるい
Oracleです テーブルA 列a,列b,列c テーブルB 列m,列n テーブルC 列s,列t WHERE 列b=列s or (列c=列m and 列n=列s) で全列出力したいんですけど列b=列sでマッチすると列Bが全レコード結合されてしまいます 前者でマッチした時は列mと列nは出力しないようにしたいです AとCは基本的に全列出力されるので、Bだけを条件によって出力されなかったりするJOINって作れますか
>>706 欲しい出力結果がよくわからん
>前者でマッチした時は列mと列nは出力しないようにしたいです
条件によって出力される列の数を変えたいのか?
>>706 unionに変えちゃまずい?
select a, b, c, null, null, s, t from A, C where b=s
union all
select a, b, c, m, n, s, t from A, B, C where c=m and n=s
あと、 select distinct a, b, c, case when b=s then null else m end as m, case when b=s then null else n end as n, s, t from A, B, C where b=s or c=m and n=s みたいなのでもいける気はする 試してないから構文エラーとかあったらごめん
710 :
NAME IS NULL :2012/05/30(水) 17:18:38.29 ID:FSJSgAvr
質問です。。 ・Postgresql 9 ・テーブルデータはざっくりですが、以下のような感じです。 table_name id | state | name | pride ------+-------+-----------+---------------- 1 | 2 | hoge1 | 01 2 | 1 | hoge2 | 02 15 | 2 | hoge3 | 02,03 16 | 1 | hoge4 | 02,04,05 33 | 1 | hoge5 | 04 34 | 1 | hoge6 | 01,05 35 | 1 | hoge7 | 01,02,03 36 | 1 | hoge8 | 01,02,03,04 実際は、もっとレコード数が多いと思っておいてください。 ・やりたい事 ランダムに10件、とかselectして表示させたいのですが、 state = 1 である事が絶対条件で、 なおかつ pride の、 「01」が含まれるものの中から10件、ランダムに抽出 「02」が含まれるものの中から10件、ランダムに抽出 ・・・以下、実際のデータでは20位まで続きます。 ・・・といった内容を、出来るだけ簡潔に書こうと思うと、どんな方法があるでしょうか? ちなみに、最終的にはidとnameを表示させるだけ、 phpでWEBに表示させます。 SELECT id,name FROM table_name WHERE state = 1 AND pride LIKE '%01%' ORDER BY RANDOM() LIMIT 10 これで「01」が含まれるものの中から10件、ランダムに抽出・・・ はできるのですが、コレを20回って・・・と思いますし、 SELECT id,name FROM table_name WHERE state = 1 で全部出力して配列に突っ込んでからソートしなおす、 というのもあまりスマートでないような気がして。。。 良い方法ないでしょうか。
>>710 たぶん無い。
WITH RECURSIVEを使えば見た目スマートに出来そうな気もするが、
結局はSQL側でループするか、ホスト言語(PHP)側でループするかの違いしか無い気がします。
712 :
710 :2012/05/30(水) 20:15:33.99 ID:9ULM8hGf
>>711 おぅ・・・そうですか。
WITH RECURSIVEも調べてみましたが…うーん。。。ですね。
地味にやるしかないかなぁ。
ありがとうございます。
質問です sql server 一つのSQLで複数のテーブルを更新したいです。 ★INSERT ALL、UNIONは使わない ★IDは日付6桁に下5桁は連番にする insert into table1 select case when (max(substring(table1.ID,1,8))) is null then CONVERT(VARCHAR,GETDATE(),112) + '00001' else CONVERT(VARCHAR,GETDATE(),112) +right('0000'+convert(varchar,convert(float,SUBSTRING(max(table1.ID),9,5)+1)),5) end as table1.ID , CONVERT(VARCHAR,GETDATE(),120) as table1.ID , 1 as table1.KYAKU_ID , CONVERT(VARCHAR,GETDATE(),120) as table1.ENT_DT , CONVERT(VARCHAR,GETDATE(),120) as table1.UPDT_DT , 0 as table1.DEL_FLG from table1 begin INSERT into table2 select case when (max(substring(table2.ID,1,8))) is null then CONVERT(VARCHAR,GETDATE(),112) + '00001' else CONVERT(VARCHAR,GETDATE(),112) +right('0000'+ convert(varchar,convert(float,substring(max(table2.ID),9,5)+1)),5) end as table2.ID, 1 as table2.SEQUENCE, 1 as table2.SYOUHIN_ID, 2 as table2.SYOUHIN_KAZU, 1 as table2.SYOUHIN_TANKA, 20 as table2.TOTAL_PRICE, CONVERT(VARCHAR,GETDATE(),120) as table2.ENT_DT, CONVERT(VARCHAR,GETDATE(),120) as table2.UPDT_DT, 0 as table2.DEL_FLG from table2 insert into table1 select case when (max(substring(table1.ID,1,8))) is null then CONVERT(VARCHAR,GETDATE(),112) + '00001' else CONVERT(VARCHAR,GETDATE(),112) +right('0000'+convert(varchar,convert(float,SUBSTRING(max(table1.ID),9,5)+1)),5) end as table1.ID , CONVERT(VARCHAR,GETDATE(),120) as table1.ID , 1 as tabke1.KYAKU_ID のところでエラーが出ます(table2でも同じ部分でエラー有り) いろいろ考えましたがどこが間違ってるかわかりません 訂正など教えて貰えれば助かります。お願いします。
714 :
713 :2012/05/31(木) 02:10:28.08 ID:???
すいません 訂正です IDは13文字 日付は8桁は下5桁は連番でした
>>710-711 select id, name, rank() over (partition by match_pride order by random()) as rank_in_pride
from table_name join (values('01'), ('02'), ('03')) as t(match_pride) on pride ~ '.*' || match_pride || '.*'
where rank_in_pride <= 10
window関数も正規表現も使ったことないけど、こういうのできないのかな
>>713 as table1.ID ってかけるもんなの?
ともあれ、エラーが出なくなるまでどんどん削って特定するのが楽だと思うよ。
あとはエラーメッセージを読むとか。
717 :
710 :2012/05/31(木) 09:09:09.66 ID:WUyDFWiQ
>>715 IDコロコロ変わってますけど、移動してるからデス。
さてはて、レスありがとうございます。
試してみましたが、そのままではエラー返って来ました。
ON pride ~ '.〜
辺りで引っかかっているようです。
argument of JOIN/ON must be type boolean, not type text
ってエラー出たので・・・ナニコレ。prideはbooleanじゃなくてtextだよ、と言ってるのかな?
ともあれ、Window関数ってテもあるんですねー。
勉強になります。。
|| は文字列の連結。論理和は or だよ。
on pride ~ ('.*' || match_pride || '.*') こうすればいいのかな。 on pride like ('%' || match_pride || '%') でいけるのならそれでも
720 :
719 :2012/05/31(木) 15:07:16.46 ID:???
>>717 argument of JOIN/ON // onの引数は
must be type boolean, // (その評価結果が)booleanであるべき
not type text // textじゃなくてね。
>>718 うん。
721 :
719 :2012/05/31(木) 15:25:47.42 ID:???
そうか、postgresqlだから、 (values('01'), ('02'), ('03')) as t(match_pride) を (select to_char(i, '00') as match_pride from generate_series(1, 20) as t(i)) as t こうかけるかも。
あと、state=1の割合も教えて indexが利きそうなくらいのカーディナリティの低さはある?
ごめん s/低さ/高さ/
とりあえずsqlかいたら?
726 :
710 :2012/06/01(金) 07:14:56.50 ID:ESzAumhQ
>>719 うーん、上手く行かないですね。。。
すいません、あんま時間がなくて、ちゃっちゃとコピペして試しただけなので、
エラーの理由とかチェック出来てませんが;;
>> 722
>> 723
今のトコ2000ぐらいです。
state=1の割合は9割弱でしょうか。
実際には、0、1、2、3が使われています。
ユーザのステータスを表していて(にしちゃ、スペルがヘンなのは無視してくださいw)
0 仮登録
1 使用中
2 停止中(ユーザ任意の停止)
3 利用禁止(管理者任意の強制停止)
こんな感じです。
>>226 すまん家族サービスでレス遅くなった、
2000レコードとか少ないうちはこんなんでそこそこいけるかな、
select
priderec --pride
,id
,name
from
(
select
id
,name
,priderec
,rank() over(partition by priderec order by random()) as cnt_per_pride
from
(
--分解しレコードに変換
select
id
,name
,unnest(string_to_array(pride,',')) as priderec
from
table_name
where
state = 1
) a
where
-- 20以下のprideのみ
priderec::int <= 20
) b
where
--pride当たりは10件に制限
cnt_per_pride <= 10
order by
priderec::int
;
一度全部レコードに展開してる。
強引といえば強引なのでコストは結構高いよ。
prideの中身とレコード数自体が10万以上とか増えてくるとだんだん破綻してくると思う。
その時は
・1〜20で繰り返してレコードを抽出して処理
に切り替えたほうが良さそうだね。これもSQLだけでいけるよ
ただ、抽出でシーケンシャルだとこれも辛いので、
数が増えそうなら、テーブル構成の変更をおすすめするぞ。
このままに近いテーブル構成取るにしても、
prideを配列型にして、ginインデックスを貼って、
pride_arrの要素検索でインデクスが効くようにするといいと思う。
729 :
NAME IS NULL :2012/06/12(火) 22:10:11.19 ID:7l5jIcyB
DBはSQLiteを想定してますが、MySQLでもpostgreSQLでも全然かまいません 採取リスト |番号|名称|コード|登録日|登録者|公開| というテーブルがあります。 イメージとして、とある物体がありまして、登録者が各自で次々と登録していきます。 各物体には登録者の間で共有されていてぶれのないコード(A-0001とか)があるものの、 名称に関しては、ある程度の裁量があるため、登録者によって表記にぶれが起きます。 |番号|名称 |コード | 登録日 |登録者|公開| |01 |クラゲ |A-001|2012/6/1 | 田中 | 1 | |02 |くらげ |A-001 |2012/6/2 | 鈴木 | 0 | |03 |海月 |A-001 |2012/6/3 | 佐藤 | 1 | |04 |クラゲ |A-001|2012/6/4 | 高橋 | 0 | |05 |ひとで |A-002|2012/6/5 | 小林 | 0 | 番号はオートナンバーで主キー。 登録日はそのままINSERTされた日。 告知フラグは0か1で、外部に公開されていたら1です。 んで、ここから公開されてない行を抜き出すビューを作りたいんです。 CREATE VIEW 未公開リスト (番号, 名称, コード) AS SELECT 番号, 名称, コード FROM 採取リスト WHERE 公開 = 0 みたいなSQLを走らせると、 |番号|名称 |コード| |02 |くらげ |A-001| |04 |クラゲ |A-001| |05 |ひとで |A-002| という風になってしまいますが「くらげ」と「クラゲ」で実質的に重複してしまいます。 これを例えば「コードを基準にして重複がないように選んだ」上で、 名称には、特定の登録者の名称を用いてまとめることはできないのでしょうか? 単に、DISTINCTを使うだけでは無理なようですが・・・。
「特定の登録者の名称を用いてまとめる」の意味が分かんない
たぶん
>>4 だと思うけど
特定の登録者の名称を用いてまとめる って何?具体的にどういうこと?
732 :
729 :2012/06/12(火) 22:45:31.35 ID:7l5jIcyB
説明不足ですいません。
要は「クラゲ」と「くらげ」は同じものを指しているのに、カタカナと平仮名の表記の違いから別物だと認識されてしまうので、
登録者の鈴木の用いてる名称(この場合は「くらげ」)に合わせて、それに統一させることはできないのか?ということです。
>>729 の例だと、
|番号|名称 |コード | 登録日 |登録者|公開|
|01 |クラゲ |A-001|2012/6/1 | 田中 | 1 |
|02 |くらげ |A-001 |2012/6/2 | 鈴木 | 0 |
|03 |海月 |A-001 |2012/6/3 | 佐藤 | 1 |
|04 |クラゲ |A-001|2012/6/4 | 高橋 | 0 |
|05 |ひとで |A-002|2012/6/5 | 小林 | 0 |
ここからSELECT文に「WHERE 公開フラグ = 0」の条件を入れて検索したときに
|番号|名称 |コード|
|02 |くらげ |A-001|
|05 |ひとで |A-002|
こういう結果が欲しいんです。
>>732 一意になる基準を決めれ。番号か名称か登録日で一番小さいものとか。
734 :
729 :2012/06/12(火) 23:08:17.40 ID:7l5jIcyB
特定の登録者(最も正しい表記をしてくれるであろうと期待される人間)の名称を用いる、という基準を一応持っています。
ぱっと思いつくところだと、 postgresならwindow関数使って、 同じコードでの区間集計で、ひらがな、カタカナ、漢字ならの中で、order byでこの順に並べ替えることによって、 常に最初のもの、とか最後のもの、(或いはN番目のもの)を選択するって感じならできると思うが、 ひらがなに統一とか、鈴木の書いたケースに統一っていのはなかなか難しいと思う。 DBから見たら違うものでしかないし、判断できないから。 ひらがな、カタカナ、漢字の区別をつけて値を返す関数を作成すれば出来そうだけどね。
>>734 その優先順位のデータがあるならばできなくはないが、標準SQLの範囲では
あまり効率はよくないだろうな。
指定した人がいないコードとかではどうすんの? 仕様が曖昧すぎて出せない
まあ、設計の話はスレ違いだが 普通の設計では、コードと正しい名称を持ったマスタテーブルを別にもつんだが
739 :
729 :2012/06/12(火) 23:35:24.67 ID:7l5jIcyB
なるほど・・・・特定の登録者を用いた名称、というのは難しいんですね・・・
ありがとうございました。
>>737 確かにそうですね・・・
>>738 詳しくお願いできますか?
その正しい名称というのは事前に入力しておかないといけないのでしょうか、やはり?
>>739 特定の登録者って、どうやって特定するのか決めろって言ってるんだが
一定の条件で機械的に決まるなら出来るだろうって言ってる
人間が判断して決めないとダメなら、その判断した結果を入力しておかないと無理
741 :
729 :2012/06/13(水) 00:22:53.37 ID:emGltIb9
>>740 登録者の優先順位をつけたテーブルを事前に用意してそこを参照する・・・というのは少し複雑ですね。
>>734 その鈴木さんのレコードがなかったら誰を頼りにするんだろ
ごめんまるかぶりでした。
ってだけだと申し訳ないので…
>>739 A-001は鈴木さんも田中さんも高橋さんも選ばないといけないのかな。
たとえばコードに対応する名前を入れられたら、それをマスタ登録して、
ほかの人は自動で入力されるようにしたら、統一できるし楽にならないかな。
あとは優秀な鈴木さんにマスタの名称を変更させる機能を提供するとかで。
そもそも複数登録できるようになってるのがおかしいとは思うんだけど、そうなってる理由ってなんだろう?気になる。 登録の際にコードが被ったら弾くか、名称の変更を行なって登録するのが普通だとは思うが。
>>734 登録者の優先順位をこんな具合に人間が決めていいのかな?
create table 採取リスト (番号 serial, 名称 varchar(100), コード varchar(100), 登録者 varchar(100), 公開 int);
create table 優先 (登録者 varchar(100), 優先度 int);
insert into 採取リスト (名称, コード, 登録者, 公開) values ('クラゲ', 'A-001', '田中', 1), ('くらげ', 'A-001', '鈴木', 0), ('海月', 'A-001', '佐藤', 1), ('クラゲ', 'A-001', '高橋', 0), ('ひとで', 'A-002', '小林', 0);
insert into 優先 values ('田中', 0), ('鈴木', 4), ('佐藤', 1), ('高橋', 2), ('小林', 3);
select 番号, コード,
(select 名称 from 採取リスト join 優先 using (登録者) where 採取リスト.コード = 未公開.コード order by 優先度 desc limit 1) as 名称
from 採取リスト as 未公開 where 公開 = 0 group by コード;
747 :
729 :2012/06/13(水) 08:42:47.08 ID:N2kuDrG0
皆さん本当に丁寧にありがとうございます SQLiteはusingとか使えないっぽいです 確かに最初にコードと名称が打ち込まれたら、以降は名称の入力を許さないというのもあると思います・・・。 最初に間違った名称が入力された場合、以降はそれに統一されかねないのがややネックですが
USING使えなかったらON に置き替えりゃいい
749 :
NAME IS NULL :2012/06/13(水) 17:36:35.61 ID:KVKN/UOS
2ch風スレッド掲示板を作成しているのですが
そこのトップページ作成時のSELECT文の書き方に迷ってしまったため、
お教えいただければと思っております。
・RDBMS
MySQL 5.1
・テーブル構造
//スレッドテーブル
CREATE TABLE IF NOT EXISTS `bbs_master` (
`threadId` int(11) unsigned zerofill NOT NULL auto_increment, //スレッドID
`status` tinyint(4) unsigned default '1', //スレッドのステータス(スレストとか)
`subject` text, //スレタイ
`res_count` int(11) NOT NULL default '0', //現在のレスの数
`createdDate` datetime default NULL, //スレッド作成日
`updatedDate` datetime default NULL, //最終更新日
PRIMARY KEY (`threadId`),
KEY `status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
//レステーブル
CREATE TABLE IF NOT EXISTS `bbs_data` (
`replyId` bigint(20) unsigned NOT NULL auto_increment,
`status` tinyint(4) unsigned default '1', //レスの状態(あぼーんとか)
`threadId` int(11) unsigned zerofill default NULL, //紐付されるスレ
`username` varchar(32) default NULL, //ユーザ名
`body` text, //レス本文
`mailAddress` varchar(128) default NULL, //メールアドレス
`createdDate` datetime default NULL, //レスした日
PRIMARY KEY (`replyId`),
KEY `status` (`status`),
KEY `threadId` (`threadId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
//外部キー
ALTER TABLE `bbs_data`
ADD CONSTRAINT `bbs_data_ibfk_1` FOREIGN KEY (`threadId`) REFERENCES `bbs_master` (`threadId`) ON DELETE CASCADE ON UPDATE CASCADE;
スレッドテーブル側にてスレッド一覧を持ち
レステーブル側でレスをスレッドIDと紐付て
>>1 から持つように作成しております。
トップページにおきましては、2chの板トップページと同じく
最新の書き込みのあったスレッドを10件程度 それぞれ最新のレスを10件程度と共に載せようと思うのですが
そのSELECT文の書き方で行き詰ってしまいました。
10件ずつレスを呼び出す福問い合わせをスレッドの分だけ回せないかなどと考えているのですが
使う機能の名前や大まかな流れ等でもお教え頂ければと思います。
よろしくお願いいたします。
泥臭く書けばどうにでもできるような。 まずは動くようにしてみたら?パフォーマンスに問題がなければアプリで制御してもいいんだよ
751 :
749 :2012/06/13(水) 20:11:07.42 ID:KVKN/UOS
>>750 返信ありがとうございます。
個人のサイトで仲間内とネトゲーの情報をやり取りする程度で使うつもりですので
パフォーマンスは全く問題ではなく、極端な話
一旦、
SELECT threadId,subject..... FROM bbs_master ORDER BY bbs_master.updated DESC LIMIT 10
でクエリー回してアプリで受け取り
その後、そのループ内でレスを拾うクエリーを都度投げるですとかならできるのですが
自分のレベルアップを狙って、一回のSQL文でスレッドごとにレスを10件ずつに制限しながら10スレッド分引くにはどうすれば?と考えたときに行き詰ってしまいました。
ヒントや大まかな流れ等だけでも結構ですのでなにとぞよろしくお願いいたします。
この前の続きかな、 なんだ、そういうのを考えるのが楽しいんじゃんよ。 スレッドマスタなのにbbs_master?と思ったらカテゴリは無いのか。 ってのはいいとして、 ・アプリで回す bbs_masterから最新10スレッド取って来る->アプリでそのスレッドに付き最新10レス取得をループ ・1クエリで済ませる bbs_masterから最新10スレッド取ってきて(サブクエリ)、 そのスレッドidにつき、bbs_dataテーブルとjoinして最新レス10件取ってきて、 スレッドid(+その他カラム)でgroup byして、 スレッドの更新時刻 降順->レスの更新時刻降順でorder by な感じ? クエリを組むときは、 目的の結果を得るためにどうしたらいいのか、 一歩一歩頭で組み立てながらクエリを組むと良いのでは。
753 :
749 :2012/06/13(水) 21:08:20.73 ID:KVKN/UOS
>>752 ご返信ありがとうございます。
テーブルの命名も些末なものだったようで大変恐縮です。
あと申し訳ないのですがこの件は、初診(?)となります。
自身のレベルアップも目的ですので
事例を探しながら組もうと頑張っていたのですが
複数件返される副問い合わせを元にしてクエリーを回すという部分で
どうも混乱してしまって、後頭部が痛くなってきたところで降参してしまいました。
努々、楽しめるよう肝に銘じたいです。
お教え頂いた流れ上で再度挑戦してみます。
どうもありがとうございます。
あぁ、 スレ取ってきて、 それを元にselect句で相関サブクエリでもいいか、ていうか、こっちの方がシンプルか まぁもがきながらでも自分で組んでみた方がいいよ
よく考えたらselect句じやダメだな
スレッドidごとに10件てところが面倒だろうと思ってたけど、そこはスルーされてるんだな。。
757 :
749 :2012/06/14(木) 15:54:05.36 ID:???
すみません、いまだに目標に到達できません。
>>755 うー、select句じゃダメなんですか。
仕事もあるので、これに注力しきれてないのですが
MySQLのリファレンスから機能を総洗いしてみて使えるのを拾っていこうかと考えています。
>>756 あれれ、スルーしましたか??
select レス from bbs_data where スレ in (select スレ from bbs_master where 最新10スレ) and スレごとに最新10レス
759 :
758 :2012/06/14(木) 16:03:41.39 ID:???
>>757 ううん、アドバイスしてる人がそこをスルーしてるなっておもって。
760 :
758 :2012/06/14(木) 16:07:26.65 ID:???
select レス from bbs_data where スレ in (select スレ from bbs_master where 最新10スレ) and exists (select * from bbs_data where スレ = スレ and レス > (select max(レス) from bbs_data where スレ = スレ) - 10) っぽい感じになるのかな。
761 :
758 :2012/06/14(木) 16:12:11.84 ID:???
ん? select レス from bbs_data join bbs_master using (スレ) where スレ in (select スレ from bbs_master where 最新10スレ) and レス > スレ.res_count - 10 これでいいのかも
762 :
749 :2012/06/14(木) 16:44:30.11 ID:???
>>758 ありがとうございます。
本職中なのでまだ試してないのですが
それで完璧なように見えます。
自分で作っておいてなんですが、res_count - 10で1スレあたりの数を制限できるのに全く気付いてませんでした。
どうもありがとうございました。
A Table a1 a2 -- -- 1 A 3 B 5 C 6 D B Table b1 b2 -- -- 2 E 4 F 6 G を select で a1 a2 b1 b2 -- -- -- -- 1 A null null 3 B 2 E 5 C 5 F 6 D 6 G にしたいけど、どうしたらいいでしょうか?
すみません a1 a2 b1 b2 -- -- -- -- 1 A null null 3 B 2 E 5 C 4 F 6 D 6 G でした
基準がよくわからん
意味がわからん それぞれの列にどういう意味があって、どういう条件で同じ行にしたいの? a1を超えない最大のb1?
>>763-764 条件がよく分からんがこういうことか?
select
A.a1,A.a2,B.b1,B.b2
from
A
left outer join B on(
TO_NUMBER(A.a1)=TO_NUMBER(B.b1)+1 or
TO_NUMBER(A.a1)=TO_NUMBER(B.b1))
;
たぶんもうちょっと変な要望があるとおもう
これはかなりの難問。 条件は、A tableとt B tableの最後のデータを横一列ににするとか。 積み上げ棒グラフを作るようなイメージ。
770 :
sage :2012/06/21(木) 12:06:59.60 ID:oEiJL9az
すまん、763です。具体的に言うと 株価Tab(時刻、株価) 為替Tab(時刻、$\為替レート) を株価のテーブルをメインにして SELECT時刻、株価、$|為替レート にしたいんだけど株価と為替の時刻は当然一致していないけど、 株価の時刻からみて最新の為替レートを表示したいんです。 よろしくおねがいします。
ぽいね
773 :
NAME IS NULL :2012/06/21(木) 18:04:51.54 ID:uEysGvXe
・DBMS名とバージョン: Access2003 ・テーブルデータ: ID、作業開始日、作業完了日、作業区分 ・欲しい結果 一定期間の作業開始日及び作業完了日を日付別にカウントしたい。 ・説明 例えば、2012/06/01から2012/06/07の期間を指定した場合、以下の様に取得したい。 日付 作業開始 作業完了 2012/06/01 10 10 2012/06/02 5 5 2012/06/03 20 15 2012/06/04 21 20 2012/06/05 7 10 2012/06/06 10 15 2012/06/07 4 10
>>770 >すまん、763です。具体的に言うと
次回からは、初めから具体的に言ってくれ。
>>773 作業開始、完了ってのはドコで見分けるの
作業区分?完了日がnullとか?
>>770 こうかな?
select *
from A T1
left outer join
B T2
on T1.a1 >= T2.b1
where not exists (
select *
from B T3
where T1.a1 >= T3.b1
and T2.b1 < T3.b1
)
order by a1
;
780 :
773 :2012/06/21(木) 20:58:02.92 ID:???
ああ、しかしAccessか 再帰問合せもCASEもないっぽいねえ
782 :
776 :2012/06/21(木) 23:46:34.36 ID:???
>>780 単一クエリで処理する方法は分からないから UNION で
SELECT 作業開始日 AS 日付, Count(作業開始日) AS Count開始日, NULL AS Count完了日
FROM テーブル1
WHERE 作業開始日 IS NOT NULL
GROUP BY 作業開始日
UNION ALL
SELECT 作業完了日, NULL, Count(作業完了日) AS Count完了日
FROM テーブル1
WHERE 作業完了日 IS NOT NULL
GROUP BY 作業完了日
>>782 それだと同じ日付が開始と完了で2回でるんじゃね
作業開始日、作業完了日でカウントしてFULL OUTER JOINで行けると思うけど
ACCESSってFULL OUTER JOIN使えないんだっけ?
ダメなら、作業開始日と作業完了日でUNIONして日付マスタっぽいのつくって、
相関サブクエリでそれぞれの件数とれば行けるかと
UNIONした結果を日付でGROUP BYして、SUMすればいいとも思う
無茶苦茶強引にやるなら select A.日付,A.作業開始,B.作業完了 from (select A1.日付,A2.作業開始 from (select 作業開始日 as 日付 from テーブル union select 作業完了日 as 日付 from テーブル ) as A1 left outer join (select 作業開始日,count(*) as 作業開始 from テーブル) as A2 on (A1.日付=A2.作業開始日) ) as A left outer join (select 作業完了日,count(*) as 作業完了 from テーブル) as B on (A.日付=B.作業完了日) ; でいけそうな気がする
>>783 きっとレポートで集計するんでしょ
単純にクエリが欲しいなら 784 で良いし
id5とid10という2つの情報しかないのですが id5がもつc1とid10がもつc1を交換するとき どういうクエリーをかけばよいでしょうか? 1.select c1 from t where id=5 or id=10 order by id 2.begin transaction 3.update t set c1=? where id=5 (?は1でとったid10のc1値) 4.update t set c1=? where id=10 (?は1でとったid5のc1値) 5.commit 自分の能力ではこんな手順が限界ですが サブクエリーを駆使したらupdate1文でいけたりするのでしょうか? もしできたらどんな感じの文になるか教えていただきたいです
>>788 ありがとうございます
開発環境がMySQLとSQLiteなのでちょっと厳しそうですが
SQLite以外では出来そうなことはわかったので
がんばってググってみます
sqlite は、だめだな。 今、手近なマシンで試したら... SQLite version 3.6.13 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .schema t CREATE TABLE t (a, b); sqlite> select * from t; 1|1 2|2 3|3 sqlite> update t set b = case a sqlite> when 1 then (select b from t where a = 3) sqlite> when 3 then (select b from t where a = 1) end where a in (1, 3); おっ、エラーにならないじゃん。 sqlite> select * from t; 1|3 2|2 3|3 Orz… まだ、エラーになる方がマシだよ。
>>790 sqliteよくしらないが、それテーブルに相関名付けても同じなのか?
・DBMS名とバージョン: SQLServer2008R2 ・テーブルデータA: No.,テーブルB用id ・テーブルデータB: id,No.,nvarchar(MAX) ・欲しい結果 テーブルデータAのNo.でクエリすると紐付いているテーブルBの文字列をBのNo.昇順に連結したデータを取得したい A No id -- -- 1 a 2 b B id no text -- -- ---- a 1 あ a 2 い a 3 う b 1 か b 2 き 結果 a あいう b かき ・説明 8000文字を超える文字列を扱いたいがSQLServerの設定はいじれない ストアドは使用可能 アプリ側で対応も出来るが可能ならSQL側で完結させたい
>>791 いくつかやったけど、同じだった。
まあ、相関名つけたら挙動が変わるというのも、それはそれでどうかと思うし。
>>792 with t as
(
select id,no,cast(text as nvarchar(max)) as text from B where no=1
union all
select B.id,B.no,t.text+B.text from t
join B on B.id=t.id and B.no=t.no+1
)
select t.id,t.text from t
join A on A.id=t.id
where
t.no=(select MAX(no) from B where id=A.id)
;
796 :
795 :2012/06/23(土) 22:32:32.40 ID:???
補足 noは1から連番で振ってある事が前提 再帰クエリでやってはみたが、どう考えてもストアド作る方がいいな、これ ストアド扱うスレってあったっけ?
797 :
792 :2012/06/23(土) 22:44:44.09 ID:???
>>793 おお、XMLドキュメントとして扱うとは!
すごく盲点でした
>>795 こ、これは高度すぎて初心者の自分にはわけわかめ
精進します
お二方ありがとうございました
798 :
NAME IS NULL :2012/06/24(日) 01:06:38.36 ID:xl2vNYYv
【質問テンプレ】 ・DBMS名とバージョン sqlite3 ・説明 今はUNIQUE制約をつけると支障が出るのでUNIQUEはつけず 準備ができ次第将来的にUNIQUEを追加する予定です ※今は使わない不要なカラムにDEFAULTを空文字で埋めていて そのためUNIQUEがつけられません あとでUNIQUE制約を追加する方法ですが ALTER TABLE t ADD UNIQUE (c1, c2)では UNIQUEのところでエラーが出てしまい働かなかったので CREATE UNIQUE INDEX t_uni on t (c1, c2)にしたところ作成できたのですがこれでいいのでしょうか? 両者の違いがわかりませんがテーブルを変更するのはALTERだったと思うので こんなんでいいのか困っています 問題があれば正しいSQLとアドバイスをお願いしたいです
799 :
NAME IS NULL :2012/06/24(日) 21:06:00.04 ID:5hY+sk/g
DBMS名とバージョン PostgreSQL 8.4 仕事でどうしてもsql触らないといけなくなったので今朝から勉強してるんですが 一度構文エラーだとかを起こしてしまった後に他のSELECT文だとか打って 実行しようとして;を打った後Enterを押してもスルーされてしまうのですが その解決方法教えていただけませんか?
どこで打ってんだよ トランザクション中であれば、 無視されて当然だしそれで正解。
>>800 なるほど
何かヒントになりそうです
どうもありがとうございます。
マスターとなるテーブル内で「*」を使うのってありなんですか? 目印の代わりにつけたみたいなんですが 検索とかで影響でないんでしょうか? ちなみにSQL Server 2005 です。
>>798 SQLiteはalter tableで制約の変更はできないみたいね
どっちにしろユニークインデックスで問題なし
>>802 質問の意味が分からん
SQLで「*」はワイルドカードではないよ
select句で使えば「全ての列」という意味にはなるけど
スレ違いではあるけれど。 目印って書いてるから、カラム名に*をつけたいってことだよね。 id* みたいな。 それができるRDBMSがもし存在したとしても、するべきじゃないよ
データとして'*'が入ってるってことか?
Sqliteで列(カラム)の数を取得したいんですがどうすればいいですか?
sqlの中でってこと? それともただ単にわかればいいの?
単にわかればいいです、androidソース側から
であれば、 pragma table_info(テーブル名) の結果行数を数えれば良い
なるほぢど、やってみます
812 :
NAME IS NULL :2012/06/28(木) 20:50:45.25 ID:CzuyUlLS
勤続年数をyy.mmの形で出したくて datediff(year,入社月日,今日)と例えばしてるのですが、yearの部分の変更で対応できるのでしょうか?
DATEDIFFでググったら出てきたぞ
814 :
NAME IS NULL :2012/06/28(木) 23:11:08.14 ID:CzuyUlLS
自分で試すだけやん…
table1 id | name ----------- 0 | りんご 1 | みかん table2 no | id ---------- 0 | 0 1 | 0 2 | 1 3 | 1 4 | 1 この二つのテーブルから以下の結果を得るSQLの書き方を教えてください id | name | num ------------------- 0 | りんご | 2 1 | みかん | 3 select id, name, (select count(code) from table2 as t2, table1 as t1 where t1.id=t2.code) as num from table1; 自分で考えた↑では2行ともnumが5になってしまいました
SELECT id, COUNT(id) FROM table2 GROUP BY id の結果と table1 を結合
>>817 select t1.id, t1.name, t2.id, count(t2.id) from table1 as t1, table2 as t2 where t1.id = t2.id group by t2.id
で目的の結果が得られましたが、table1にのみ(2,いちご)を追加しても
id | name | num
-------------------
0 | りんご | 2
1 | みかん | 3
2 | いちご | 0
とはなりらずに、追加前と同じ結果でした
片方のテーブルにない物も集計対象にするにはどうしたらよいのでしょう?
from句以下を table1 as t1 left outer join table2 as t2 on t1.id=t2.id group by t2.id; にしろ
一方に無いものも欲しい という場合は、とりあえず「外部結合」って奴を思い出してあげてください。
822 :
816 :2012/07/02(月) 23:37:11.47 ID:???
>>819 , 821
819のやり方でうまくいったと思ったのですが、table1に(3,バナナ)を追加して
table2で未使用のレコードが2つになっても
id | name | num
-------------------
0 | りんご | 2
1 | みかん | 3
2 | いちご | 0
のままでした
そこで
select t1.id, t1.name, t2.id from table1 as t1 left join table2 as t2 on t1.id = t2.id;
なviewを作って
そのviewにたいして
select t1.id, t1.name, count(t2.code) from view1 group by id;
としたところ欲しかった
id | name | num
-------------------
0 | りんご | 2
1 | みかん | 3
2 | いちご | 0
3 | バナナ | 0
が得られました。
ありがとうございます。
t2側でgroup byしてるからじゃないの? select t1.id, t1.name, count(t2.id) from table1 as t1 left join table2 as t2 on t1.id = t2.id group by t1.id, t1.name でいいような しかしgroup byがそんな変な動きするのってMySQLだっけ?
>>823 group byがっていうか
>select t1.id, t1.name, t2.id from table1 as t1 left join table2 as t2 on t1.id = t2.id;
>なview
セレクトリストでidがかぶってるのにエラーにならんのかと...
たぶんt1.idがidって名前で生きてるからうまくいってるんだと思うが
>select t1.id, t1.name, count(t2.code) from view1 group by id
これ通すのもMySQLぐらいか
sqliteで select * from test where a = '1' or a = '2' って感じで取得してるんですが、 上記のwhereで指定した条件の順番に結果がかえってこないんです。 理想としてはaが1のデータが配列の0番目の要素、2のデータが配列1番目の要素って感じに、 where句で指定した順に取得したいんです そんなことは無理なんでしょうか? ちなみにソートでは対応できない任意の順番なのでorder byでは無理です。 ちなみにunionでselect文で繋いでも、where句で指定した順番では帰ってきませんでした。 暫定対応としてselect文を一度ずつ実行して配列に入れています。
無理。
SQLって使えねーな ありがとうございました
自分の力量のなさをツールのせいにするなよ
うるせー PHP板からいちいちやってくんなカス
>>825 > order byでは無理
この決めつけが視野を狭くしてるのではないかね
>>830 その通りでした。
カラムをもう一つ増やせばできないこともないことに気づきました。
まあそのカラムにソートに必要な値を入れといて、
後でそいつをキーにソートするって方法ですけど。
でもそうするとこのキーの値もデータ更新時に毎回更新することになるから、
ちょっとなーって思ってたところです。
まあ400回ループするよりマシかもしれないのでちょっと考えてみます。
でも現状のカラムデータだけではソートは無理です。
ありがとうございました。
出来ないやつって物のせいにするよね
>>831 本気で取り出し順を工夫するときは、別に取り出し順テーブルを持たなくちゃ。
>>832 あのな
自分の力量がないことなんかわかってんだよ
ただの捨て台詞だ
黙ってろボケ
>>833 なるほど。
それいいですね
参考になりました
ありがとうございます。
ある整数型のカラムnumがあって、 その内容が、100以下の素数であるレコードだけ抜き出すために SQLを簡潔に書く方法はありますでしょうか where num=2 or num=3 or num=5 (略) num=89 or num=97 と書いてもいいんですが、 たとえば where num={2,3,5,7,11,(略),83,89,97} のようなまとめた書き方があったら教えてください
in
select id, name, email from users; というSQLがあって、idとemailはユニークだけど、nameは重複可能であるとします。 このとき、nameが重複したときは最初(または最後)に現れたレコードだけをselectすることはできますか。 DBはPostgreSQL 9です。 よろしくお願いします。
環境ないからSQL書かんけど nameでgroup byしてmin(id)とって、それと突き合わせてemail取るとかでいけそうな
>>839-841 ありがとうございます。
distinct onがいちばん簡単そうなので、これでできるかをまず検討し、
できなければ
>>4 の方法でいこうと思います。
C# SQLite 特定の列にNallがあるかどうかの判定をして、あるかないかによって0または1を返したいのですが へたれな頭で考え、ネットからコピーして、下記のように力業?で一応出来ております もっと簡単にできるものでしょうか? // 変数宣言 const string DATABASE_NAME = @"c:\test.db"; string gDataBaseFilePath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), DATABASE_NAME); string gDataSource = "Data Source=" + Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), DATABASE_NAME) + @";password=""testpass"""; int hantei = 0; // 処理 private void HanteiShori() { string sql; SQLiteCommand command; using (SQLiteConnection conn = new SQLiteConnection(gDataSource)) { try { conn.Open(); int allData = 0; int noNall = 0; // レコード数 sql = "SELECT COUNT(*) FROM testTable"; command = new SQLiteCommand(sql, conn); SQLiteDataReader reader = command.ExecuteReader(); while (reader.Read()) { string tmp = reader[0].ToString(); allData = int.Parse(tmp); } // Nall以外の数 sql = "SELECT COUNT(retuData) FROM testTable WHERE retuData is not NULL"; command = new SQLiteCommand(sql, conn); reader = command.ExecuteReader(); while (reader.Read()) { string tmp = reader[0].ToString(); noNall = int.Parse(tmp); } if (allData > noNall) { hantei = 1; } else { hantei = 0; } } catch { } finally { conn.Close(); } } }
NallってNullのことか? 普通にNullの行数数えるだけだろ select count(*) from testTable where retuData is null でダメなのか?
845 :
843 :2012/07/06(金) 00:59:36.16 ID:???
それでいけました ありがとうございます それにしてもへこむ、、、 結構がんばって検索して頭ひねったつもりでいたのにあっさりと答えて頂いた 自分で出来たときなんか「オレって天才じゃねw」とか思っていたりして しかも長文が恥ずかしい さらにNallって 精進いたします
アフリカではよくあること
格好つけて「なる」と発音してきたのはよく分かった。
俺もナルって言ってるわ。 ドイツ語だとヌルらしいな。 ゼロもヌルだそうなので、ジェームス・ボンドはドイツ語だと「ヌルヌルズィーベン」だそうな。
そしてポッカの「レモン100」は、 ツィトローネ フンダート! になるんですよ。 スレ汚しごめん。
>>835 なんだよ、SQLite スレとのマルチかよ。
851 :
NAME IS NULL :2012/07/08(日) 13:04:32.99 ID:0KdAjTTB
DB初心者です。質問させてください。 特定多数の人が利用するFacebookの投稿情報を管理するデータベースを作るとした時に、 そのデータのテーブルの作り方は、 1案. UserIDカラムのある一つのテーブルに全部入れてしまうのか 2案. ユーザー毎にテーブルを作って管理するのか では、一般的にはどちらのほうが良いとされるのでしょうか。 2案では、同じカラムのテーブルが作られるから、1案が妥当になるのでしょうか。 しかし一つのテーブルに特定多数の人のデータが入っているのはいかがなものかという気がしてます。 一ユーザーが保存する投稿データは10件くらいにする予定です。 よろしく御願いたします。
普通に案1のほうだろ。
ってスレチだな。設計スレに行け。
ユーザごとにテーブルっていう発想が素晴らしい 将来大物になるかも
DB初心者がいきなりでかい物を作ろうとするときのよくある勘違い発想じゃん
856 :
851 :2012/07/08(日) 13:55:23.74 ID:0KdAjTTB
普通は1案ですか。 スレチで且つお恥ずかしい質問でどうも申し訳ございませんでした。 ありがとうございました。
2案でやってみりゃすぐ破綻するからやってみ。
>>856 結構意味深い質問なのではないかと思う。
オブジェクト指向で育った人なら2案を考えても不思議ではない。
2案の弱点は最終的には FROM テーブル名 のテーブル名のところに
変数を持って来なくてはならなくなる。それはSQLの設計思想から外れる。
860 :
851 :2012/07/08(日) 14:52:18.70 ID:0KdAjTTB
>>857 ユーザーが増えすぎると、一々ユーザー毎のテーブルを開くのに破綻するということでしょうか。
普通はトランザクション使って大量データを更新するんですね。
>>858 はい
>>859 すごいですね。仰せのとおり会社業務では、オブジェクト指向のソフト開発がほとんどです。
オブジェクト指向とは関係ないですが、よく配列データに操作するのにハッシュ的感覚で添字使って高速アクセスしたりするので、
そのような考え方をしてたと思います。
つまりは何回もテーブルは開いたり閉じたりするなということでしょうか。
因みにSQLiteです。
>>859 > オブジェクト指向で育った人なら2案を考えても不思議ではない。
え?w
あるユーザーの投稿一覧を取得しようとしたとき どのテーブルを使うかはどうやって調べるんだよ
863 :
851 :2012/07/08(日) 15:12:04.26 ID:0KdAjTTB
>>862 ユーザー毎のテーブルなのだから、テーブル名がユーザーIDです。
そのユーザーIDはどこから引いてくるの? 何らかの検索結果で出たIDをテーブル名にしてさらにSQL発行するのか 一つのテーブルなら一発でひけるのに
>>863 ユーザマスタ(ID,名前)もユーザ毎にテーブルを作らないのか?w
866 :
851 :2012/07/08(日) 15:24:32.16 ID:0KdAjTTB
>>864-865 一つのテーブルでいいことはもうわかりましたのでそうします。
ありがとうございました。
スレ違いだってのがわからないの? 馬鹿なの? 死ぬの?
うまい回答が出来なかった時の免罪符ってか
生まれて初めてプログラミング(PHP+MySQL)やったとき、 主キーもインデックスも知らなかったから、動作を軽くするためにやったわw>キーごとにテーブル作成
生まれて初めてのプログラミングでデータベースまで使ったのか、 最近の子はすげーな。
このスレの凄いところは 普段は人の気配がほとんどないと思わせておきながら何かあると急に湧き出してくるところ
主キーって今まで設定してなかったんだけどあれなに?
ぬしキーを知らぬとは、、、
Facebookの管理にそんな必要があるかは疑問だが、個人ごとにテーブルで 管理することの面白さは、それぞれの個人を別の属性の集合、全積、関係として 管理できる点にある。設計という観点からすれば、それなりに筋が通っている。 ただ、RDBそれからRDBに起源を持つ、SQLとは折り合わない部分が多々ある のでは、ということだ。
ぬしって読むのかw しゅきーかと思ってた
>>872 そういう話をテーマにしたスレが確かあったはず。
>>876 恐怖なんとやら、っていうスレなら随分前に1000まで行って終わった。
878 :
874 :2012/07/08(日) 17:50:53.36 ID:???
ごめん直積だった。最近こんな言葉使ったことなかったもんで・・すみません。
>>874 そんな設計で筋が通っているなんて・・・恐ろしくてとても言えないわw
入庫、出庫、締め用のテーブルがあるとし、それぞれ、HEADER、DETAILがあり HEADERには、入出庫、締め番号、日付、ACTIVE(該当月Y/N)など DETAILには、アイテムと数量が入っているとします そこでDAILY MOVEMENTを作成したいのですが、 1~31のように固定ではなく、トランザクションがあった日のみ、つまり SELECT TRANS_DATE FROM (SELECT TRANS_DATE FROM INCOMING WHERE ACTIVE='Y' UNION ALL SELECT TRANS_DATE FROM OUTGOING WHERE ACTIVE='Y') T_DATE group by TRANS_DATE ORDER BY 1 でTRANS_DATE抽出しておきます 結果をREPORT WRITEとかWEBを用いずに TRANS_DATEが横方向に1行目に表され、 2行目1カラムは、アイテム、2カラム目はOPENING数量で、 3カラム以降はIN又はOUTの数量を表記したいのですが JUL/8はトランザクションがありませんので表記されていません 最後のカラムは、その月の現在までのSUMMARY JUL/7 JUL/9 JUL IN OUT IN OUT IN OUT CLOSE 3 5 3 3 8 15 みなさんなら、どうSQLを書きますか、教えてください
Stored Procedureを用いてループさせるとした場合ならどうでしょうか 特にどのSQLかは、こだわりませんが、擬似SQLコードでは、どうでしょうか? JUL JUL7 JUL9 JUL OPEN IN OUT IN OUT IN OUT CLOSE アイテム 15 3 5 3 3 8 10
>>881 まともに意見が欲しいなら、もうちょっと他人に解るように説明した方が良いんじゃね
俺様用語が多すぎるわ
SQLに「表記」はないぞ
なぜそれをカラム可変でやる必要があるのか理解できん
素直に日付ごとに行を持てば(出力すれば)良いんじゃないのか
トランザクションが毎日あるなら別ですが、1週間に2,3回とかですと、 ブランクばかりになってしまいます、ですので可変で表記する必要があります もちろんレコードが存在する日付のみを、カスケイドすれば可変になりますが それでは、知恵がないかと思いまして、SQLに経験豊かな方々は、 どのようなコーディングをされるのかを、拝見したく思いまして
>>885 >>884 は、カラム数を可変にする必要性があるのかっていってるんだが?
トランザクションが二日あったら、2行で出力すれば良いんじゃないのか?
それを表示するときにホストアプリで縦横変換すれば良いだけで
データの表示形式を決めるのはSQLの範疇ではないって言ってるんだが
>レコードが存在する日付のみを、カスケイドすれば可変
意味がわからん
日本語でおk
そもそも、これは7月の入出庫だけが入っているテーブルなのかな。 7月だけActiveにしてあるなんて考え難いし。
Activeは、その月を取り出すためためだけの目的でして、 倉庫では、お客様の都合で2重帳簿を作ることがしばしばあります つまりトランザクションDATEの年と月だけでデータ抽出すると 要望に答えれないからです。在庫があるのに、落としてある、 在庫がないのに、あるように見せるなど、各お客の要望に従って 幾つかのACTIVEのようなカラムを儲けています
後から後からどんどん条件が出てくる w
条件というか蛇足だな
本質は
>>5 のカラム数をデータに依存して決定したいという話なのに
自分で調べる奴・・・問題の本質を理解する力がある 2chで聞いて済ませる奴・・・抽象化する力がないので質問内容もわけわかめ
SQLじゃなくてRPGでも使うべきなんだろうな、ああいう人は。
SQLの代わりにグレネードランチャー使うって凄いな
oracle使っているのですが、 カンマ区切りの文字列を、カンマで分割した複数行としてSELECTできないでしょうか? SELECT * FROM (select "1,2,3,4" from dual) 〜〜〜〜〜 とかで複数行として、カンマ分割した結果がほしいです!
無理やりやるならテキストデータレベルでカンマを「 from dual union select 」で置換して select * from (select '1' from dual union select '2' from dual union select '3' from dual union 〜) みたいにする
898 :
895 :2012/07/10(火) 23:33:45.63 ID:???
ご教示ありがとうございます! テキストベースにしたりファンクションにしたりしないとやはり厳しいんですね・・・。 ファンクション形式でやってみます!
まず格納時にちゃんと複数行で格納するべき それが無理なら、ホストアプリで分解する SQLやストアドで何とかするのはとても勧められない
テーブル名:PRODUCT CODE, PRODUCT_NAME, M_Type 001,パソコン,01 002,パソコン NEC,01 003,パソコン FUJITSU,01 004,パソコン,01 005,パソコン,02 006,プリンター,03 ・・・ とあるとき @ PRODUCT_NAMEの重複するデータを抽出するにはどうしたらいいでしょうか? 001,パソコン,01 004,パソコン,01 005,パソコン,02 が出て欲しい A PRODUCT_NAMEかつM_Typeも一緒のデータを抽出するにはどうしたらいいでしょうか? 001,パソコン,01 004,パソコン,01 が出て欲しい お願いします。
GROUP BYしてHAVINGかな
DBMS:SQLite3.7.12.1(System.Data.SQLite1.0.81.0) [テーブルデータ] CREATE TABLE tblA( id INTEGER, status001 INTEGER, status002 INTEGER, status003 INTEGER, status004 INTEGER, . . . status300 INTEGER ); id |status001|status002|.... . |status300| ----+--------+--------+ +--------| 1| 0 | 0 | | 0 | 2| 1 | 0 | | 0 | 3| 0 | 0 | | 1 | 4| 0 | 1 | | 1 | 5| 0 | 0 | | 0 | 6| 1 | 1 | | 0 | 7| 0 | 1 | | 0 | 8| 1 | 1 | | 1 | 9| 1 | 1 | | 0 | 想定レコード数 50,000〜2000,000 [欲しい結果] ------------------------------------------- status001 | 4 //status001=1であるレコード数 status002 | 5 //status002=1であるレコード数 . . . status300 | 3 //status300=1であるレコード数 正規化に問題があるように思えますが これらを一度のSQLで取得出来ないでしょうか。 この結果を最も速く取得する方法を模索しています(__)
UNIONを300書けばできる
904 :
902 :2012/07/11(水) 13:27:22.01 ID:???
>>903 一例ありがとうございます。既にそちらの方法は作成済みです。
>>901 すみません知識不足のためよくわからないです。
サブクエリの部分がよくわからないです。
ggrks
>>900 select * from product group by product_name having count(*) > 1;
かな。試してないけど。
>>900 @
select *
from PRODUCT T1
where exists (
select *
from PRODUCT T2
where T1.CODE <> T2.CODE
and T1.PRODUCT_NAME = T2.PRODUCT_NAME
)
;
A
select *
from PRODUCT T1
where exists (
select *
from PRODUCT T2
where T1.CODE <> T2.CODE
and T1.PRODUCT_NAME = T2.PRODUCT_NAME
and T1.M_Type = T2.M_Type
)
;
>>902 >>903 に一票
それか結果を
status001|status002|.... .|status300|
--------+--------+ +--------|
4| 5| | 3|
で得てからアプリ側で縦横入れ替えるか
テーブル作りなおすべき
【質問テンプレ】 ・SQLite3 ・テーブル id,unixtime 100001,1341404056 100001,1341997094 100001,1341987930 100002,1341997860 100002,1341989037 ・欲しい結果 100001,1341997094 100002,1341997860 ・説明 上記テーブルでid毎にunixtimeが一番大きいデータを1つだけ取り出すには どのようなクエリでできるでしょうか。1回では無理でしょうか。
select id,max(unixtime) from hoge group by id order by id;
913 :
911 :2012/07/12(木) 11:53:58.76 ID:???
すみません、情報不足でした。テーブルにはテキスト情報もあり、
id,unixtime,value
"1" "1341404056" "内容1"
"1" "1341997094" "内容2"
"1" "1341987930" "内容3"
"2" "1341997860" "内容1"
"2" "1341989037" "内容2"
このような場合に
>>912 さんに教えていただいた
select id,max(unixtime),value from t_test group by id order by id
とすると、
"1" "1341997094" "内容3"
"2" "1341997860" "内容2"
と内容がずれてしまうのですが、
こういった場合では、
"1" "1341997094" "内容2"
"2" "1341997860" "内容1"
と出すにはどうしたらよいでしょうか。
>>913 それだと副問い合わせになるな
(id,unixtime) がユニークだとして
select t.id,t.unixtime,t.value from t_test t,
(select id,max(unixtime) as unixtime from t_test group by id) tmp
where t.id=tmp.id and t.unixtime=tmp.unixtime
order by t.id;
915 :
911 :2012/07/12(木) 12:25:38.43 ID:???
>>914 神様ありがとうございます!出来ました!
916 :
902 :2012/07/12(木) 13:38:28.50 ID:???
ご意見ありがとうございます!
>>909 検討してみます。
>>910 status群を子テーブルにするのが正しい姿のような気がします。
代わりにエクセルとかでささっと編集するのが面倒になるけどね
918 :
NAME IS NULL :2012/07/17(火) 22:22:45.76 ID:Di4GcY9V
・DBMS名とバージョン MySQL5 ・テーブルデータ name (verchar) abc040 abc100 abc90 abc20 abc1000 ・欲しい結果 nameはユニーク abcは固定、そのあとに数値文字列 ソートして、数値文字列の大きい順に抽出したい abc1000 abc100 abc90 abc040 abc20 ・説明
4文字目以降をゼロ詰めしてソートすればいいな。
4文字目以降の文字列を作る 左側を0でトリムする その値で降順ソートする
ご意見ありがとうございます! ちょっと難しそうですね。
ABCが固定であれば、 order by カラムdesc; じゃ駄目なの?
4ケタ目以降で、ゼロ埋めじゃなくて、数字変換する方が良いと思うんだが つかまあテーブル定義やり直すべきだろう カラムは最小単位で定義するのが鉄則
>>922 それだと
abc90
abc20
abc1000
abc100
abc040
こうなるよ
>>918 SELECT * FROM table ORDER BY CAST(TRIM(LEADING 'abc' FROM name) AS SIGNED INTEGER);
・バージョン MySQL5.5 ・テーブルデータ time (TIME), num1 (INT), num2 (INT) 00:00:00, 1, 0 00:00:10, 2, 0 00:00:20, 3, 2 00:00:30, 4, 3 00:00:40, 5, 3 ・欲しい結果 00:00:20, 3, 2 00:00:30, 4, 3 00:00:40, 5, 3 ・説明 time(時刻)が新しい(最近の)方から3行ぬきだし、 timeが昇順になるように並べます。 SELECT文でうまいことできないでしょうか。 よろしくお願いします。
>>927 ↓俺が使ってるもの(銘柄コード指定で最新データ10日分のを抜き出し
日付の昇順で表示するもの
select * from
( select vdate,sp,hp,lp,cp ,vol
from daily_sp_tbl where sc=5401 order by vdate desc limit 10 ) t
order by vdate;
そちらの名称に合わせて書き換えてみたら
ゴキ光線のお小言が始まるでぇ〜( ´Д`)y━・~~
・DBMS名とバージョン SQLite3 ・テーブルデータ tbl1 tid(auto), name(text) tbl2 tid(int), sid(int) tbl3 sid(auto), tag(text),type(int) ざっとこんな感じでnameに対して複数のタグを持っている といった感じのテーブルに対して、データを入れたいと思っています。 で、バックアップがCSVで「name,tag...」という形式で大量にあるのですが、 タグテーブルに無ければ追加、名前テーブルに追記、連結データを追加、 と手数が思ってた以上に多いので、 挿入の手数をもう少し減らせる手段とかありませんか?
何言ってんのか分かんない
SQLの質問がありまして、書きます。 Aテーブル A B C 1 11 2 22 3 33 Bテーブル A B C 4 44 1 5 55 2 6 66 欲しい結果 A B 1 44 2 55 3 33 6 66 BテーブルのCがAテーブルのAと一致したらBテーブル参照したいですが、A項目のみ値をAテーブルの値にしたいです。 何かアドバイスお願いします。。。。。 調べても、よくわからなかったので。。。 お願いします。。。
>>932 欲しい結果の(3,33)と(6,66)を考えなければ
select A.A, B.B from A,B where A.A=B.C;
で簡単なんだが、下の二行はどういう条件で抽出されるべきなの?
>>933 そうなんですね。。。
BテーブルのCに一致しないものを表示させたいです。。。。。。。
AテーブルのAとBテーブルのBはかぶらないのか? AとBをUNIONして、BをOUTER JOINしてCASEでNULL判定かな
こういうことじゃないの? select case when A.A is null B.A else A.A end as A, case when B.B is null A.B else B.B end as B, from A full outer join B on A.A = B.C
大変ありがとうございました。 みなさんのおかげで、無事にできました。
>>936 > case when A.A is null B.A else A.A end as A,
なんで、coalesce(A.A, B.A) 使わないの?
939 :
NAME IS NULL :2012/07/24(火) 06:22:52.28 ID:Gfkf5V7p
初心者用が見つからなかったのでこちらで質問します テーブル tbl |-----INDEX----|--DATA--| yyyy mm dd no item 2012 01 05 005 itemAA 2012 01 05 007 itemAC 2012 01 05 009 itemBB 2012 01 10 001 itemBA 2012 01 10 007 itemFG 2012 01 12 006 itemQW : : 結果 2012 01 10 001 itemBA 2012 01 10 007 itemFG この場合 select * from tbl where yyyy='2012' and mm='01' and dd='10' このようにnoを指定しないと検索時にインデックスは有効とならないのでしょうか? インデックスはその項目全てをSQLに明記しないと有効とはならないのでしょうか? 初歩的すぎる質問だと思いますがお願いします
sage忘れました 申し訳ないです
インデックスってこのスレで取り扱ってたっけ
オプティマイザ次第。
>>938 DBMS名書いてないから
>>939 普通のインデックス構造をもつ普通のDBMSなら普通は有効となる
ただしどんな状況でも必ずそうだとは言い切れないので
実機でアクセスパスを確かめること
(確かめる方法はDBMS固有なのでスレ違い)
オプティマイザ以前に、そのDBMSでその手の検索にインデックスが有効かどうかが問題 今時のDBMSなら効くと思うけど、まずはDBMSのマニュアルで確認するべきだな そのうえで実際の読み込みにインデックスが使われるかどうかはオプティマイザ次第 つか初心者ならまずちゃんとマニュアル読めよと
・DBMS名とバージョン MySQL 5.1 ・テーブルデータ CSVファイル "犬","シベリアンハスキー" "猫","マンチカン" "熊猫","レッサーパンダ" ・欲しい結果 インポートして、次のようにしたい、要するに連番をつけたい ID 動物 種類 1 犬 シベリアンハスキー 2 猫 マンチカン 3 熊猫 レッサーパンダ ・説明 インポートするときにdefaultをつければいいのですが、SQL文で書けないでしょうか。
MySQLならAUTO_INCREMENTあるだろ
すると次はレコード消した時にIDが虫食い状態になるのでなんとかしたい…とかの質問が来るんだな w
>>946 そうなんですが、csvのデータをいじらずにSQLのload data infile文で
なんとかならないかと思ったのですが
誰がいじれなんつった?両方使えよ
そんなんSQL92の範囲にあったっけ?
951 :
939 :2012/07/24(火) 22:28:35.43 ID:???
>>941-944 MySQL 5.5 と ACCESS2003です
オプティマイザ及びアクセスパスについて調べてみることにします
レスありがとうです (_ _)
>>943 > DBMS名書いてないから
そんなこと言うなら、case もダメだろ。
Access かも知れないんだし。
前提書いてないなら、SQL-92 あたりを想定してもいいと思うんだが。
MySQL5.1 セール価格表(P) 商品CD 適用日 単価 aaa 2012-08-01 2500 aaa 2012-08-20 3000 bbb 2012-08-01 10000 bbb 2012-08-15 8500 予約表(Y) 商品CD 購入日 数量 aaa 2012-08-01 2 aaa 2012-08-05 3 aaa 2012-08-25 1 bbb 2012-08-13 4 bbb 2012-08-19 5 ほしい表 aaa 2012-08-01 2 2500 aaa 2012-08-05 3 2500 aaa 2012-08-25 1 3000 bbb 2012-08-13 4 10000 bbb 2012-08-19 5 8500 購入日時点で適用日以降の単価が反映された表を得るにはどうしたらいいでしょうか
>>953 SELECT
商品CD,
購入日,
数量,
(SELECT 価格 FROM セール価格表 WHERE セール価格表.商品CD = 予約表.商品CD AND セール価格表.適用日 < 予約表.購入日 ORDER BY 適用日 ASC LIMIT 1) AS 価格,
FROM
予約表
みたいのでいけない?
思いつきで確認してない上に普段こうならんように組んじゃうから間違っているかもだけど。
あと、もっと効率のいいのがると思うけど。
予約表に単価を持たせる 冗長だけど我慢する
>>954 下記のように少し直しましたら、動きました・・☆。
ありがとうございました。
SELECT
商品CD,
購入日,
数量,
(SELECT 価格 FROM セール価格表 WHERE セール価格表.商品CD = 予約表.商品CD AND セール価格表.適用日 <= 予約表.購入日 ORDER BY 適用日 DESC LIMIT 1) AS 価格,
FROM
予約表
>>955 セール価格表には単価だけでなく、期間立てで持っているフィールドがあるんです。
>>956 決して効率よくないはず。
可能であれば、ホスト言語側でマージして
DB側に負担かけないようにしたほうが後日幸せになれるはず。
MySQL 5.1です。 テーブル1 15:30:20 カツ丼 15:35:40 天丼 15:50:15 他人丼 テーブル2 15:30:30 400円 15:35:45 550円 15:51:00 480円 というテーブルがあって、テーブル1と2の時刻が近いものをマッチさせて 15:30:20 カツ丼 400円 15:35:40 天丼 550円 15:50:15 他人丼 480円 のような結果を出したいのですが、どのようにすればいいでしょうか。 よろしくお願いします。
夏休みだからかな。
なんかの設問ぽいのが来ているな。
>>959 UNIX_TIMESTAMP()とABS()使って最も差分が最小値のを取り出せばいいんじゃないかな。
これ以上は、
>>4 見て質問書き直して。
UNIXTIME_TIME
>>959 ごめん。
TIME_TO_SEC()だわ。
963 :
NAME IS NULL :2012/07/27(金) 10:17:32.88 ID:KIhgtPiw
・DBMS名とバージョン SQLite3 ・テーブルデータ テーブル名 directory folder val /contact/ index /test/ connect /example/ foo /hoge/ bar /fuga/ com ・欲しい結果 問い合わせ内容とfolderの内容が部分一致していればvalを返す /contact/ にアクセスがあった場合はindexを返す /contact/foo の場合もindexを返す ・説明 $folder_hensuu = "%/contact/%"; select * from directory WHERE folder LIKE $folder_hensuu とした場合はヒットするが $folder_hensuu = "%/contact/hogehoge%"; の場合はヒットしない。 この場合はどうすれば一致判定が出来るようになりますか?
SQLite3はよくわからないんだけど、なんか逆にすべきな気がする。 つまり、部分一致する際にそのWHEREの基準となるのがfolderカラムのほうでしょ。 だから、カラムのほうに文字列結合でみたいにすればいいんではないでしょか。 MySQLしか出来ないのでこれ以上は申し訳ない…。 MySQLで書くとこんな感じ。 SELECT val FROM test WHERE '/connect/hogehoge' LIKE CONCAT('%',folder,'%');
休憩時間が設定されているときに、指定日時より'HH:MM'後の時刻を求めたいです。 ・データベース:PostgreSQL 8.4 ・テーブル: 休憩時間 開始時刻 終了時刻 08:00 08:30 19:00 19:30 22:00 22:30 使うかどうかわかりませんが、次のマスタもあります。 カレンダー 日付 ... 2012-07-26 2012-07-27 2012-07-28 ... ・説明 指定した日時から休憩時間を除いた'HH:MM'後を計算します。 計算結果が休憩時間内(開始終了時刻を含む)の場合は、休憩時間終了時刻を結果とします。 ・欲しい結果 '2012-07-27 09:00'の'09:00'後 => '2012-07-27 18:00'(休憩時間がないのでそのまま足す) '2012-07-27 09:00'の'10:00'後 => '2012-07-27 19:30'(10時間後は19:00の休憩と重なるので、19:30が答え) '2012-07-27 09:00'の'11:00'後 => '2012-07-27 20:30' '2012-07-27 09:00'の'13:00'後 => '2012-07-27 23:00'(19:00〜と22:00〜の二回の休憩を挟む)
>>965 確かに難問だ。
何を聞かれているのか説明を見るとすさまじく混乱する。
つまり、
1.出勤時刻と実労時間数を入力されたら
2.休憩時間を実労時間からはずした上で
3.勤務終了予定時刻を出力しろ。
4.ただし、終了予定時刻が休憩時間内である場合は、休憩終了時刻を出力する
ってこと?
それだけだと、欲しい結果のその日付の存在理由がなんなのかわからなくなるけど。
入力されるデータの例を出して。
ただし、ちゃんとフォーマットした形でね。
968 :
967 :2012/07/27(金) 16:31:53.50 ID:???
ごめん、1〜4を踏まえた上で例を考え直してってことでお願いします。 おそらく最後の例のままでいいんだろうけど ちょと日本語読み直してたら混乱してきてた。
>>967 私は出題者ではないのですが、
次の休憩開始時刻 - 一つ前の休憩終了時刻 = 就業時間 とすると
後・時間からこの就業時間を切り取って行く問題ですね。
さらに最後の休憩時間の後の就業時間をどう表現するかなど、
考えどころの多い問題のようです。
970 :
965 :2012/07/27(金) 18:19:05.67 ID:???
すみません。ちょっと欲張りすぎました。問題を一段階簡略化します。 休憩時間がマスタに設定されているとき、「与えられた日時」から実働9時間後の日時を求める。 (※)実働とは、休憩時間を除いた勤務時間。 この結果は、残業届けを出すときの残業開始日時を計算するときに使います。 (その後、月締め処理で残業届けに基づいて残業時間合計を計算します。) 「与えられた日時」は、未来の日付の残業届けを出すときは定時開始時刻(例えば09:00)になり、 過去の日付の残業届を出すときは、遅刻をしていればその日時になります。 例えば、'2012-07-27 09:00'と'09:00'という即値を使ったクエリで、 '2012-07-27 18:00'が計算 できるでしょうかというのが質問です。 勤務している時間を'+'、休憩時間を'_'で表すと、一日は、 ++++++___++++++__+++_++_++++ みたいに表せて、任意の開始日時(下の*)から9時間後を求めたいということです。 +*++++___++++++__+++_++_++++ +++*++___++++++__+++_++_++++ うまく説明できたでしょうか?
971 :
965 :2012/07/27(金) 18:28:24.50 ID:???
>>969 そう、その通りです。
Excelでイメージするなら、休憩時間と勤務時間の累計をして、目視で判断すればすぐに
わかりそうな問題なんですが、クエリでできないものかと…。
最も好ましいのは、一つのクエリで結果を計算できること、
次に好ましいのは、ワークテーブルを使わずにPostgreSQLのFunctionで計算できること。
最悪はワークテーブルに「実休憩時間」を展開して、複数ステップを踏んで計算するか、
Functionを再帰呼び出しして(できるのだろうか)結果を求めるか、クライアントアプリ側で
ゴリゴリやるかになると思います。
いやそれ、SQLでゴリゴリやる内容じゃないと思うぞ。
休憩時間じゃなくて、実働時間をもたせたら 実働時間のサマリが指定時間を超える最大のものとかで求まらんかな
データベース:MySQL 5.1 ストアドファンクションを作成しているのですが、 ストアド内ではGetDate()は使用できないのでしょうか? また、何か代替のものはあるのでしょうか? 初歩的な質問で申し訳ありません。
WHERE句の(+)ってどういう意味なのですか? ぐぐっても出なかったもので(^_^;)
Oracleだと外部結合演算子でググれ 他は知らん
Oracle方言でしょ、それ
979 :
965 :2012/07/30(月) 11:43:54.03 ID:???
やはり簡単にはいかないようですね。
休みの間も考えたのですが、どうもうまくいかないので、結局、ワークテーブルを使って、
Excelでやるような累計をしながら、Functionで実装することにしました。
方針は、
>>973 さんの方法です。
考えて下さった方、ありがとうございました。
980 :
NAME IS NULL :2012/07/31(火) 12:36:18.52 ID:RZdi1fDI
・Microsoft SQL2012を使っています。ちょっと質問なのですが テーブル作成時における検査制約で、とある列の列名の長さ が”6文字以内”という可変長の条件にしたいのですがどのよう に書けばよいのでしょうか? CONSTRAINT CK_stor_id CHECK(stor_id >=6 )) 上記では間違いでしょうか?よろしくお願いします。
なぜ試して見ないの?
間違いだろうね。
列名の長さ?
・SQL Server2008R2Express テーブルデータ ・2012-08-01 11:35:00, りんご, 1 ・2012-08-01 16:22:00, みかん, 2 ・2012-08-02 13:54:00, りんご, 2 ・2012-08-02 14:32:00, りんご, 1 ・2012-08-04 16:22:00, みかん, 3 ・欲しい結果 2012-08-01 2012-08-02 2012-08-04 ・説明 件数に関係なく売り上げがあった日だけのリストが欲しいのですが うまい方法あるでしょうか
distinct と having count(*)>1
ごめん間違えた distinct でいい
データベース:MySQL 5.2 table bbs( uid INT, rid INT, text TEXT ); table users( id INT UNIQUE, name VARCHAR(32) ); 欲しい結果のイメージ uid, rid, uid.name, rid.name .name は users テーブルの name の項目 掲示板で、投稿者ID (uid) と 返信先ID(rid) のそれぞれの名前を users から取得したいです。
bbsテーブルにusersテーブルを2回JOINするだけだろ
>>984-986 dateをformatかけて日付だけ取り出したいんじゃないかな?
Transaction-SQLわからなかったのでレスできなかったけど。
>>987 それぞれのID用にusersテーブルを別名つけて2回JOIN
やってみてダメだったら、作ったSQL文張ってみて
>>988-989 SELECT a.id, a.name, b.id, b.name, bbs.text FROM bbs LEFT JOIN users AS a ON bbs.uid=a.id LEFT JOIN users AS b ON bbs.rid=b.id;
a とか b とかっていう名前はともかく、これでなんとか取得出来ました。
ありがとうございます m(_ _)m
(bbs にあるデータは全て取りたいので INNER ではなく LEFT にしました)
こう言った文が長くなったときに、他の言語の様にブロックで囲むと言った記述は出来ないのでしょうか?
それとも可読性を求める時は改行で分けるのが一般的なのでしょうか?
改行とインデント使うのが一般的かと
よくやる人は
>>990 のSQL使うと
SELECT
a.id,
a.name,
b.id,
b.name,
bbs.text
FROM
bbs
LEFT JOIN
users AS a
ON
bbs.uid=a.id
LEFT JOIN
users AS b
ON
bbs.rid=b.id
;
くらいやる
( ´_ゝ`)フーン
>>991 これは改行しすぎだろ。
select みたいに、フィールド名がずらずら続く奴はべつにして
キーワードと関連するオペランドは基本的に同じ行にしといたほうが読みやすいと思うぞ。
俺ならこんな感じ。
SELECT
a.id,
a.name,
b.id,
b.name,
bbs.text
FROM bbs
LEFT JOIN users AS a ON bbs.uid = a.id
LEFT JOIN users AS b ON bbs.rid = b.id;
なるほど プログラムから使うときは SQL 文を複数に分けて連結してたけど、 改行で分けて書いた方が見た目分かりやすいですね。
>>993 俺もこんな感じで書くな
どうでもいいが俺はアプリのソースに直接SQLを埋め込む実装は好きじゃない。
SQL文は別のファイルにして、アプリからそれを読み出してwhere句の部分とかをアプリから変数で置換するのが好きだな。
アプリもSQLも仕変や改修も管理も楽になる。
と言っても元々NEとかSE出身でアプリやDBは素人のお馬鹿さんなんだがw
>>994 あと、DBMS によってはキーワードなんかの間違い箇所を行で教えてくれるものがあるから、
長大な SQL を書く時はデバッグが楽。
SELECT col1, col2 FROM ( aTab INNER JOIN bTab ON aTab.id = bTab.id ) INNER JOIN cTab ON cTab.id = aTab.id すごく人によって差がありますなぁ…。
1000
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。