このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。
SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。
質問するときはDBMS名を必ず付記してください。
【質問テンプレ】
・DBMS名とバージョン
・テーブルデータ
・欲しい結果
・説明
前スレ:SQL質疑応答スレ 6問目
http://pc11.2ch.net/test/read.cgi/db/1210940477/
よくある質問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 ;
いちょーつ
7 :
NAME IS NULL :2008/10/10(金) 00:27:52 ID:JpXt+XXo
SQL質疑応答スレ 6問目にて時間と分の足し算を質問した者です。 回答くださった皆様ありがとうございます。 参考にして頑張ってみます。
8 :
NAME IS NULL :2008/10/10(金) 00:51:42 ID:1bc3EllS
・DBとバージョン SQLite ・テーブルデータ MainTable key … ------- 002 … 014 … 034 … 105 … SubTable key data time … ----------------- 002 2345 1 … 002 1345 5 … 002 1123 8 … 034 4562 3 … 034 2930 9 … 105 1222 7 … 105 4850 8 … ・欲しい結果 key c1 c2 ----------------- 002 0 2 014 0 0 034 1 1 105 1 2 ・説明 c1はSubTableのdataが1000以上かつtimeが5以上の数。c2はSubTableのtimeが5以上の数。 MainTableを軸にしてSubTableに対応するkeyが無い場合は0を表示したいのですが、 SELECT m.key, coalesce( t1.c, 0 ) as c1, coalesce( t2.c, 0 ) as c2 FROM MainTable m LEFT JOIN ( SELECT m.key, count(*) as c FROM subTable s INNER JOIN MainTable m ON m.key = s.key WHERE s.time >= 5 and s.data >= 1000 GROUP BY m.key ) t1 ON t1.key = m.key LEFT JOIN ( SELECT key, count(*) as c FROM subTable WHERE s.time >= 5 GROUP BY key ) t2 ON t2.key = m.key バインドする時に「s.time >= 5」の部分が2回出てきたり、同じようなサブクエリを 2回使ってたり…。もっとスマートな形があると思うのですが、良い解決策が見つかりません。
9 :
8 :2008/10/10(金) 01:04:08 ID:1bc3EllS
すみません。ちょっと間違えました。 ・MainTableはoverカラムがあります。 誤:key … 正:key over … ・c1の条件は1000以上では無く、MainTable.over以上です。(1000以外の場合もあります) 誤:c1はSubTableのdataが1000以上かつtimeが5以上の数。 正:c1はSubTableのdataがMainTable.over以上かつtimeが5以上の数。 ・なので、何の為にMainTableをJOINしてるかわからないSQL文になっていました。 誤:WHERE s.time >= 5 and s.data >= 1000 正:WHERE s.time >= 5 and s.data >= m.over 以上、よろしくおねがいします。
>>9 SQLiteで動くかどうか未確認。
SELECT key,sum(CASE WHEN data >= over THEN 1 ELSE 0 END) AS c1 ,count(data) AS c2
FROM MainTable
LEFT JOIN
(SELECT * FROM SubTable WHERE time >= 5) AS T1 USING(key)
GROUP BY key;
--補足
c1もc2もtime>=5なので、サブクエリT1で先に抽出。
data >= over の判定はCASEで。
と言う具合に条件判定を別けてるので、実運用時の条件次第では
複雑なCASE文になるかもしれんよ。
11 :
8 :2008/10/10(金) 11:52:55 ID:???
ありがとうございます。 なるほど。sumの中にCASEですか。 そういう書き方ができるとは知りませんでした。 (まだ、SQL初めて2週間なので…) SQLiteで無事に動きました。とても助かりました。
だれか SQLServerとOracleでの 文字列→日付 日付→文字列 をフォーマット付きで指定できる奴の テンプレ作っておいてくれ 俺が帰ってくるまでにw なかったら俺が探して書くw
PCとActiveSync接続中のネット接続ON/OFF切り替えするメニューどこでしたか?
誤爆しました。
15 :
NAME IS NULL :2008/10/12(日) 00:17:55 ID:kBgP9NuQ
200個のレコードを持つテーブル(table)から、ランダムに100個のレコードを削除しようとしています。
select * from table order by random() limit 100;
などとして、ランダムに100レコード、テーブルからレコードを取得して
http://sonic64.com/2002-12-25.html にしたがい、上記実行結果をCSV出力して、
\pset format unaligned -- 出力形式を指定
\pset fieldsep ',' -- フィールドのセパレータにカンマ区切りを指定
\o psql_out.csv -- 出力ファイルを指定
http://winofsql.jp/VA003334/mysql050903155156.htm にしたがい、CSVをtableに入力することで実現しようとしているのですが、
ERROR: invalid input syntax for type date: ""
CONTEXT: COPY test, line 2, column time: ""
とかいわれて、なんかむつかしいです。
tableはCOPYの前にTRUNCATEしています。
方法をどうかおしえてください。
わざわざいったんCSVに出力しないとできないものでしょうか?
>>15 > select * from table order by random() limit 100;
が出来てるなら、identify 可能な column を select して、それで delete where するだけやん。
17 :
NAME IS NULL :2008/10/12(日) 00:29:33 ID:kBgP9NuQ
すみません。sqlの実行結果を、利用して再度sqlにて >dentify 可能な column を select して、それで delete where する 方法をお教えください。具体的なSQLを教えていただけますとうれしいです。
>>17 identify 可能な列が分からないから、なんとも。
delete で where に in とか使ったことないの?
19 :
NAME IS NULL :2008/10/12(日) 00:42:26 ID:kBgP9NuQ
SQLの実行結果からカラム名とかは取得できるので、直に手で打てば、 deleteできるのですが、実行結果からリダイレクト?みたいな形で 人手を介さずSQLのみで、レコードを削除したいのです。 そういうことってできそうですか?すみません。
20 :
15 :2008/10/12(日) 01:00:14 ID:kBgP9NuQ
# select * from table order by random() limit 100; instance_id,instance_name,par_class_id,par_class_name,user_id 1,あ,3,い,4 というような結果が返ってきたときに、 delete * from table where insance_id = 1 みたいなことをしたいのですが、 instance_id=1というところの設定を、上記のSQLの実行結果から自動取得して、 deleteに反映させたいのですが、方法がわからないのです。 どうかよろしくお願いします。
>>20 select * from table where insance_id IN (select insance_id from table order by random() limit 100)
ってしたらどうなるか分かる?
22 :
15 :2008/10/12(日) 09:33:33 ID:kBgP9NuQ
ありがとうございます。INを用いることで、少し前進しました。 ですが、instance_idとuser=idを指定して、サブクエリを投げる方法がわかりません。 現在は以下のように投げているのですが、エラーがでてしまいます ランダムを使っているので、構文を二つに分けることもできず、苦労しています。 どうか、よろしくお願いいたします。 # select * from table where instance_id AND user_id IN (select instance_id , user_id from table order by random() limit 3); ERROR: subquery has too many columns
>>22 いや、だから、identify 可能な列が云々書いたんだけど…
それなら exists とかでやったら?
基本的な SQL 文を勉強した方が良いんじゃないかと。
24 :
15 :2008/10/12(日) 09:47:30 ID:kBgP9NuQ
ありがとうございます。 INでは無理ということでしょうか? SQLの勉強は進めたいと思いますが、この方法の解を何かお教えいただけませんか? よろしくお願いします。
25 :
15 :2008/10/12(日) 09:50:28 ID:kBgP9NuQ
select * from table where exists (select instance_id , user_id from table order by random() limit 3); これでいけますのでしょうか?
26 :
15 :2008/10/12(日) 10:09:17 ID:kBgP9NuQ
やってみたけど、25じゃうまくいきません。
28 :
15 :2008/10/12(日) 10:30:29 ID:kBgP9NuQ
見捨てないで、方法をおしえてください。INを使った方がいいのかな?むつかしい。。
>>28 >> 基本的な SQL 文を勉強した方が良いんじゃないかと。
> SQLの勉強は進めたいと思いますが
> やってみたけど、25じゃうまくいきません。
勉強する気がないかの能力がないのかは知らんが、お前には無理。
30 :
15 :2008/10/12(日) 10:35:10 ID:kBgP9NuQ
そうですか、残念ですが、あきらめます。
SQLServer2005です。 列A+列B>5000のような条件を指定してSELECTしたいのですけれども これって1000万行とかあったら恐ろしく応答遅くなりますか?
34 :
33 :2008/10/12(日) 15:03:22 ID:???
>>32 列A+列Bというインデックスが張ってあればいいけど
そうじゃなきゃフルテーブルスキャンだな。
>>33 SQL構文の一部としてのセミコロンも存在するけどその場合は違う。
SQL Server固有の区切り文字だろう。
(SQL Serverはよく知らんけども。)
T01Prefectureってなに?
データーベースの設計で、primary keyって必須なのか? そういうことにきづいた最初の人は誰?
リレーショナルデータベースを 関係データベース って呼ぶキチガイって本当にいるのか?
>>38 インデクシングをBツリーで実装したデータベースエンジンの場合、Primary Keyは効率上必須(無いと線形探索しかできない)。
誰が言い出したかは知らんが、最初のBツリーの実装時に生まれたんだろ常考
(テーブル内のレコードは一意でなければならない、というレベルでならデータベースの関係モデルを最初に提唱した
Coddがすでに言ってたが、知っての通りPrimary Keyはそれ+αなので明らかにCoddより後)
データベース:SQL2000 NULLに足し算した結果、NULLとならないようにするオプションありますか? 例:NULL+1=1
>>41 NULLというものの意味をもう少し勉強したほうがいい
>>41 NULL は NULL であって 0 じゃないから、そんなオプションはないと思う。
SQL2000 ってのが何か分からないが、SQL Server のことなら
ISNULL って関数を使えばいいんじゃない?
確かに、NULLと0を等価で扱いたいことはあるけどな。
そのためのCOALESCE
テーブル作るときに varchar(100) って指定した場合と varchar って指定しない場合はどう違うんですか。 あとH2使おうとしてるんですけど varchar2はどう違うんですか
47 :
NAME IS NULL :2008/10/19(日) 12:44:50 ID:Mvsa6eQB
>>46 指定しないんなら、default値じゃんえーの?
>>46 質問の件ANSIでどう決まってるかは知らないが、
Microsoft SQL Server 2005 - 9.00.3068.00 (Intel X86) Feb 26 2008 18:15:01 Copyright (c) 1988-2005 Microsoft Corporation Express Edition on Windows NT 5.1 (Build 2600: Service Pack 3)
で実験した。
>varchar
varcharはvarchar(1)と解釈されるようだ。(CREATE TABLE [foo]([test] [varchar])の実行計画と、作ったテーブルへのINSERTで確認)
1文字しか入らない(2文字以上INSERTしようとすると失敗する)ので実用性がほとんどなさげに思える。
>H2, varchar2
テーブルを作ろうとしたら、そんな型はないと怒られた。
49 :
NAME IS NULL :2008/10/19(日) 15:28:53 ID:2YpDp4aW
>>46 【質問テンプレ】
・DBMS名とバージョン
50 :
46 :2008/10/19(日) 16:49:20 ID:???
>>47-49 H2:1.1.101 (2008-10-17)で
作ってみて左のペインで確認したらたらこうなってたよ。
varchar(100) → VARCHAR(100)
varchar → VARCHAR(2147483647)
varchar2(100) → VARCHAR(100)
varchar2 → VARCHAR(2147483647)
指定しないとMAXになるってことかな。
varchar2でもvarcharになるんだね。
最初から試せって話だね。
>45 全くスペルが覚えられない俺に一言
なんというか単語にNull値をどうにかしてやるぜ!感(?)がまるで感じられないから嫌い。 もっと直接的にIsNullとかIfNullとかNVLとかNzとかだったら喜んで使うんだけど
環境mysqlです。 1 2 3 4 5 6 7 8 9 このようなテーブルから4,5,6の行を取得したい場合に SELECT * FROM table WHERE col1 = 4 AND col2 = 5 AND col3 = 6 と書くと思いますが、 行の一致を確かめるにはEXISTSの方が良いと聞きました。 しかし、次のようにするとエラーが出ます。 SELECT * FROM table WHERE EXISTS(1, 2, 3) EXISTSの中はクエリでなければならないので当然といえばそれまでなのですが、 やはりEXISTSは無理なのでしょうか。
結合するよりも相関クエリの方が適している場合があるというだけで、 単純にテーブルから抽出するだけなら前者でよいと思うよ。
分りました。ありがとうございます。
回答がすでに出ているので蛇足だが、仮にcol1の値でテーブル内のレコードを一意に特定できる場合、 SELECT * FROM [table] WHERE col1 = 4 AND col2 = 5 AND col3 = 6 は、EXISTSを使って SELECT * FROM [table] WHERE col1 = 4 AND EXISTS(SELECT 1 FROM [table] WHERE col2 = 5 AND col3 = 6) と書けてなかなか趣き深い。
蛇足に駄レスだが、col1で一意になるなら where col1 = 4 だけでいいよね。
user ------------------------ id, user_name, ..... 1, 石井, ..... 2, 鈴木, ..... 3, 佐伯, ..... 4, 野村, ..... 5, 藤田, ..... item ------------------------ id, user_id, item_name,.... 1, 1, AAAA, .... 2, 5, BBBB, .... 3, 2, CCCC, .... 4, 1, DDDD, .... 5, 3, EEEE, .... type ------------------------ id, name, .... 1, タイプ1, .... 2, タイプ2, .... usertype ------------------------ id, type, user_id 1, 1, 1 2, 1, 2 3, 2, 1 4, 2, 5
上記の様なテーブルがあり user.id = item.user_id user.id = usertype.user_id type.id = usertype.type の様な関係があるのですが user_idが1の人が操作した際は result ------------------------------ item.id, user_id, item_name 2, 5, BBBB user_idが2の人が操作した際は result ------------------------------ item.id, user_id, item_name 2, 5, BBBB 5, 3, EEEE の様な感じで、usertypeテーブルにて自身が所属するtypeと 同じtypeを持っているユーザー以外(どのtypeにも属さないユーザーも含みます)が所持しているitemを表示させたいのです。
SELECT item.id, user_id, item_name FROM item WHERE item.user_id = usertype.user_id AND item.user_id != <自身のID> AND usertype.type NOT IN(SELECT type FROM usertype WHERE user_id = <自身のID>); の様な形では、自身が所属していないタイプにも属していた場合は弾かれずに表示されてしまい 困っております。 どのような形で記述すれば、希望の形で取得出来ますでしょうか。。。
書き忘れました。。。mysql 5.0.22です。 ご指南のほど、宜しくお願い致します。
>>59-62 user_id 1の人はtype 1と2に属するから
それらのtypeに属さない、user_id 3,4の人が
所有するitemを表示する。
user_id 2の人はtype 1に属するから
そのtypeに属さない、user_id 3,4,5の人が
所有するitemを表示する。
で、いいのか?
だとすると
>>60 の前者は「5, 3, EEEE」の間違いだと思うが。
それと自分がどのtypeにも属さない場合に欲しい結果は?
自分以外が所有するitem全部?
解けそうでとけねー。つーか頭が溶けてきたw。 ちょっと要点を整理。 早い話usertypeテーブルだけ注目すりゃいい。 user_id=1の場合、id=1とid=3の行がuser_id=1なので除外。id=3の行はid=1のtypeと同じなので除外。よってid=4の行だけが残る。 user_id=2の場合、id=2が除外。id=2の行とtypeが同じid=1も除外。よってid=3と4が残る。 この残ったusertypeとitemテーブルをuser_idで結合すれば桶。
俺も
>>60 の前者は5,3,EEEEの間違いだと思う。
どのtypeにも属さないユーザーも含みます
って書いてるからもうちょっと脳を溶かしてがんばってw
自分がどれにも属していなければ、いずれかに属しているユーザが所有するitem全部じゃないかな。 どれにも属していない他のユーザのitemは出さない。
67 :
64 :2008/10/21(火) 19:48:48 ID:???
user_idで結合すればBBBBであってね? あれ?
68 :
59 :2008/10/21(火) 19:52:28 ID:???
すいません、仰るとおり、60の前者は5,3,EEEEの間違いですorz
69 :
64 :2008/10/21(火) 20:07:08 ID:???
あぅ、64で書いた解釈じたい間違ってら。 お騒がせスマソ...orz
これでいいんかな? select id, user_id, item_name from item A where not exists (select * from usertype B inner join usertype C on B.type = C.type where B.user_id = <自身のID> and A.user_id = C.user_id) and A.user_id <> <自身のID> ;
100レコードあるテーブルから10件SELECTするのと 100000レコードあるテーブルから10件SELECTするのとではパフォーマンスに違いはありますか?
インデックスがちゃんと使われていれば気にするほどじゃないと思う
73 :
59 :2008/10/22(水) 10:23:18 ID:???
>>70 有難う御座います!
これで漸く作業を進める事が出来そうです。
NOT EXISTSの存在、今の今まで浮かびませんでした
一緒に考えて下さった63-67の皆様も、本当に有難うございました。
>>72 ありがとうございます。
インデックスが適切に張られていたと仮定しての話でしたが、
素人目に考えるとファイルオープンや二分木探索のときに総レコード数が多い方が
明らかにオーバヘッドが高いように思うのですが、そんなに変わらないもんなんでしょうか。
2分探索で最悪のケースで17回比較で、それが10回分なら最良のケースと比較しても170回の差でしかないし これは一瞬だ
>>74 > ファイルオープン
インデックスは多くの場合において随分小さいです。
> 二分木探索
この言葉が出てくるならレコードが100の場合におおむね6回の比較、
100000件でおおむね17回の比較でよいことも分かりますよね。
パフォーマンスの違いはもちろんあるよ。
EXISTSの使いかたを見ても分かりません。 どこかに詳しく解説書いてあるページありますか?
>>75-76 ありがとうございます。
レコード数は必要がない限りそれほど気にせずにやってみます
クエリの処理がボトルネックになっているということが判明するまでよけいなことしない方がいいよ。
>>79 9−7で
>--7.暗黙の型変換を行なっている
>char型で定義されたcol_1に対する条件を書く場合の例:
>
>× SELECT * FROM SomeTable WHERE col_1 = 10;
>○ SELECT * FROM SomeTable WHERE col_1 = '10';
>○ SELECT * FROM SomeTable WHERE col_1 = CAST(10, AS CHAR(2));
という話があるんだけど、アプリのAPI(具体的に言うとPDO)からプリペアドステートメント使ってクエリ投げる時に
明示的に型を指定しないとインデックスが使用されない場合もあるの?
例えばuser_idがintで定義されている場合、
$userId = $_POST['userId']; //100
$stmt = $db->prepare('SELECT * FROM users WHERE user_id = :user_id');
$stmt->bindParam(':user_id', $userId); //ここで$userIdはstring
$stmt->execute();
みたいな。
APIの実装次第と言われたらそれまでだろうけど。
>>71 あんまり意味ない。
パフォーマンスを気にするのは10万行以上の単位。
いやいや、
>>71 は装置制御とかでmsオーダーのレスポンスの話をしているのかもしれないぞw
85 :
57 :2008/10/24(金) 00:23:37 ID:???
>>58 それはcol1=4の行の内容が(4,5,6)であると最初から分かってる場合だけなりよ。
>>71 WHERE句の内容と書き方にもよるが、
ある列にインデックスが張ってあってその列による選択性が高い(WHERE句の最初の方に出てくる等)場合、
レコード件数に対して検索時間はO(log n)なりよ。
理想条件だと、100件からの検索と、10000件からの検索の検索時間非は大体2倍(=log 1000/log 100)がセオリー。
実測値はケースバイケースなので責任持たない。
>>85 > col1の値でテーブル内のレコードを一意に特定できる
いや、こういう仮の前提を作ったのは
>>57 でしょ?
その上でcol2 col3を見るだなんてなんと非効率的な。
87は、54の言う SELECT * FROM table WHERE col1 = 4 AND col2 = 5 AND col3 = 6 と、87自身が言う SELECT * FROM table WHERE col1 = 4 が同値かどうか冷静になって考え直したほうが良い
89 :
87 :2008/10/24(金) 03:27:08 ID:???
まことにすまなかった。 せっぷくいたす。
90 :
NAME IS NULL :2008/10/24(金) 07:27:33 ID:7hbw5N2D
オー ジャパニーズ ハラキリー
91 :
57 :2008/10/25(土) 06:35:40 ID:ADsJ0YJ7
>>89 (= >58?)
いや大変スマン、冷静になって考え直すべきだったのは漏れの方だった。
>57を落ち着いて読み直すと表現がまずい上にEXISTSを使ったクエリが間違ってた(汗
訂正。
誤: col1の値でテーブル内のレコードを一意に特定できる場合
正: col1の値がテーブル内で一意の場合
誤: SELECT * FROM [table] WHERE col1 = 4 AND EXISTS(SELECT 1 FROM [table] WHERE col2 = 5 AND col3 = 6)
正: SELECT * FROM [table] WHERE col1 = 4 AND EXISTS(SELECT 1 FROM [table] WHERE col1=4 AND col2 = 5 AND col3 = 6)
訂正前の>57を読んだとき、>58の批判は全く正当だ。
あまりに89(=58?)に対してすまなかったので心の中でロールバックしといた
時に、EXISTS を使うとき、SELECT 句では何を返してる? 具体的なDB名を挙げられないのだが、 昔は、定数を返した方が速かったそうだが、 現在のオプティマイザでは、* を返した方が速いらしい、ということをどこかで聞いた。 まあ、ms, ns の世界だとは思うが、必要な場合には試してみてくれ。
今から言うことはオフレコで。 EXISTS(SELECT 1 FROM foo WHERE ...)と、 EXISTS(SELECT * FROM foo WHERE ...)と、 EXISTS(SELECT a, b, c, d FROM foo WHERE ...)とでは データベースエンジンがやるべきことに違いが生じないっていうか原理的に生じ得ない。 というのは、いくら列の指定に凝ってみても、 データベースエンジンにしてみればテーブルを検索して指定条件をテストすれば済み、 戻し値を生成する必要がない、というシチュなので。 ただし、より複雑な状況において、具体的な列指定がオプチマイザに対して テーブル検索回数を減らす最適化のヒントを与えることもあるかもしれんがよくわからない
>>93 ということはキーではないカラムdを抽出するようなクエリであったとしても、
エンジンはexistsの中に書かれていることから、dを抽出しない動作になると?
>>94 一般に「dを抽出する」とは
(1) 指定条件に当てはまる行をテーブルから検索またはスキャンして
(2) 見つかった行のd列の値を(データベースのクライアントに)返す
という動作をコミにした意味だと思うが、EXISTS()内のSELECTでは(2)をやる必要がない。
というのは、EXISTS()の評価にあたっては、EXISTS()の括弧内に書かれたクエリ行が行を1行でも返すか、全く返さないか
どちらであるかのみが問題なので。
一方、(1)を遂行するにあたってはWHEREの後ろに続く条件式等があれば十分で、SELECT と WHERE の間に書かれている内容は無用。
96 :
95 :2008/10/25(土) 18:50:02 ID:???
途中で送信したorz
(1)の前には表の結合が入ることもある。
(実際は表の結合とステップ(1)はオプチマイザの働きで渾然一体となって進行するので、明確に前というと語弊が生じるが。)
>>94 (続き)
行の検索とキーとの関係は、次のような感じ。
キーである列には通常インデックスが張られているため検索パフォーマンスが高いが、例えば
SELECT d FROM foo WHERE c = 3
と言うクエリにおいて、列dがキーだったとしても、データベースエンジンが返すべき行を検索するにあたり、
活用されるのは列cのインデックスであり、列dのインデックスではない。
>>95-96 で結局だな、
>>92 が書いたようにEXISTS述語のサブクエリでは
カラム名を指定せずに SELECT * としておいて
DBのプランナもしくはオプチマイザ任せにしておくのが吉。
って結論になっている。ってことで桶だよな。
んじゃ、existsのなかでシーケンスを使ってみたりなんかすると? 使い道は思い浮かばないけど、文法上書くことはできるはずで。 DB依存の挙動になるのか、プランナの気分次第、未定義、どうなるんだろ。
>>99 シーケンスという特性上、カウントアップされるべきなら、実行されるんじゃね。
と言うか、プランナとかオプチマイザって思っている以上によくできてる。
IN述語よりEXISTS述語の方が高速で、IN (サブクエリ)形式の多くは
EXISTS (相関サブクエリ)に書き換え可能だから、そうするのはよく言われることだけど、
今じゃ下手すっとIN述語の方が速い。
行数にもよるだろうけど、IN述語=遅い という固定概念は捨てた方がよさげ。
おそっ なにこれw
>>100 おせえええええええええええええええええええええ
104 :
新人です :2008/10/28(火) 22:23:13 ID:+iClIPVC
はじめまして。 「*=」をJoin句に直したいのですが、結果がうまくいかず。。 SQL初心者です、どうぞよろしくお願いいたします。 この式をJOIN句に直したいです。 FROM A_TBL, B_TBL as B_TBL01, B_TBL as B_TBL02, C_TBL, D_TBL WHERE A_TBL.No = B_TBL01.No AND A_TBL.No = B_TBL02.No AND A_TBL.No = C_TBL.No AND A_TBL.No *= D_TBL.No AND C_TBL.ID *= D_TBL.ID AND ↓こうしたのですが、正しい結果がえられません。 FROM (D_TBL RIGHT OUTER JOIN C_TBL ON C_TBL.ID = D_TBL.ID) RIGHT OUTER JOIN A_TBL INNER JOIN B_TBL AS B_TBL01 ON A_TBL.No = B_TBL01.No1.No INNER JOIN B_TBL AS B_TBL02 ON A_TBL.No = B_TBL02.No2.No ON A_TBL.No = D_TBL.No AND A_TBL.No = C_TBL.No ご教授お願いいたします。
*=ってどこの方言? というか、こういうの(*=)ってどうやってぐぐるの?
ああ、でも雰囲気からいって a *= b は a is null or a = b ってことなのかなあ
107 :
NAME IS NULL :2008/10/29(水) 17:41:35 ID:+fWDHmgW
よろしくお願いします。 複数テーブルを、左外部結合したいです。 ・DBとバージョン MySQL: 5.0.51 ・テーブルデータ MainTable key data1 ------- 1 a 2 b SubTable1 key data1_1 ---------- 1 壱 2 弐 SubTable2 key data2_1 ---------- 1 ひ 2 ふ ・欲しい結果 key data1 data1_1 data2_1 -------------------------- 1 a 壱 ひ 2 b 弐 ふ MainTableとSubTable1だけのものはうまくいきました。 select MainTable.key, MainTable.data1, SubTable1.data1_1 from MainTable LEFT OUTER JOIN SubTable1 ON MainTable.key= SubTable1.data1_1; MainTableとSubTable1とSubTable2と、テーブルを二つ左外部結合 する方法がわかりません。以下の文で Warning: mysql_num_fields(): supplied argument is not a valid MySQL result resource in というエラーがでます。 select MainTable.key, MainTable.data1, SubTable1.data1_1, SubTable2.data2_1 from MainTable LEFT OUTER JOIN SubTable1 ON MainTable.key= SubTable1.data1_1, LEFT OUTER JOIN SubTable2 ON MainTable.key= SubTable2.data2_1; いろいろ入れ替えてみてためすのですが、 >select MainTable.key, MainTable.data1, SubTable1.data1_1, SubTable2.data2_1 ここの時点でエラーがでるようです。 よろしくお願いします
JOINつなげるのにカンマいらないだろ? あと ON でkey とdata_1比べてるけどkeyじゃないの?
109 :
107 :2008/10/29(水) 18:42:58 ID:+fWDHmgW
>>108 ありがとうございました、動作しました。素早い回答に感謝です.(_ _).
110 :
新人です :2008/10/29(水) 22:56:43 ID:I8Y4s5GR
105 106 さま INNER JOINを先に実行することを教えて頂き、解決しました。 ありがとうございました!
>>105 そういえばこのスレだったかもしれんが、「どこの方言?」って聞いたら
いきなり火病おこしたやつがいたな。
馬鹿にされたと思ったのか、田舎にコンプレックスを持っていたのか。
>>111 まじでw
方言確認気をつけるようにするわww
結局、*= を使えるのはどのDBMS? もしくは*=で検索する方法でもいいけどw
ちなみに "asterisk equal" join でググッタらでた。
しまったカタカナがまずかったか
>>4 のパターンで日付が同じデータが複数ある場合、全部持ってくるんじゃなくて 1件だけ
適当に取ってくる方法はないかなぁ。
秒数まで持ってるし、データ量や更新タイミングから言うとまず起こらないんだけど。
>>117 ベンダーによってはある。
MySQLならそのままで通る。
SELECT * FROM Table GROUP BY id;
PostgreSQLならDISTINCT ONがある。
SELECT DISTINCT ON (id) * FROM Table ORDER BY id,date DESC,data DESC;
OracleやMS-SQLにも何らかの方法があるんじゃね。
119 :
118 :2008/11/01(土) 21:19:37 ID:???
>>118 ではidでまとめちゃったが、日付ならidのところをdateで置き換えて。
と、挙げたSQLではGROUP BYされないカラムの取り出し方が、
MySQLは適当で、PostgreSQLではソート後の最大値(
>>4 と同じ)にしてる。
当然逆も可能。(念為)
117です。言うのを忘れていましたがMySQLでした。
>>118-119 うひょぉっ
本当だ。動いた。
>>4 みたいにGROUP BYしたのと結合してたのが馬鹿みたいだ。
取り出し方は適当で大丈夫なので、これで完璧です。
ありがとうございます!
121 :
118 :2008/11/02(日) 00:44:07 ID:???
あぁ、今更なんだが、 PostgreSQLの様に独自拡張の文法が用意されているのならともかく、 MySQLのは「そんなんありか!?」って仕様だからなぁ。いつ仕様変更されるかワカランし。 これが身に染みついちゃうと、後で苦労しても知らないYO。
>>121 まあ現行のMySQL特有ということは頭に置いておきます。
これ以外で方法なさそうだしなぁ…。
MAXかMIN使えば普通にどのDBでも複数行から一行だけ持ってこれる。みんな普通はそうやる。 MySQLだけ仕様がおかしい。
そうやって取得したものがいずれかの1行とは限らないからねえ
確かに。 group by でユニークキーをmax()/min() で持ってきて、それをサブクエリにして1レコードまるごと持ってくるとかするのかな。
126 :
NAME IS NULL :2008/11/04(火) 22:11:04 ID:+P/QclNj
次のsqlのうちパフォーマンスが良いのはどちらでしょうか? DB SQLServer2005 データはこんな感じです a_table a_id a_name 1 a 2 b 3 c b_table b_id b_name out_id 1 z 1 2 z 1 3 x 2 4 v 3 5 v 3 6 v 3 1: update a set a.a_name = b.b_name from a_table a inner join b_table b on a.a_id = b.out_id 2: update a set a.a_name = b.b_name from a_table a inner join (select distinct b_name,b.out_id b_table) b on a.a_id = b.out_id よろしくお願いします。
127 :
NAME IS NULL :2008/11/04(火) 22:12:21 ID:+P/QclNj
次のsqlのうちパフォーマンスが良いのはどちらでしょうか? DB SQLServer2005 データはこんな感じです a_table a_id a_name 1 a 2 b 3 c b_table b_id b_name out_id 1 z 1 2 z 1 3 x 2 4 v 3 5 v 3 6 v 3 1: update a set a.a_name = b.b_name from a_table a inner join b_table b on a.a_id = b.out_id 2: update a set a.a_name = b.b_name from a_table a inner join (select distinct b_name,b.out_id b_table) b on a.a_id = b.out_id よろしくお願いします。
>>126 まあ1だと思うがどっちも文法的におかしいぞ
129 :
126 :2008/11/04(火) 22:21:54 ID:+P/QclNj
>>128 レス有難うございます。
すみませんが理由を教えていただけないでしょうか?
130 :
128 :2008/11/04(火) 22:38:02 ID:???
>>129 2のサブクエリselect distinct b_name,b.out_id from b_tableが高速に実行できるとすれば
b_nameとb.out_idにはインデックスが張ってあるはずで、
そのインデックスは1でも有効に働くだろうから
余計なことをしていない1のほうが速いだろう。
と、思ったが文法がおかしいだけじゃなく正規化もされてないんだな。
とりあえず文法だけでも直して再度質問することをお奨めする。
再度質問する場合はa_table, b_tableそれぞれの件数、
インデックスの有無、distinctによる削減結果件数なども併記すべし。
きびしー><
132 :
128 :2008/11/04(火) 23:01:29 ID:???
え?そう? ごめん、しばらく黙る。
133 :
126 :2008/11/04(火) 23:21:40 ID:+P/QclNj
128さん
ありがとうございます。
>>130 a_table 1万件
b_table 3万件
インデックスはb_id
distinctの削減結果件数は1万件
文法についてですが、
エラーはなく正しく実行されているのですが・・・
>>126 それだとa_nameに代入されるb_nameの値が必ずしも一意に決まらないと思うが?
update に from が使えるのは SQL Server か 世の中広いな
それにしても直感的におかしな文法だな。 select 列 from 表 なら「表から列を選ぶ」だけど update 表 set 列 = 値 は「列に値をセットして表をアップデートする」だから from(から)の出番はないような気がするんだが。
ほええ。 やっぱ各DBMSの方言もしっとくべきだなあ。
SQL Server2000 tableA ID, name ----------------- 1 AAA 2 BBB 3 CCC 4 DDD tableB ID, kingaku ----------------- 1 100 1 150 3 100 4 200 4 300 tableC ID, kingaku ------------------ 1 100 3 300 ●希望する出力 ID, name, goukei ------------------- 1 AAAA 350 3 CCCC 400 4 DDDD 500 tableB,tableCにIDが存在する場合は集計し、 tableAのID,nameとともに出力。 集計はtableBもしくはtableCにIDが存在する場合に行い、 共に存在しない場合は出力しない。 こんな感じでよろしくお願いします。
>>138 SELECT * FROM tableA JOIN
(SELECT id,sum(kingaku) FROM
(SELECT * FROM tableB UNION ALL SELECT * FROM tableC) AS T1 GROUP BY id) AS T2
USING (id) ;
>>139 sql server に usingがなかったので一瞬焦りましたが、できました。
ありがとうございました。
usingのかわりがあるの? まあONで置き換えられるしな。
142 :
NAME IS NULL :2008/11/08(土) 01:14:43 ID:i4vY6ugV
Mysql アクセスデータを取得したいのですが判りません 何日にどのipの人がどんなページを見たかデータが入っています 取得したいのは何日に見に来た人数とページビューの数です (問) key ip address ----------------------- 2008/11/1 a page1 2008/11/1 a page2 2008/11/1 b page1 2008/11/1 b page3 2008/11/1 a page3 2008/11/2 c page1 2008/11/2 f page1 2008/11/2 g page2 取得したい結果 key ip address ------------------------- 2008/11/1 2 5 2008/11/2 3 3 よろしくおねがいします
>>142 group by して count()
>>142 MySQLって "key" っていうカラム名許可するんだ?
SELECT key,(SELECT count(DISTINCT ip) FROM Table WHERE key=T1.key) AS ip,count(key) AS address
FROM Table AS T1 GROUP BY key;
SELECT key, count(DISTINCT ip) AS ip, count(DISTINCT address) AS address FROM Table GROUP BY key; こうはできないもんなの?
146 :
NAME IS NULL :2008/11/08(土) 02:21:43 ID:i4vY6ugV
ありがとうございました 144と145両方で出来ました keyというカラムはなんとなく付けただけなのです 許可はされなかったみたいです 144より145の方が早く処理されました DISTINCTをよく調べたいと思います
countの中にDistinctなんてかけるもんなんだな
148 :
NAME IS NULL :2008/11/10(月) 14:08:32 ID:Kl9WWcCZ
ORACLE10gです。 下記の様なテーブルがある場合に、 A,B毎に最大の登録日、登録時刻をもつレコードを抽出したいのですが、 どのようなSQLを記載すればよいのでしょうか? ■元になるテーブル A|B|登録日 |登録時刻 1|1|08/10/01|11:00 1|2|08/10/02|10:00 ←この行 2|1|08/10/03|11:00 ←この行 2|2|08/10/03|10:00 2|3|08/10/03|09:00 ■期待する結果 A|B|登録日 |登録時刻 1|2|08/10/02|10:00 2|1|08/10/03|11:00
A,B毎というのがよくわからんかった
例を見る限りだとA毎に見えるよね
152 :
NAME IS NULL :2008/11/10(月) 21:37:19 ID:Eo8iobDT
MySQL エイリアス名を動的に付けたいのですがいい方法ご存知ありませんか オライリーのSQLクックブックの「回転」ぽい処理で使いたいです。 select max(case when x.cx = y.cy then x.cx else null end) as x.cx(ここを動的に) from (select distinct name as cx from table1) as x cross join (select distinct name as cy from table1) as y; 例えば name←コラム名 山田 藤本 佐藤 を、 山田|藤本|佐藤 ←コラム名 山田|藤本|佐藤 といった感じで。
153 :
148 :2008/11/11(火) 12:51:53 ID:D298vrnL
間違っていました。 ■元になるテーブル A|B| 登録日 |登録時刻 1|1|08/10/01|11:00 1|1|08/10/02|10:00 ←この行 1|2|08/10/01|10:00 ←この行 2|1|08/10/03|11:00 ←この行 2|1|08/10/03|10:00 2|1|08/10/03|09:00 ■期待する結果 A|B| 登録日 |登録時刻 1|1|08/10/02|10:00 1|2|08/10/01|10:00 2|1|08/10/03|11:00 ■書いてみたけれど、なんか違う気がします SELECT TMP1.A, TMP1.B, tbl1.登録日, tbl1.登録時刻 FROM (SELECT tbl1.A, tbl1.B, Max([登録日]+[登録時刻]) AS MAXDT FROM tbl1 GROUP BY tbl1.A, tbl1.B) AS TMP1 LEFT JOIN tbl1 ON TMP1.A = tbl1.A AND TMP1.B = tbl1.B WHERE TMP1.MAXDT=[tbl1].[登録日]+[tbl1].[登録時刻]
>>4 のやりかたでAとBについて出してUNIONでつなぐとか?
155 :
NAME IS NULL :2008/11/11(火) 20:39:01 ID:pgxBFx5e
MySQL 5.0です。 table_A id | name | age | blood ------------------------ 1 | aaaa | 12 | A 2 | bbbb | 11 | B 3 | cccc | 13 | O 4 | dddd | 12 | AB 5 | eeee | 14 | A 6 | ffff | 12 | O 上記のようなテーブルから、下記のようなデータを作成したいと思います。 table_B.`s`は一律です(今回は'1') table_B s | id| blood --------------- 1 | 1 | A 1 | 2 | B 1 | 3 | O 1 | 4 | AB 1 | 5 | A 1 | 6 | O INSERT `table_B` SELECT '1',`id`,`blood` FROM `table_A`; では偉ーとなってしまいました。 SQLのみで実現は可能でしょうか?
>>155 くだらん誤変換を放置してるようなことするからエラーが起きるんだよ。
INSERT INTO table_B SELECT 1,id,blood FROM table_A;
>>153 select a, b, max(登録日+登録時刻) from t group by a, b, 登録日+登録時刻;
こういうのってできないんだっけ?
A,B毎というのが、A,Bのすべての組み合わせなのか AとBと別に考えるのかが、その例だとわからないな
160 :
148 :2008/11/12(水) 12:21:18 ID:vPpovanH
>>153 参考にしてみました、
select A ,B,登録日,登録時刻
from
(
select Rank() over(partition by A ,B order by 登録日 desc,登録時刻 desc) as Rank
A ,B,登録日,登録時刻
from tbl1
)
where rank=1
order by A ,B
>>159 A,Bのすべての組み合わせです。
161 :
NAME IS NULL :2008/11/15(土) 19:12:30 ID:x3mReOjA
DB:sqlserver テーブルにデータを追加する際に、 ある列に1から連番を付与する方法を教えていただけないでしょうか? 追加処理の度に1から連番を付与する仕様になっています。 よろしくお願いします。
163 :
161 :2008/11/15(土) 19:51:47 ID:x3mReOjA
答えわかってんじゃんw
165 :
161 :2008/11/15(土) 21:26:03 ID:x3mReOjA
>>164 追加処理の度に1から連番なのでIDENTITYは使えません。
ROW_NUMBER()で対応します。
すみませんでした。
166 :
NAME IS NULL :2008/11/15(土) 21:46:31 ID:KO4GmOZO
MySQL4.1なんですが、 1位になった回数/試合数で計算し、勝率を表示したいんです。 試合数分のレコードがあって試合結果の順位が 記録されています。 ユーザーID|順位| 1 1 1 2 1 4 1 1 2 2 2 3 2 2 2 1 上記のデータであれば ユーザーID|勝率| 1 0.5 2 0.25 となるような結果を得るには、どのようにSQLを書けばよいのでしょう。 SELECT count( 順位 ) / count( ユーザーID ) AS 勝率 FROM table WHERE 順位 = 1 GROUP BY ユーザーID ORDER BY 勝率 DESC 上記SQLだと順位 = 1の数しか取得できないので無意味。 順位=1のレコード数とユーザーIDのレコード数を別々に もってくればいいのは分かるのだけど。。。
常に1を返す式と、1位のときに1を返す式を SUM して、後者を前者で割る
postgresのsequenceや、mysqlのautoincremantみたく、 要求したら+1されたユニークなIDを得るというのを、 DB依存せずにやりたいと思っています。 単純にテーブル(seq_table)1個作って、 トランザクション開始 update seq_table set id = id + 1 select id from seq_tableしてプログラムでIDを得る コミット でいいかな?
169 :
NAME IS NULL :2008/11/15(土) 22:08:02 ID:KO4GmOZO
166です。 167 の言うようにSQLを変更したらできました! サンクス! SELECT sum( 順位=1 ) / sum( ユーザーID>0 ) AS 勝率 FROM table GROUP BY ユーザーID ORDER BY 勝率 DESC
170 :
NAME IS NULL :2008/11/16(日) 21:36:41 ID:Q2ekdbiC
ずっと結合は2つのテーブルの間でしかできないと思いこんでいたのですが、 多対多というものを知りました。 これって、 テーブルAの行数 * Bの行数 * Cの行数 のテーブルを内部的に作成してから、条件を絞り込んでいくんですよね? 行数が増えたら、作成されるテーブルが恐ろしく巨大になりませんか? それぞれ10000行あったら1000000000000行のテーブルになるわけで、 それだけで処理が止まってしまうんじゃないかと思います。 実際のところどうなのでしょうか?
>>170 普通はWHERE句を先に処理するなどの最適化が行われる。
それより多対多という単語の使い方を間違っていないか?
3つのテーブルの結合イコール多対多ではない。
172 :
NAME IS NULL :2008/11/16(日) 21:43:43 ID:BeWlaJjJ
叩いた?
結合するテーブルの数と一対一、一対多、多対多の間には何の関係もないな
DBはOracle 10です。 TABLE_Bの特定の行をTABLE_Aにコピーしたいとします。 TABLE_AとTABLE_Bの構成が全く同じ場合は以下でOKなことは分かります。 INSERT INTO TABLE_A SELECT * FROM TABLE_B WHERE ID = 123; ただ、TABLE_AとBは基本的には同じ、ただし、Aの方が1列だけ多い。 そして、その列に特定の値(以下の例では5)を入れたい場合は以下の ようにするしかないのでしょうか? 列数が少ない場合にはコレでも良いのですが、多くなると(30列位)結構面倒です。 INSERT INTO TABLE_A SELECT COL1, COL2, COL3, COL4, 5 FROM TABLE_B WHERE ID = 123; ちなみに、以下のようにしたらエラーになりました。 INSERT INTO TABLE_A SELECT *, 5 FROM TABLE_B WHERE ID = xxxxxx;
>>174 INSERT INTO TABLE_A
SELECT * FROM TABLE_B CROSS JOIN (SELECT 5 FROM DUAL)
WHERE ID = xxxxxx;
でいけるような。
ただ、列の順序は保証されないってのが本来の仕様なので
TABLE_A側もB側も全ての列を明示的に指定するのが正しいっちゃ正しいが。
176 :
NAME IS NULL :2008/11/17(月) 10:10:10 ID:jsAO1g2R
お願いします。 ・DBMS名とバージョン Paradox,SqlServer2000 ・欲しい結果 ローカルHDにあるParadoxにINSERT文を発行したいのですが、FROMのテーブルがSQLServerです。 ・説明 可能でしょうか。
>>168 それでできるけど、アクセスするユーザ数が多い場合は更新待ちでパフォーマンス悪いかも。
DB: SQLServer 2005 or 2008
[articles]
id body
- ---------
1 hoge hoge
2 foo bar
[tags]
id article_id tag
- -------- ---
1 1 sqlserver
2 1 mysql
3 2 sqlserver
4 2 windows2008
[欲しい結果 (タグに sql と windows 両方を含む記事のみ検索]
id body
- ---------
2 foo bar
タグ付けされた記事を複数のタグでAND検索したいです。
以下を参考にタグの完全一致による検索はできました。
ttp://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html 次にタグの部分一致による検索を行いたいのですが、
どのようにしたらいいでしょうか?
たとえば windows と sql の両方をタグに含む記事を探したいのですが、
単純に以下のように like に置き換えてもだめでした。
# sqlserver と mysql が %sql% にマッチして having 句の条件を
# 満たしてしまうため、%windows% にマッチしない article_id=1 もヒットしてしまう。
select a.id
from articles a join tags t on a.id = t.article_id
where t.tag like '%sql%'
or t.tag like '%windows%'
group by a.id
having count(a.id) = 2
>>179 個別にやって、最大1ってことにして、それぞれ足し込めば?
>>179 思いつき... にしてもひどいSQLだな、こりゃ。
SELECT * FROM articles JOIN
(SELECT DISTINCT article_id FROM tags AS T1 WHERE
EXISTS (SELECT * FROM tags WHERE tag LIKE '%sql%' AND article_id=T1.article_id)
AND
EXISTS(SELECT * FROM tags WHERE tag LIKE '%windows%' AND article_id=T1.article_id)) AS T2
ON articles.id=T2.article_id;
>>179 select a.id
from articles a join tags t on a.id = t.article_id
group by a.id
having count(case when tag like '%sql%' then 1 end) > 0
and count(case when tag like '%windows%' then 1 end) > 0
とか。
前方一致とかインデックスが使える条件ならパフォーマンス的に
もう少し考えるべきところだけど、部分一致じゃどうせインデックス使えないから
テーブルスキャンを一回で済ませる形がいいかと。
>>174 INSERT INTO TABLE_A
SELECT
B.*,
5
FROM
(SELECT * FROM TABLE_B
WHERE ID = xxxxxx) C
ではどう?
oraはAS CつけたらNGだっけ。
>>183 横から確認してみたけど
INSERT INTO TABLE_A
SELECT B.*, 5 FROM TABLE_B B
WHERE ID = xxxxxx;
でいけるね。
185 :
179 :2008/11/17(月) 22:53:19 ID:???
>>180-182 ありがとうございます。CASE 使えばよかったのですね。
>>182 さんのsqlをちょっと改造して以下のような感じで実装してみようと思います。
sum(case when t.tag like '%sql%' then 1 else 0 end) > 0
そのままだと、「警告: NULL 値は集計またはその他の SET 演算で削除されました。」という
警告が出てしまうので。
インデックスについてはあきらめていました。中間一致だからインデックスが使えないっていうのと、
あと、複数の記事に同じタグを付ける場合が多いだろうから、タグによる検索では選択度が低くなり
インデックスを使ってくれないだろうなぁと。
インサイドSQL Server 2005 って本に選択度が5%以下じゃないとインデックス使うより
フルスキャンしたほうが早いからそうするよって書いてありました。
>>181 さんのEXISTSを使ったやりかただと、前方一致かつうまくいけばインデックスを
使ってくれそうな気がしますね。
みなさんありがとうございました。勉強になりました。
186 :
NAME IS NULL :2008/11/18(火) 14:00:38 ID:PMPxWylf
Oracle9iです。 table_A id | str | ----------- 1 | code=58 | 2 | code=587 | 3 | code=58 | 4 | code=58&code=59 | 5 | code=589 | 6 | code=58&code=62 | 上記のテーブルから、下記のようにstr列の中でcode=58の次の文字が数字以外というレコードを 取り出したいのですが、SQLのみで可能でしょうか。 10gならば正規表現が使えるようですが、9iでも同じような事ができるのでしょうか。 結果 id | str | ----------- 1 | code=58 | 3 | code=58 | 4 | code=58&code=59 | 6 | code=58&code=62 |
likeで一旦拾ってからnot likeで外してくしかないんじゃね?
case文でゴリゴリしたらできるんじゃないかな
状況が分からないから何とも言えないが、データの内容がGETパラメータなのであれば、以下で事足りるような? str like '%code=58' or str like '%code=58&'
str like '%code=58' or str like '%code=58&%' の間違い
マルチのなにが悪いかいってみろ
195 :
NAME IS NULL :2008/11/21(金) 19:42:28 ID:Ee0sJ6k2
マルチダさぁぁぁぁぁぁぁぁぁぁぁぁぁぁんんんんんん!!!!!!!
ヒンギスか
197 :
NAME IS NULL :2008/11/22(土) 13:56:31 ID:ai39yrzb
insert文の中に、select文を埋め込むことはできますか? イメージ的にはこんなことがしたいです。 insert into hoge values((selec max(id) from hoge), 'hello');
>>197 できないから、普通にこうしとけ。
insert into hoge
selec max(id), 'hello' from hoge;
セレク
セレク!!そこにいるのはセレク!! お前なんだね?!
はい、ご主人様
エス・キューエル家の人々
203 :
NAME IS NULL :2008/11/24(月) 08:25:44 ID:QSS6Kc1K
>>200 リアルで寒気を感じたw
まじできもいよ
204 :
NAME IS NULL :2008/11/24(月) 14:52:42 ID:3P4+K3os
初めまして。 SQLを覚え始めたばかりなのですが教えていただきたいことがあります。 testtable テーブル名 列名 データ型 Number int(50) name char(20) Money float DateTime datetime という構造のテーブルがあるとして Moneyに$500と入れたいのですが…$が入りません。 あと、datetime型のDateTimeに2008-05-10と入れてもエラーが出ます。 具体的に書くと insert into testtable (number,name,money,datetime) values(1,'the food shop', $500, 2008-05-10); と入れているのですが。 使っているのはMySQLです。 ついでにもう一つ、2008-05-10のところをできれば May-10-2008と入れたいのですが、その場合はdatetimeでは無理ですか?
>>204 ・float型に文字は入れられない
・datetime型をリテラルで指定する場合はシングルクォートで括る
・MySQLのdatetime型では'YYYY-MM-DD HH:MM:SS'の形式しか受け付けない
(区切り文字の変更や時刻の省略などは可能)
206 :
204 :2008/11/24(月) 15:28:15 ID:???
>>205 ありがとうございます。
やっぱりそうですよね…?
実は学校の課題なんですが
指定されてたtesttableがそういうデータ型の指定だったんです…
そこに$500とMay-10-2008と入れるようにと問題に書かれてて混乱してました。
明日学校で聞いてみます。
問題文をきちんと読んでないに3クエリ
Moneyは$であることが前提なんざんしょ
charだとしても単位を一緒に入れることはないよ
210 :
206 :2008/11/26(水) 07:46:36 ID:???
なんだか周囲の友達と話してたら
$って書いてるけどそのまま1000とか500とか数値だけ書けばいいらしくて
そのまま数字だけ書いてだしちゃいました。
>>208 さんの意見が妥当っぽいです。
皆さんありがとうございました。
211 :
NAME IS NULL :2008/11/26(水) 17:49:34 ID:P6dphl9h
SQLiteを使っています。 MySQLでいう SELECT date FROM test_db WHERE MONTH(date)='11' としてdate(日付)が11月のものだけ抽出したいと思っています。 しかし、SQLiteではMONTHが使えません。 何か方法はないでしょうか?登録されているデータはdatetime形式です。
strftime('%m', date) = '11' とかでどうか。 strftimeの書式はcの関数と同じ。
213 :
211 :2008/11/26(水) 18:11:52 ID:???
>>212 出来ました!こういう書き方があったんですね。
これなら年とか日も出来そうです。
大変参考になりました。ありがとうございました。
214 :
NAME IS NULL :2008/11/27(木) 18:21:18 ID:OUCKJ4Ly
Access2003で、テーブルがあって、何か機能を付け加えろと言われたのですが、 具体的にはどんな機能が加えられるのでしょうか? 初心者なのでよくわからないんです… ちなみに検索機能はもう実装してあります。 スレ違いかもしれませんがどうか答えていただけないでしょうか。
そういう人間はDBをいじっちゃいけないと思うんだがなぁ w
分析機能でも付け咥エロってことじゃないの? 統計、チャートとか
>>214 更新可能なデータを扱うのがDBと思ってくれれば、自ずと用途が決まると思うんだけどな〜
よくあるのは社員情報や商品の在庫管理。
>>214-217 > 何か機能を付け加えろと言われたのですが、
よくわからんのなら、こんなところでクダ巻いてないで、
言われた奴に聞き返せよ。
って言うか、釣りだろ。
>>218 そんな冷たい事いうなよ。
Accessの入門書くらい本屋行けばいくらでもあるのに、スレ違い承知でわざわざ書き込んでるんだぞ。
それにググればいくらでも参考になりそうなサイトが見つかるのに、わざわざ書き込んでるんだぞ。
それぐらいこのスレが大好きなんだ。
もっと優しく接してあげなければ。
やさしく接してあげた結果 SQLに全く関係のない内容で埋め尽くされたら おまえは全裸で土下座でもしてくれるのか?
なんじゃそりゃ
アクセスに機能を追加するとか凄腕ハッカーじゃね?
223 :
214 :2008/11/28(金) 20:31:44 ID:1YXDKRyt
>>218 教えてくれないんです…
実は、学校の課題なんです。
何か一つでもいいから具体例を教えていただきたいのです。
>>223 ・DBに対するフォームが存在して、それに検索機能は実装してある。
これに機能を追加するということでいいの?
今ある機能がCRUDのうちRだけなのであれば、CでもUでもDでも作ればいい。
Rを強化するんであれば、検索条件の細分化でもすれば?
225 :
214 :2008/11/28(金) 20:50:09 ID:1YXDKRyt
ここは課題を代わりにやってあげるスレじゃないから。 今まで出てきたヒントで十分だろ。
>>225 はぁ。いったい何がしたいのか分からん。
テーブル増やすとかそういうことをしたいの?
つーか、SQL 関係ないからスレ違いだな。 これ以上荒らさないでね。お願いだからさ。
CRUD関連の追加がだめなら確かにスレ違いだな レコードのファイルパスカラムのデータを元にフォームに画像を表示とか、、、まあどうでもいいや。スレ汚しごめん
つーか、宿題スレとか Access スレとか行くとこいっぱいあるだろ。 楽したいなら、にちゃんとかグーグルの検索ぐらい覚えろよ。 しつこくアゲてるから、どうせ釣りなんだろうけど。
質問者だからIDのためにageてんじゃないの?
おこちゃまなんだよ
SQLというかトランザクションの話なんですけど・・・ トランザクションの負荷は、純粋にレコードの件数に比例すると考えていいですか? insert文を10回発行して10レコード挿入するのと insert + selectでの1文で10レコード挿入するのでは、 トランザクション的な負荷は同じと思って良いですか? ここで言っているトランザクションの負荷というのは、 1トランザクションで処理できる限界への負荷という意味です。
234 :
NAME IS NULL :2008/11/30(日) 00:29:33 ID:l1/wPYst
DB(SQL)だけでこの世界で食べていけますかね。 数学もダメダメで、PG言語はほとんどわかりません。 そんな人居ますか?
数学関係無いし
>>234 SQL だけだと無理でしょ。
チューニングとかのノウハウ持ってるなら何とかなると思うけど、
そう言うやつはこんな質問しないだろうし。
DBだけで食ってる人はいるけどこの先も食えるかは知らない。 たいていの人はDBとプログラム両方できると思うよ。
238 :
NAME IS NULL :2008/12/01(月) 01:22:01 ID:KQlcGKxo
とあるテーブルにdate型の、3つのカラムがあるとする。 select col1, col2, col3 from tablen 3つのカラムの中で、maxなものを1つだけ抽出したい場合、caseでだらだら書く以外にシンプルな方法ありますか? max( max(col1), max(col2), max(col3) from tablen みたいにかければよかったんだけど・・・
maxなものを1つだけとは、 col1 2006年 col2 2007年 col3 2008年 とあったら、col3がほしいてことです。 ID惜しい・・・
DBMSの方言もしくは提供ファンクションを使わない限りはcase文ですっきり書くしかないと思うよ。
241 :
NAME IS NULL :2008/12/01(月) 19:55:15 ID:bNYYQYag
>>236 チューニングって
既存システムのDB改修の事?
それとも
OracleなどDBソフトの機能のカスタマイズの事?
>>241 パフォーマンス上げる為の調整のことだと思うけど?
それならできるよ!とか、そういう考えを持ってたんだろうか? プランを見て、ああ、これにインデックス貼らなくっちゃ。とかそんな程度のチューニングはその辺の PGでもできて当たり前で、DBで食っていくためには規模、システム構成にあわせたメモリチューニング だったり物理ファイルの配置レイアウトを考えたり、最低でもそういったことが求められるんじゃないかな。 俺はただのPGなのでその辺を任せられる人がいたら助かるなあと思うこともあるよ。
244 :
NAME IS NULL :2008/12/02(火) 11:16:37 ID:2PdMcQOD
>>242 >>243 様は処理速度は速くするためにDBをSQLでチューニングするって事ですね。
でも現在は処理速度の速いCPUと大容量のメモリを使用できる時代に不思議ですね。
よほどスペックの低い鯖がたくさんのこっているのでしょうね。
いつまでも あると思うな メモリと親のすね
246 :
NAME IS NULL :2008/12/02(火) 12:43:20 ID:rujSWkct
◆既にあるテーブル一覧 table foo bar . baz ID|NAME ID ID|ID2 -+----- -- -+-- 0a|hoge 0a 0a|a 1a|fuga 2z 0a|b 2z|piyo 1a|a ◆やりたいこと テーブルfooのうちbarにIDがあるものを抽出する。 ただし、bazのIDにも一致するものはID末尾文字を ID2に置き換えてbazの行数分出す。 ◆最終的な結果 ID|NAME -+----- 0a|hoge 0b|hoge 2z|piyo ↑これを出したいのですがうまいやり方がわかりません。 どうかご教授いただけるとありがたいです。 環境はMySQL5.0.5です。
>>246 SELECT CASE WHEN id2 IS NULL THEN id ELSE concat(substring(id,1,char_length(id)-1),id2) END,name
FROM bar JOIN foo USING(id) LEFT JOIN baz USING(id);
・DBMS名とバージョン SQLite3 ・テーブルデータ MainTable key item1 item2 --------------------- 1 1 2 2 3 3 2 4 SubTable ID name price ・・・ ------------------------ 1 サザエ 100 ・・・ 2 カツオ 80 ・・・ 3 ワカメ 20 ・・・ 4 アナゴ 999 ・・・ ・欲しい結果 key item1 item2 total ------------------------------ 1 サザエ カツオ 180 2 ワカメ 20 3 カツオ アナゴ 1079 item1とitem2の名前を引っ張ってきて合計金額を表示したいのです。 item2はnullの場合があります。これを実現するにはどうSQLを書けばいいか教えてください
>>248 ヒント:ifnull()もしくはcoalesce()
>>248 できればMainTableを見直したほうがいいよ。
251 :
248 :2008/12/02(火) 21:22:49 ID:???
>>249 ありがとうございます。
SELECT key,
( SELECT name FROM SubTable WHERE item1 = ID ) AS item1,
( SELECT name FROM SubTable WHERE item2 = ID ) AS item2,
ifnull( ( SELECT price FROM SubTable WHERE item1 = ID )
+ ( SELECT price FROM SubTable WHERE item2 = ID ),
( SELECT price FROM SubTable WHERE item1 = ID ) ) AS total
FROM MainTable;
これでやりたいことはできました。改善すべき点があればご指摘お願いします。
>>250 key item
----------
1 1
1 2
2 3
3 2
3 4
↑このようにしたほうがいいということですか?
Subtableに"ID:0 name:noitem price:0 ..."を突っ込んで、item2のnullの 代わりに0を使う、みたいな。
>>251 いや、普通にJOINすればいいと思うが
select A.key,
B.name as item1,
C.name as item2,
B.price + ifnull(C.price, 0) as total
from MainTable A
inner join
SubTable B
on A.item1 = B.ID
left outer join
SubTable C
on A.item2 = C.ID
テーブル設計を見直すならそのほうがいいけど
その場合は結果の出し方も考え直したほうがいい
>>244 SQL で チューニングって何か勘違いしてないか?
スペック云々で不思議がるってことはほとんど何もしたことがないからなんだろうか。
例えば、低スペックマシンで3時間かかるクエリがあって、それを高スペックマシンで
動かしたら10分で終わるようになりました。
けれど、インデックス、DBの設定を見直すことで、低スペックマシンでは20秒で
終わるようになりました。
こういうことが当たり前に起こる世界なので、高スペックなのに遅いのは単に処理が
面倒だからで片付けるのではなく、適切な設定などを行った上でも遅いのかどうかを
吟味する必要がある。
256 :
248 :2008/12/02(火) 23:04:16 ID:???
>>253 そんなにすっきり結合させる方法があったのですね。もっと精進しなくては・・・
どうもありがとうございました。
>>255 なんか説得の方向性が間違ってるような。
低スペックで3時間かかるものを高スペックに変えただけで10分になるとする。
しかし低スペックのままでもチューニングによって20秒まで縮めることができるとする。
あなたはどちらを選びますか?
みたいな感じじゃね?
もちろんチューニングにかかる人件費より高スペックに変える設備投資のほうが
安くて効果も充分だと思えばそういう選択肢もアリなわけで。
まあチューニングでごろっと変わるのはぼらくるだと思う。 MSSQLは普通に使っても効率よく動いてくれる。
えーと、どんなヘタなSQLでも、ですか?
DB自体の設定じゃないの?
Oracleも6〜7.3ぐらいまでなら、 DBの設定やcreateやりなおし技術とSQLの最適化だけで食うことができたが 今はどうなんだ? 設定ぐらいで劇的に変わるの?
>>244 プロセスが使えるメモリ空間の最大知ってる?
チューニングだけ専門に人をつけるってことは
その金を払うだけのメリットを見込める規模があるってことだよ
そもそも構築後の環境変更にかかる工数って
ただ買ってきたメモリを挿せばいいってレベルじゃない
当然ながら全テストやり直し
影響範囲の狭いやり方は常に求められる
最新スペックですら32ビットの壁で苦労してんだよ
話を最初に戻すけどSQL専業って工数圧縮の為に
派遣にやってもらうってことはあるけどSQLだけやってればいい上位職ってないと思うよ
DB構築時に全体を見渡せる人って重宝されるけどな
まぁ、PGっていうよりインフラ系になるんだろうが・・・
> その金を払うだけのメリットを見込める規模があるってことだよ > 最新スペックですら32ビットの壁で苦労してんだよ 規模がどうのこうの言う割には、32bit って... 馬鹿ですか?
>>263 確かにとっとと64Bit環境に移行しろよと思うことはある。
だけどなぁ、同じ鯖上で動くアプリが32bitでしかテストしてないとか色々理由があって、
64bitに出来なかったりすんのよ。
64bitOSでDB鯖作って、アプリは別鯖に切り出せよとかは無しな。
規模がどうのこうの言う割には、DBとAPが同じ鯖 って... 馬鹿ですか?
規模とかそういうのはスレ違いです。
GroupInfoテーブルからGroupNumber1000に所属しているユーザかつ UserInfoテーブルのStateフィールドが1になっているユーザを取り出したいのですが 以下のSQLだと構文エラーになるんですが,どこが違いますか? SELECT * FROM UserInfo WHERE UserInfo.State = 1, UserInfo.UserID = ANY(SELECT UserID FROM GroupInfo WHERE GroupNumber = 1000) 環境はMySQLVer5です
268 :
267 :2008/12/08(月) 12:24:45 ID:???
すいません.普通にANDつけ忘れてました
このスレで初めてワロタ
270 :
NAME IS NULL :2008/12/13(土) 00:31:16 ID:SY8WXs78
・DBMS名とバージョン Oracle9 ・テーブルデータ 受注受付 受注No(key) 受注日 顧客名 ----------------------- N13 20081202 D N14 20081203 E 受注詳細 受注No(key) 受注日 顧客名 地区 ・・・ ----------------------------------- N10 20081129 A あ地区 ・・・ N11 20081130 B と地区 ・・・ N12 20081201 C か地区 ・・・ N13 20081202 D と地区 ・・・ ・欲しい結果 受注No(key) 受注日 顧客名 地区 ・・・ ------------------------------------- N10 20081129 A あ地区 ・・・ N11 20081130 B と地区 ・・・ N12 20081201 C か地区 ・・・ N13 20081202 D と地区 ・・・ N14 20081203 E 受注受付は受注詳細が作成された後、一定時間で削除されます。 現時点で合わせたものを出力したいです。 どうSQLを書けばいいか教えてください。 よろしくお願いします。
>>270 SELECT * FROM 受注詳細
UNION ALL
SELECT *,NULL FROM 受注受付 AS T1 WHERE NOT EXISTS (SELECT * FROM 受注詳細 WHERE 受注No=T1.受注受付);
272 :
271 :2008/12/13(土) 01:04:33 ID:???
サブクエリの最後間違ってた。 ×受注No=T1.受注受付 ○受注No=T1.受注No
質問です。 ID | data | 更新日 1 | A | 2000/5/2 2 | B | 2000/7/22 3 | C | 2000/6/1 上記のようなtableと値があって、 常に更新日の新着順でselectを呼び出すものとします。 更新日はデータが変更される度にupdateで変更されます。 ソートの対象は常に更新日であるため、 更新日をインデックス化させたいところですが、 update処理でインデックス対象のカラムの値が頻繁に変更される場合、 インデックスの再構築処理の負荷を考えると インデックス化させた方が良いのどうか判断出来ずにいます。 ググるとdeleteはなるべく避けて、 updateでレコードの無効フラグをonにした方が良いとは書かれているのですが、 インデックス化対象のカラムの値のupdateについては見つけられなかったので、 どなたか分かる方がいらっしゃれば助言をよろしくお願いします。
あ、ソフトウェアはmySQLです。
update と参照(select)の相対頻度、総レコード数などの諸元によるのでは。 update は、24時間に一回未満(だって日付しか記録してない)、 select は、5分に一回とかいうなら、レコード数によっては index 張り直しても引き合いそう。
>>273 > インデックス化させた方が良いのどうか判断出来ずにいます。
測定すればいいだけだろ。
277 :
270 :2008/12/13(土) 13:54:35 ID:S9gQei/+
>>271 ,272 様
ありがとうございます。早速やってみます。
質問です Web上で年と月を指定するとその月の勤務表が現れるようにしたくて 日付を年月と日に分けて、IDと合わせ3つのフィールドで管理したいと思います 初歩的な質問だと思うのですが 日付を年月と日に分けるにはどうしたら良いのでしょうか? また実際のデータの記述はどのように分かれているのでしょうか? どなたか教えて頂けないでしょうか?
>>278 日付型ファンクションは処理系によって全然違うけど
一般的には文字列型に変換してからsubstr系の関数じゃね?
> 実際のデータの記述はどのように分かれているのでしょうか?
は質問の意味がワカンネ
日は要らなくね?年と月に分けるならわかるけど てかSQLの質問なんだろうか・・・
質問させてください。 A、Bというテーブルがあって Aの主キーがa_id、Bの外部キーがa_id(Aテーブルの主キー)として 2つのテーブルをleft joinで連結するとき select * from A left join B on A.a_id = B.a_id と書いたのですが人に指摘され select * from A left join B on B.a_id = A.a_id としたほうがよい、と言われたのですがこれには理由があるのでしょうか? 指摘をもらった人に聞いてみたら自分で調べろと言われたのですが ネットで検索してもそれらしい理由が見つかりません。 ご存知の方がいましたらお教えくださいm(_ _)m ちなみにDBはoracleです。
>>278 > 日付を年月と日に分けて、IDと合わせ3つのフィールドで管理したい
> と思います
年月とに日に分ける?
日付は普通に日付型で管理した方がいろいろな組み込み関数が使えるか
ら分けないほうがいいと思うぞ。
>>280 勤務表だからデータとしては、日までいるだろうと思う。
ただ、
>>278 の質問がいまいち要領を得ないので、なんとも言えないけど。
>>281 俺は同じだと思うけど
中には左辺にしかインデックス使わないとかいう処理系もあるのかもね
>>278 日付は1つの列で扱った方が、他のRDBMSやSQL上での比較に使いやすいよ。
下手に年月日で分けると単純な日付の比較でcastが必要な気がする。
2009/1/1 > 2008/12/31
等が実現できるDATE型をおすすめします。
>>281 > と書いたのですが人に指摘され
昔の覚えた変な知識から脱却できないじじいの
言うことなんて無視しとけばいい。
年月しか分からないから年月日のフィールドではダメだから分けるしかない><とか。 y年m月1日 <= 年月日 < y年m+1月1日 で指定年月のレコードとれるよ
>>285 古い知識がまだ有効であるような環境かもしれないじゃないか。
その書き方の差で結果が変わってた時代があるなんて俺には想像もつかないが。。。
けどきっとなんかあったんだろうなぁ。
>>280 > 年月しか分からないから年月日のフィールドではダメだから
> 分けるしかない><とか。
そういう時でも、便宜的に日のフィールドは1日固定にしとくとか
したほうがいいと思う。
>>227 > 古い知識がまだ有効であるような環境かもしれないじゃないか。
その状況で「自分で調べろと言われた」んだったら、職場から腐っ
てるんだろう。
質問です。 もともとはhtmlのみで作っていたのですがデータが変更になると関連ページすべてを 手作業でしなければならなくなり修正が大変になるので、DBからデータを参照して HTMLを生成するPHP+SQLというものを最近知りました。 調べていくうちにセキュリティの項目にぶちあたったのですが、データを参照するのみで サイト利用者がデータを追加したり検索したりといった入力フォームがない場合でも SQLインジェクションというものを考慮した方がいいのでしょうか。
>>289 スレ違い。
HTML から SQL を投げる形であれば、いずれにせよ SQL インジェクションの対応は必須。
>>290 該当するようなスレが見当たらなかったのですが失礼しました。
SQLインジェクションは考慮する形で調べてみようと思います。
>>291 DB な話じゃなくて、DB に投げるまでの話だから。
Web 技術とかム板とかかね。
prepared statement が有効だから、必ずしもDBの前の話とは限らないのでは。 prepared statement を使うと、ちゃんと実行計画してくれない、とかいう話が絡んでくるから。
場合によってはSQLインジェクション気にする必要はないけどね。 今回の話で行けば対応すべき箇所がないということになってそうに思う。
こんばんは。 下記のような処理を実施したいのですが、 SQL文はこれでよいでしょうか? また、他にも書き方がありますでしょうか? ご査収よろしくお願いいたします。 【実行したい処理内容】 テーブルAの中からCOL1、COL2、COL3の組み合わせが一致するデータで、 複数あればその中でCOL4が最大以外のデータを削除したい。 (最大値のみ残したい) 【SQL】 DELETE * FROM TABLE_A TB1 WHERE ((TB1.COL4) NOT IN (SELECT MAX(TB2.COL4) FROM TABLE_A TB2 WHERE TB2.COL1 = TB1.COL1 AND TB2.COL2 = TB1.COL2 AND TB2.COL3 = TB1.COL3 )) 【実行前】 [TABLE_A] COL1 COL2 COL3 COL4 --------------------- 100 200 300 10 100 200 300 05 100 200 300 15 140 220 300 10 150 220 300 33 150 220 300 44 150 220 300 55 【実行後】 [TABLE_A] COL1 COL2 COL3 COL4 --------------------- 100 200 300 15 140 220 300 10 150 220 300 55
select col1, col2, col3, max(col4) from table_a group by col1, col2, col3 以外のレコードを削除すれば良いのでは
こうかな?(未検証) delete from table_a tb1 where exists (select * from table_a tb2 where tb1.col1 = tb2.col1 and tb1.col2 = tb2.col2 and tb1.col3 = tb2.col3 and tb1.col4 < tb2.col4)
Oracle10gを使っています。 確か、サブクエリーが使えない句があったと思うのですが 忘れてしまったので教えていただけませんか。 よろしくお願いします。
次のような演算をしたいのですがSQLが分かりません。 よろしくお願いします。 顧客のテーブルと、その顧客が買った商品のテーブルがあって ある商品Xを買っていない顧客を調べたいと思っています。 TABLE 顧客にはIDとNAMEのフィールドがあります。 TABLE 購入にはCUSTOMER_IDとPRODUCT_IDのフィールドがあります 最初考えたのは SELECT DISTINCT ID FROM 顧客 LEFT OUTER JOIN 購入 ON 顧客.ID = 購入.CUSTOMER_ID WHERE ISNULL(購入.PRODUCT_ID) || 購入.PRODUCT_ID <> X という文でしたが、これだとXを買っていても他の商品を買っていると 取ってきてしまいます。どうしたらいいでしょうか?
>>299 select ID
from 顧客 A
where not exists (select *
from 購入 B
where A.ID = B.CUSTOMER_ID
and B.PRODUCT_ID = X)
301 :
NAME IS NULL :2008/12/18(木) 12:34:27 ID:ZuN1OxZw
顧客の個人情報をDB化させたいとお願いされたのですが、DBは弄ったことがないため 今から勉強したいと思っています。 ・別の場所にある子会社も同期をとって参照、書き換えができる。 ・自動的にバックアップをとる ・個人情報なのでセキュリティはしっかりと このような目的の場合、どの言語やソフト等を勉強するのがいいでしょうか? mySQLやアクセス等色々あるでしょうが 複数に渡って勉強できる時間はないので1つにしぼりたいのです。お願いします。
>>301 その要件と質問から読みとるあなたのスキルなら、
悪いことは言わないから外注に出すことをおすすめする。
やろうとしていることはシステム構成設計そのものだからな。 幅広い知識が求められる。 まあ、それ以前にスレ違い。
おれも
>>302 に一票。
て言うか、お願いされたやつに「できません」と言えよ。
顧客の個人情報なんて一番危ないやつだから、
> ・個人情報なのでセキュリティはしっかりと
のところでミスすると下手したら会社傾くぞ。
mysql5.0.51です。 CSV状に保存(3,5,2,6とか)しているフィールドに検索をかけたいんですが、 FIELDかFIND_IN_SETくらいしか思い着きません。 でもこれだと数値別に文を作成しないといけなくなります。 多分。 何か他に検索方法があったりするんでしょうか?
306 :
299 :2008/12/19(金) 00:59:06 ID:???
>300 ありがとうございます。 もしかしたらサブクエリに対応していないMySQL3.xで使うことになるかもしれないのですが サブクエリを使わないでもできますか?
307 :
NAME IS NULL :2008/12/19(金) 07:43:50 ID:K8IH8t/D
CREATE TABLE `category` ( `id` int(10) unsigned NOT NULL auto_increment, `name` varchar(16) NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `item` ( `id` int(10) unsigned NOT NULL auto_increment, `name` varchar(16) NOT NULL, `categoryId` int(11) NOT NULL, PRIMARY KEY (`id`) ) このようなテーブルがあり、カテゴリごとのアイテムの個数を調べたいのですが、 どうすればよいでしょうか? SELECT c.id,c.name,count( * ) FROM category AS c LEFT JOIN item AS i ON c.id = i.categoryId GROUP BY c.id これだとカテゴリに属するアイテムが0の場合でも1になってしまいます
inner join
item.id が null なら 0、非null なら 1 として sum()
count(*)をcount(i.categoryId)にすればいいだけでは?
MySQLでage.sqlのファイルをデータベースsageにインポートして
レコードの作成をしたいんですがどうすればできますか?
http://y-kit.jp/saba/xp/mysqltry3.htm ここを参考に進めてデータの一括投入のところで以下のエラーが出て進めません
Error: 1261 SQLSTATE: 01000 (ER_WARN_TOO_FEW_RECORDS)
Message: Row %ld doesn't contain data for all columns
オールカラムのデータをコンテインしてないからじゃないのかな
314 :
NAME IS NULL :2008/12/20(土) 11:50:46 ID:NTPL7EOm
自己非等値結合とは、どのような概念でしょうか?
どうしたらそれが出たのかも書いてくれないか
318 :
312 :2008/12/20(土) 21:49:33 ID:???
>>317 useでデータベース選んで、テーブル作ってから
ファイルは、C:\ に main.sqlを使いたいんでそれを置きました
mysql> load data infile 'C:/main.sql'
-> into table test;
でエラーがRow 1 doesn't 〜〜〜となります。
エラーをそのまま読むとデータの列が足りないように見えるが
320 :
もくもく :2008/12/20(土) 23:38:21 ID:vBt0wfGB
テーブルのカラムに flag1, flag2, flag3 があり、すべて ブール型であるとします。 これらを1つの整数型のカラム flags のビットで表現するように変更したいのですが、 パフォーマンスの劣化や、プログラムの保守性の低下などは、あり得るでしょうか?
create index test_f1 on test(flag1); のようなインデックスが張れなくなるから、 フラグの有無を検索するときのパフォーマンスが劣化するよ
322 :
もくもく :2008/12/20(土) 23:44:12 ID:???
323 :
NAME IS NULL :2008/12/21(日) 15:05:27 ID:E9EuX9rA
select 0x000a などとしたとき、10と数値で表示したいです。 しかしmysqlではblob型として認識されてしまいました。 どのように記述すれば良いでしょうか? mysql以外のDBMSでの情報でも構いません。
>>319 列の多いテーブルはどうやって作るんですか?
列をたくさん記述してあるcreate tableを発行すればいいよ
326 :
NAME IS NULL :2008/12/26(金) 10:14:52 ID:wzvura+F
MySQL、Postgres、FireBird、InterBase、SQLiteの最新版、もしくは入手可能な安定版 いわゆる巡回セールスマン問題っというのでしょうか、ノードからノードまでの利用可能な経路が何通りあるか、と言う問題をSQLで解決できないかどうかを検討中です。 ノードがA、B、C、...、AA、AB、...、Znnまで有限個数(わかりやすく、駅名だとします。) AからBまでの便はあるが、AからCの便はない、と言う具合に、便がある情報をノード情報として、次のようなテーブルに格納されているとします。 NodeNo|Sta1|Sta2| 1 | A |B | 2 | A |D | 3 | B |C | 4 | B |D | 5 | D |F | ... この表から、AからXまでの利用可能経路をピックアップしたいのです。 STa1にAを含むものを抽出、その結果のSta2に含まれている駅名をSta1に含むものを抽出、その結果のSta2に含まれている駅名をSta1に含むものを抽出...という具合です。 もちろん、同じ液を二度利用するようなことはありません。 最終的に No|Sta1|Sta2|Sta3|StaNN| 1 |A |B |D |X 2 |A |D |X | 3 |A |X | | みたいな表(フィールド数は実行結果で決定)を得たいのですが、そもそもSQLで可能ですか。 なお、AとBの格納順序には規則性があり、A|BだったりB|Aだったりすることはありません。
>>326 それをSQLでやるのは無理だと思うし、やったとしても、テーブルに格納する情報が足らなすぎる。
昔、駅すぱあとの開発記事かなにかで、駅から駅への方向情報や位置情報とかも情報として
持ってるとか書いてあるのを見た事がある。
「経路が何通りあるか?」ってアミダみたいな上から下な構造ならまだしも、電車の駅みたいな
構造だと、単純に経路を求めると何万通りとかザラにあると思うんだけど…。
で、どう絞るかって方法が重要で、その方法の1つとして方向情報や位置情報とかが出てくるんだろう。
>>326 WITH RECURSIVE か CONNECT BY が使えるDBならいけそうな気がする。
気がするだけで本当に出来るかどうかわからんけど、じっくり考えると面白そうだな。
実用なのか頭の体操なのかハッキリさせた方が良いかも。 実用なら頂点数などに関して大体のオーダーも。
再帰でできそうなきがする
部署、上位部署とかならともかく 山手線とか無限ループだぞ
>>332 軽く読んだけど、その記事の無限ループの回避策は不十分だと感じた。
パリを含む閉路は排除出来るけど、そうでない閉路(アメリカ一周とか)に
関してはやはりループに陥る。
ループを回避するには出発地や目的地についてではなく経路に関して
制約をかける必要があって、具体的にはin.経路にout.出発地が含まれ
ない事を調べる必要がある。
となるとin.経路をlike条件でしらべるか、in.経路をそれこそMULTISET型
とかの集合型にする必要があると思う。
いずれにしても経路カラムの内容はatomicでは無くなるのでSQLで書ける
にしてもなんか気持ち悪いなぁと思う。
334 :
326 :2008/12/27(土) 14:57:01 ID:dqX7NECP
おお、知らない間にたくさんレス、ありがとうございます。
>>332 参考になりそうなサイト紹介サンクス。
>>331 同じ駅は二度利用しないって制約があっても無限ループになるんですか?
しかも、駅間すべてにリンクがある訳じゃないんだけど。
>>327 格納する情報とは?
別に(ここでは)料金とか最速便とかを考慮しないんですけど。
むしろ、料金や時刻に関わらず、経路だけを見つけるということで、駅スパートなどより単純かと。
>>333 > パリを含む閉路は排除出来るけど、そうでない閉路(アメリカ一周とか)に
> 関してはやはりループに陥る。
そもそも元ネタが閉路じゃないのに何を言ってるんだ?
>>334 >>331 =>333 は、無視していいよ。
なんか妙にケンカ腰のヤツが来たなw コテハン入れてくれNG登録するから。
お前がコテハンつけたほうがいいと思うぞ。
338 :
333 :2008/12/27(土) 17:10:30 ID:???
>>335 自分は331じゃないのですが・・・
元ネタは
>>326 の事だと思うのですが、この文中の
>>もちろん、同じ液を二度利用するようなことはありません。
この制約が、与えられた元データによって保障されているのか、
(駅:Node, 便:Edgeで表現された有向グラフが閉路を含まないか)
それともクエリで実現するのかの、解釈の違いだと思います。
前者であれば確かに単純な再帰で実現できます。
ただ自分は後者の事だと読んだのですが・・・
>>335 閉路がないグラフの任意の2点間に経路がいくつあると思ってるんだ?
>>338 それを解釈して適切なクエリを作成するのは
>>326 本人だよ。
どんぴしゃのサンプルでないとだめな人なのか?
あと、MULTISET と atomic とか使うならちゃんと理解してから使ったほうがいい。
>>333 の文脈だとほとんど意味不明だよ。
>>339 自分で数えたらいいんじゃね。
馬鹿の上塗り?
もしかしてなんか悔しかったの? 今後レスするなら、 > 山手線とか無限ループだぞ について、説明してからにしてね。(w
再帰でとれば無限ループだろ。 理解できないなら入門書でも読め。
あおりたいだけのヤツは放置で
>>346 > 再帰でとれば無限ループだろ。
もしかして、
int foo()
{
foo();
}
で、うまく動かんと騒いでるレベルですか?(w
>>340 >>335 >そもそも元ネタが閉路じゃないのに何を言ってるんだ?
そもそも元ネタ(
>>326 )に「閉路じゃない」なんて書いてますか?
書いていないのであれば、
>>335 の指摘は適当ではありません。
私には書いてあるように思えませんし、閉路を含む場合に関して
atmarkの記事での回避策は不完全です。
ですので
>>333 のように書きました。
> それを解釈して適切なクエリを作成するのは
>>326 本人だよ。
> どんぴしゃのサンプルでないとだめな人なのか?
>なお、AとBの格納順序には規則性があり、A|BだったりB|Aだったりすることはありません。 と書いていることから有向ではないと考えられるし、そうであるならば、複数の経路を求めることを 想定していることから、閉路の存在を禁止してはいないと解釈するのが当然の帰結だわな。
はいはい、君は正いよね。 これで満足かな。
さんざん因縁つけて反論できなくなるとこれだよ。 マジコテハン付けてくれ。
>>351 ともあれ元ネタから閉路の存在の禁止は読み取りがたいんです。
なので突然
>>335 の様に否定されたときには少しカチンときました(笑)。
ともあれ、閉路が存在すると仮定して、閉路を含まない単純パスだけを
列挙するSELECT文って、綺麗に書けますか?
>>333 に書いた通り、likeや集合型を使う解は思いつきますが・・・
そもそも
>>335 は
>>333 へのレスなんだから、元ネタ =
>>326 じゃなくて、「その記事」の意味で書いてるし、文句をつけたい
なら「その記事」の著作者に言ってくれ。
要するにもう少し落ち着け。
でないと、
>>353 みたいな奴が沸いてくるから。
>>355 え〜、それなら。
>>335 >
>>331 =>333 は、無視していいよ。
無視しないで〜(笑)。いきなり無価値にされてたのもカチンの一つ。
閉路を含むグラフ一般に関しては「その記事」の方法は不完全。
でも元ネタ(
>>326 )からは閉路を含む可能性もあると読み取れたので
「記事の方法は不完全だよ」と指摘したのが
>>333 です。
この指摘、無価値ですか?
ともあれ、WITH RECURSIVEを使って単純パスの列挙、どう書きましょうか。
上手い方法、ありますか?
人が紹介した記事についていきなり、 > 「記事の方法は不完全だよ」 と書けばカチンとこないとでも思っているんだろうか...。
>文句をつけたいなら「その記事」の著作者に言ってくれ。 とか完全に逃げの姿勢だし、カチンと来ないんじゃないの。 「貼っただけ、中身は知らん」と思ってるかと。
359 :
326 :2008/12/27(土) 22:41:56 ID:dqX7NECP
うわ、なんでこんなに荒れてるんですか? もしかして僕の質問が悪かった?? 閉路ってのは、出発駅に戻ってしまうことですか? それだったら、なしです。「ある駅から、出発駅以外の駅に、同じ駅を2回経由せずにたどり着くルート」と書けば良かったのでしょうか。
>>357 「せっかくご紹介していただいた記事ですが・・・」ぐらい最初に書けば
良かったでしょうか。失礼しました。
でも記事の方法が閉路を含むグラフ一般に関して不完全(ですよね?)
なのは仕方がないです。改善策を探すしかないかと。
>>359 いや、問題になっているのは、求めたい経路の定義ではなくて
(こっちは「単純パス」という事で、十分に明確です)、与えられる
経路情報の元データ(NodeNo, Sta1,Sta2 )の内容です。
例えばあなたが最初に与えるSta1|Sta2の内容として、次に挙げる
R1、R2、共にあり得ますか?
もしあり得ないものがあれば、その理由も簡単に教えて頂けると
解きたい問題をはっきりさせるためにも良いかと思います。
[R1]
1|A|B
2|B|C
3|C|D
4|E|A
[R2]
1|A|B
2|B|C
3|C|D
4|D|B
ごめんなさい、R1間違えました。 [R1] 1|A|B 2|B|C 3|C|D 4|E|B
あまり子供がいなくてあれない板だと思うんだけど >ともあれ、WITH RECURSIVEを使って単純パスの列挙、どう書きましょうか。 >上手い方法、ありますか? とかには決して答えず、「記事書いたヤツに文句言え」「人が紹介した記事にケチつけやがって」とか ヒステリックにわめくだけのヤツがいるからねぇ。
冬休みだよ
親子関係のあるテーブルについての質問です Aテーブル(キー:商品コード) 商品コード 親子区分(0:子 1:親) AAA01 1 AAA02 1 BBB01 0 BBB02 0 BBB03 0 CCC01 1 Bテーブル(キー:親コード、子コード) 親コード 子コード 数量 AAA01 BBB01 2 AAA01 BBB02 4 AAA02 BBB01 1 CCC01 BBB01 3 CCC01 BBB03 5 抽出結果を以下のようにしたい場合、どのように抽出すればよいでしょうか? 商品コード 親子区分 数量 AAA01 1 0 BBB01 0 2 BBB02 0 4 AAA02 1 0 BBB01 0 1 CCC01 1 0 BBB01 0 3 BBB02 0 5 さらに、商品コードを指定することで、抽出結果を絞れるようにしたいです。 例.AAA02を指定した場合は以下が抽出結果となります。(指定した商品コード(親コード)以下を表示) 商品コード 親子区分 数量 AAA02 1 0 BBB01 0 1 CCC01 1 0 BBB01 0 3 BBB02 0 5 ご教授、よろしくお願いします。Oracle10gを使用しております。
前者は SELECT 親コード,子コード,数量 FROM ( SELECT 0 親子区分,子コード,数量 FROM Bテーブル UNION ALL SELECT 親子区分,商品コード,0 FROM Aテーブル WHERE 親子区分 = '1' ) ORDER BY 区分,親コード,子コード とかか。 後者はWHERE 親コード >= 指定した値、とかくっつければいいんでないの。
親と子が多対多ってどんな商品?
ざっくばらんに言うと、目的が分からない 親の数量は常にゼロで、子の数量がでればいいの? 指定した商品コード以下、というのは文字列としての「以下」という表現?
368 :
NAME IS NULL :2008/12/28(日) 00:56:01 ID:CE5MM/b2
>>366 子供。
夫婦の共同作業でないと作れない。
頑張れば沢山作れる。
だから多対多。でも売り物じゃない。
という冗談はともかく、子商品BBB01は親商品AAA01にもAAA02にも
使われるという事ではないかと。部品構成表だと良くあるような。
369 :
364 :2008/12/28(日) 01:14:23 ID:???
>>365 ありがとうございます。
参考させていただきます。
休日はSQLを動かせる環境がないため、
月曜に確認させていただきます。
>>366-367 親商品1つを構成させるために、
子商品が各々何個で構成されてるかを示しています。
それを、一覧で表にしています。
なので、
親商品01
子商品01 2個
子商品02 4個
親商品02
子商品01 1個・・・
という順番で表示され、親商品の個数は表には出しません。
指定した商品コード以下、とは親商品のコードを昇順に、
指定した商品コード以降を表示する場合です。
>>368 その通りでございます。
子商品BBB01は、親商品AAA01にもAAA02にも使われることになります。
大変恐縮ですが、子商品を軸とした抽出SQLもお願いできますでしょうか?
以下のように、子商品が、どの親商品で使われているかを、表わす表となります。
こちらは数量は必要としません。
商品コード 親子区分
BBB01 0
AAA01 1
AAA02 1
CCC01 1
BBB02 0
AAA01 1
BBB03 0
CCC01 1
子商品コードを指定した場合は、以下のようになります。
例.BBB02を指定した場合
商品コード 親子区分
BBB02 0
AAA01 1
BBB03 0
CCC01 1
すみませんが、よろしくお願いします。
370 :
327 :2008/12/28(日) 01:33:31 ID:???
>>326 なんか、久々にこのスレが揉めてるな…。
B___E
/ \ / \
A D G
\ / \ /
C ̄ ̄ ̄F
これまでの書き込みを要約すると上の図のような関係の時に、(AからGの
経路を求める時に)A→B→E→Dと来て、そその後にBに行った時に無限ルー
プになるのを止める方法があるのか?って事だな。
>>332 の方法だと出発地や到着地を意図的に止める事で回避しているが
上記のような関係だと、その方法は使えない。
それよりも上記の関係で左側に戻る経路(D→B/D→C/E→B/F→C等)が 無い事が保証されているなら、
>>332 の方法でokだろう。しかし、その場合は
A→B→D→C→F→G等の結果も排除する事になる。
>>334 何をもって(上記の関係の場合)左側とするかは情報として持つ必要があるので
そういう意味で「方向情報や位置情報」が出てくる。
頭の体操なのか、実務なのかどっちなんだろう。 実務だと同じ顧客に二度逝く事は有るよ。本当に二度利用しないって仕様で変更は無いの? ある程度の想定もして仕様を決めておかないと、設計が崩れて実務では酷い事に成ると思う。
>>360 > でも記事の方法が閉路を含むグラフ一般に関して不完全(ですよね?)
> なのは仕方がないです。改善策を探すしかないかと。
記事中の図とテーブルのデータ見ればわかると思うが、記事は別にグラ
フ一般に対応できるなんて言ってなくて、単方向のみのデータになって
るだろ。
それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う
のはどうかと思うぞ。
>>362 紹介したんだから記事の責任負えとか...、馬鹿ですか。
まあ、煽るしかできない子なんだろうけど。
>記事は別にグラフ一般に対応できるなんて言ってなくて、単方向のみのデータになって >るだろ。 >それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う >のはどうかと思うぞ。 そういう、条件に合わない記事を紹介するオマエが不完全って話だろ
もうそいつの相手はいいだろ。 「ボクちゃんが紹介した記事完璧!最高!」 「ちょっとでも異議があるヤツは馬鹿!死ね!」って繰り返してるだけじゃん。
>>365 が微妙に間違ってたので訂正
SELECT 子コード 商品コード,数量 FROM
(
SELECT 0 親子区分,親コード,子コード,数量 FROM Bテーブル
UNION ALL
SELECT 親子区分,商品コード,商品コード,0 FROM Aテーブル WHERE 親子区分 = '1'
)
ORDER BY 親コード,区分 DESC,子コード
>>369 の「子商品を軸とした抽出」については
上記SQLをWHERE 親子区分 = '0'にして、親コードの変わりに子コードで並べ替えて…とかで行けると思う
>>373-374 > そういう、条件に合わない記事を紹介するオマエが不完全って話だろ
>> どんぴしゃのサンプルでないとだめな人なのか?
まあ、
>>326 =
>>334 が参考にしてくれそうなので、雑魚はどうでもいいんだが。
>> どんぴしゃのサンプルでないとだめな人なのか? そこから「記事では不十分な部分をどうするか」みたいな話をしたら 「人が紹介した記事にケチ付けやがって」みたいに顔真っ赤にしてわめいちゃうんだったら どんぴしゃのサンプル紹介してもらわないとなぁ。
> 「記事では不十分な部分をどうするか」
の話については、
>>326 が自分で考えるなりもっと良いサンプルを見つけ
るなりすればいいだけのこと。もしくはお前さんが示してやればいいん
じゃね? 残念だが、俺には興味がないからどうでもいい。
俺が指摘してるのは、
>>372 の
> それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う
> のはどうかと思うぞ。
の部分だけだよ。
この違いが本気でわからないなら、かわいそうな人だと思うしかない。
まあ、煽るしかできない子なんだろうけど。
>>372 >記事は別にグラ フ一般に対応できるなんて言ってなくて、単方向のみの
>データになってるだろ。
>それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う
>のはどうかと思うぞ。
この辺りは
>>349 ,
>>354 ,
>>356 で何度か説明しました。
「閉路を含むグラフ一般」という条件は、勝手に持ち出した条件では
ありません。元ネタ(
>>326 )からは閉路の存在を否定出来ないため、
設定せざるをえなかったものです。この条件は自分だけではなく、
>>331 や
>>327 も考慮の対象としていました。
もう一度繰り返しますが、元ネタ(
>>326 )に対して記事の手法は
不完全である可能性があります。
不完全である可能性があるのであれば、その事を指摘した
>>333 を元ネタ(
>>326 )の主に対して「無視しろ」とした
>>335 のレスは妥当
ではありません。私のクレームはこの一点です。
異論があるのであれば、何故元ネタ(
>>326 )において
>>333 を無視
して問題が無いのか、元ネタ(
>>326 )の技術を元に説明して下さい。
あとここからは個人的感想になりますが、誰かに問題を解くための
参考を示す時は、大抵はその参考を用いて問題を解く方法の見通し
をつけてから自分は行います。なるべく的確な解を示したいですから。
で、元ネタ(
>>326 )の問題に対するWITH RECURSIVEを用いた解法
に関して、現在何か見通しはありますか?
そもそも「記事」を紹介した際に、元ネタ(
>>326 )における閉路の存在
の可能性は考慮していましたか?
まともなレス1回も貰ったこと無いだろうによく頑張るなw 中身について語れないから逃げ続けてるだけの奴だよ。
>>379-380 何回も書いてるけど、俺は「かなり近い」とは書いたけど、どんぴしゃとは
書いてない。
閉路を含むかどうかは
>>326 しかわからんし、
>>332 で紹介した記事が役
に立たないと思えば無視すればいいだけのこと。
> 誰かに問題を解くための参考を示す時は、大抵はその参考を用いて問題を
> 解く方法の見通しをつけてから自分は行います。なるべく的確な解を示し
> たいですから。
別にその姿勢は批判しないけど、その姿勢を人に押し付けないでくれ。
> 元ネタ(
>>326 )における閉路の存在の可能性は考慮していましたか?
全然してないよ。あくまでも参考だし、
>>378 にも書いたけど興味ないし。
あと
>>333 を無視しろと書いたのは、
> MULTISET型とかの集合型
> 経路カラムの内容はatomicでは無くなる
と意味不明のこと書いてるから (
>>340 で指摘済み)
>>381 お前も、よくがんばるね。
馬鹿みたい。
>>382 >別にその姿勢は批判しないけど、その姿勢を人に押し付けないでくれ。
押しつける気はないので、「個人的感想」と書きました。
ともあれ、記事紹介時点で閉路に関しては考慮も興味もなかった事が
はっきりしたのですっきりしました。返答ありがとうございました。
>>335 の理由もわかりました。確かに誤解を招く記述だったと思います。
閉路に対する注意まで十把一絡げに無視されてしまった理由が理解
出来ませんでしたが、元々閉路に対する考慮などなかったということで
あれば納得です。
というわけで、この点に関しては自分はお終いです。あとは本題です。
単純パスの列挙をWITH RECURSIVEを使ってすっきり書ける方法、
どなたか思いつきますか?
恐らく問題になるのは始点・終点だけではなく通過した全ノードの列を
表現した経路情報をどのようにカラム値として持つかだと思います。
ノード名をデリミタで連結した文字列にするか、それこそ入れ子リレーション
にする必要があると思うのですが、他の方法はあるでしょうか?
ガキばかりで楽しいわ
現場もこんなもんだし。 隣の席なのに、メールで同じように揚げ足取りで戦ってるんだぜwww
あるあるw 本質的な話になるとすべて煽りでごまかして 相手を攻撃するだけで優位に立ったつもりの奴が一人いただけで そうなっちゃうな。
>>383 > ノード名をデリミタで連結した文字列にするか、それこそ入れ子リレーション
> にする必要があると思うのですが、他の方法はあるでしょうか?
あとは、可能性があるとしたら Array ぐらいかな。唯一のコレクションらしいし。
ただ、ほんとにできるかは検討してないし、配列は上限値が固定になることと性
能がどうなるかはよくわからんので、悪しからず。
もし仕事でやるなら、後々のメンテを考えて素直にストアド組んだ方がいいと思
う。
>>384-386 自己紹介乙。
388 :
NAME IS NULL :2008/12/28(日) 23:22:22 ID:7vHd0a09
oracle10gなんですが、 日付、人、割合 081208,Aさん,0.31 081211,Bさん,0.37 081210,Cさん.1.67 というレコードがあって 081208,0.31 081209,0.31 081210,(0.31+1.67)の値 081211,(0.31+1.67+0.37)の値 出力を得たいのですが、 SQLでどうすればいいのでしょうか?
Oracle の Decode関数と同等のことを SQLServer でやりたいのです。 下記の示す Oracle 上で動作する Query を SQLServer 上で同等の 結果が得られるように書き換えるとどうなるのでしょうか? select decode(COL1, 1, COL1 * 1.5, 0) from TABLE_A
>>389 case文使うしか無かった気がする。
あるいは自前で関数作るか
素早いレスありがとう。 御意、早速調べてみるワ でも・・・、シンプルじゃなくなりそうだなぁ〜 多分、コレだけで SQLServer を嫌いになれますねw
>>388 081209を結果に入れるなら日付を列挙したテーブルが別途ないとダメだろう。
このテーブルを「日付テーブル」、元テーブルを「割合テーブル」として、
select 日付,
sum(割合) over (order by 日付)
from 割合テーブル
right outer join
日付テーブル
using (日付)
;
393 :
NAME IS NULL :2008/12/29(月) 00:52:30 ID:S/zwAQnp
>>392 THX!
081209,Aさん,0.32
を追加した場合、
レコード
081208,Aさん,0.31
081209,Aさん,0.32
081211,Bさん,0.37
081210,Cさん.1.67
出力
081208,0.31
081209,0.32
081210,(0.32+1.67)の値
081211,(0.32+1.67+0.37)の値
にしたいです。
そのSQLだと
総集計になってしまいました。
また、partition by追加してみると
日付毎の和になってしまいました。
やりたいことが見えない。
人単位では既に累計を持っていて、最新のレコードだけ取得すればいいということ?
だったらrow_number() over (partition by 人 order by 日付 desc)が1になるレコードだけに絞って
その後
>>392
395 :
394 :2008/12/29(月) 01:11:42 ID:???
あーそれだと081208がゼロになるか。 sql一発じゃムリだと思う。
396 :
394 :2008/12/29(月) 01:15:07 ID:???
あームリじゃないか。 分析関数使わずに、日付が自身以下で、人が同じでないものの中で、 row_number() over (partition by 人 order by 日付 desc)が1になるレコードを集計して… で行ける。
>>394 ありがとうございます。
1に絞ってみたんですが、
select to_char (a.YMD,'RRMMDD') label
,SUM(a.RATIO) over (order by to_char (a.YMD,'RRMMDD')) value1
from (
select
ymd
,ratio
,nm
,row_number() over (partition by nm order by ymd desc) num
from 割合テーブル a
) a
right outer join 日付テーブル b
on to_char (a.YMD,'RRMMDD') = to_char (b.YMD,'RRMMDD')
where a.num = 1
order by 2
これだと、名前ごとの最新レコード以外はとれませんでした。
(081208,0.31が消えてしまいます。)
相関サブクエリーだとどうだろう。 概念的にはこんな感じ。 select D.日付, (select sum(割合) from 割合テーブル P where P.日付 <= D.日付) from 日付テーブル D WHERE D.日付 BETWEEN (select MIN(日付) FROM 割合テーブル) AND (select MAX(日付) FROM 割合テーブル)
399 :
397 :2008/12/29(月) 01:51:23 ID:???
>>398 THX
割合テーブルのレコードを増幅するしかない気がしてきたんですが、
増幅のDMLは一発で行ける感じですよね・・
>>396 で言いたかったのは
>>398 の
(select sum(割合) from 割合テーブル P
where P.日付 <= D.日付)
の部分を
(select 割合計 from
(select
sum(割合) 割合計
,row_number() over (partition by 人 order by 日付 desc) rn
from 割合テーブル P
where P.日付 <= D.日付
)
where rn = 1
)
にした感じ
>>393 人ごとのその日までの最新の割合を足すっていう要件だとして、
select 日付, sum(割合)
from (select A.日付,
B.割合,
row_number() over (partition by A.日付, B.人 order by B.日付 desc) as NUM
from 日付テーブル A
cross join
割合テーブル B
where A.日付 >= B.日付
order by A.日付)
where NUM = 1
group by 日付
;
もうちょっとスマートにならないものか・・・
>>401 神!!!
いやぁ、なんとお礼を言っていいのか、分かりません・・
403 :
401 :2008/12/29(月) 02:33:16 ID:???
深夜でボーっとしてるのでいい案が思いつかない・・・
どうでもいいが
>>401 のorder byは要らないな・・・
MySQL 5.0ですが 一度評価したものは再利用できないでしょうか? 例えば select ( COALESCE( (SELECT MAX(t.updated) FROM t WHERE t.title_id=b.title_id GROUP BY t.title_id limit 1), b.created, 0) ) as max_updated, DATE_FORMAT(max_updated,"%m/%d %H:%i") as updated FROM (b) ORDER BY max_updated desc,b.title_id desc のようなことをしたいんですが、 正常にソートするためには年の部分が必須なので、悩んでます。 何か方法あるようでしたら、教えてください。
max_updatedを再利用したいのであれば単にクエリをネストすれば 良いんじゃないかと思う。
>>405 まったく同じクエリをネストするのもどうかと思って質問したのですが、
現時点ではネストする事で対応しようと思います。
ありがとうございました。
例の荒れた「各駅を一回だけ通過するパスの列挙」ネタですが、 調べてみるとSQL2003ではそのものドンピシャな"CYCLE句"なる ものが定義されているんですね。 WITH RECURSIVE パス一覧 (出発地, 到着地) AS SELECT 出発地, 到着地 FROM 便一覧 UNION DISTINCT SELECT P.出発地, T,到着地 FROM パス一覧 P, 便一覧 T WHERE P.到着地 = T.出発地 CYCLE 出発地 SET CMARK '1' DEFAULT '0' UNING 経由地リスト SELECT 出発地, 到着地, 経由地 FROM パス一覧, UNNEST(パス一覧.経由地リスト) AS 経由地表(経由地) なんてやると再帰のフラグを記憶するCMARK列と出発地の値の 列を記憶する配列型の経由地リスト列が追加されるらしい。 ついでに再帰も自動的に止めてくれるらしい。 でも、これって何所のRDBMSで実装されているんでしょうか?
408 :
364 :2008/12/29(月) 20:27:29 ID:???
>>375 本日、動作確認し、正常に動作したことを確認しました。
ありがとうございました。
助かりました。
スレ違いかも知れませんが 排他制御やロックが詳しく解説している本やサイトがあったら教えてください。 お願いします。
>>409 ベンダーによって排他やロックの実装方法は違うので、ターゲットとしているRDBMSを
書いた方がいいと思いますよ。(とはいえ、RDBMSベンダーは、ライバルの他ベンダー
のイイとこ取りを互いにやりつつ今日に至っているのできてるので、現在は、どのベンダ
ーも似たり寄ったり、大差ないのでは?非常に高度化、極小化が実現できてると思
いますけどね)
つーか、RDBMS側にお任せせず、ユーザーのアプリ側で排他制御やロックを意識しな
ければならないっていう事情とはいかなるものか、ソレも書いたほうがいいかもですね。
↑誤植訂正 × 今日に至っているのできてるので ○ 今日に至っているので
ロックはまだしも業務排他はRDBMS側で何もやってくれんと思うが
コレ、業務の排他制御のことを聞いてるんですかね? だとしたら、本人の言われているようにスレ違いですねw そのあたりを解説している書籍を紹介してくれと言われてもなぁ〜 以下、フォローよろ
414 :
412 :2008/12/29(月) 22:35:35 ID:???
ああすまん設計スレと間違えた。
416 :
NAME IS NULL :2008/12/30(火) 01:10:20 ID:Myw6Zv98
MySQLなんだけどデータ型の再定義ってどう書くんだったっけ?
事故解決した
tableA tableB ┌─┬──┐┌─┬──┐ │id │rank.││id │rank.│ ├─┼──┤├─┼──┤ │01│ A ││01│ C │ │02│ B ││02│ B │ │03│ A ││03│ A │ └─┴──┘└─┴──┘ ↑のような二つのテーブルを、二つ併せ ┌─┬──┐ │id │rank.│ ├─┼──┤ │01│ A │ ┌──┬──┐ │02│ B │ │rank.│cnt │ │03│ A │ → ├──┼──┤ │01│ C │ │ A │ 3 │ │02│ B │ │ B │ 2 │ │03│ A │ │ C │ 1 │ └─┴──┘ └──┴──┘ このようにまとめ、最終的にGROUP BYした物を出力したいというのが目的のSQLで 下のようにSQLを書きました。 SELECT x.rank,COUNT(1) AS 'cnt' FROM ( SELECT rank FROM tableA UNION ALL SELECT rank FROM tableB ) as x GROUP BY x.rank ORDER BY cnt しかし、動作させるDBがMySQL4.0系なので、サブクエリが使用できません。 ↑のSQLをサブクエリ無しで4.0系で動作するように書き換えたいと思いますので アドバイス頂けないでしょうか
バージョンうpできないの?
>>420 レンタルサーバに設置する物なので、自分の一存ではバージョンアップ出来ません。
それに4.0からのバージョンアップは文字コード絡み絡み等で中々進まないのが現状みたいですし・・・
思いつかないならアプリで対応すればいいやって思っちゃうタイプなんだが、 きっと1クエリでやり遂げたいという希望をあきらめきれないんだよね? ホームディレクトリ配下にインストールしちゃえばいいのに、とかこう、関係ないことばっかり思い浮かんでしまうわ
一応、配布するソースですので、あまり特別な環境や条件で動かす事は避けたいです 1クエリにこだわっている訳ではないんですが、やはりアプリを複雑にすると負荷も増えるので 極力DBはDB周りで解決したいと考えています。 自分があまりSQLに関して知識が無いので、上の質問がどの程度の難易度なのか分かりかねているというのが 現状なので、どうしても実現出来ないようならアプリ側で対処しようと思っています。
【質問テンプレ】 ・MySQL5.0 ・欲しい結果:最終行のある要素の値 Mysqlのある要素の最終行の値を取得するクエリがわかりません select [ある要素] from [table名] where 〜; こんな感じで取得するクエリを教えてください
>>423 >あまり特別な環境や条件で動かす事は避けたいです
今やサブクエリを使えないRDBMSの方が特殊だと思う。
426 :
422 :2008/12/30(火) 06:27:47 ID:???
MySQL4.0はまだ結構生き延びてるように思うからこの手の要件は多いように思うけどね。
>>424 ある要素というのはカラムのことでしょうか。であれば、そこはカラム名を書けばよいです。
また、最終行というのは、未ソートの状態で全抽出した場合に一番最後に出力される行のことでしょうか。
MySQLに明るくないけれど、一般にはその出力順が常に同じである保証はありません。
何かのタイミングで変更される恐れがあるということです。
どれかの要素で昇順に並べて一番最後ということであればTOP LIMIT ORDER BY辺りを調べるといいかと。
427 :
NAME IS NULL :2008/12/30(火) 12:51:14 ID:kgoJw4fa
SQLの仕様でwhere句の長さの限界は決まっているのでしょうか? WHERE (id=0 OR id=1001 OR id=2210 OR ... OR id=9855) のような特定のidの行(1000行くらい)だけ抜き出したいのですが上のようにORが長すぎると結果が返ってきません。このような目的でよい構文などないでしょうか。
428 :
NAME IS NULL :2008/12/30(火) 13:18:37 ID:FEcKjDVX
in も上限があったような気がする。 1,000行もあるんなら、必要な id 入ったテーブル作って、 結合すればいいんじゃね。
長さは各RDBMSの個別の仕様
431 :
NAME IS NULL :2008/12/30(火) 13:56:48 ID:jQ3aBqQq
>>427 単純にこんな感じでSQL書いてみたらどうかな?
select * from テーブル where id in(1,10,……100)
union all
select * from テーブル where id in(101,120,……200)
union all
select * from テーブル where id in(201,230,……300)
union all
:
:
:
一行抜き出すクエリを1000回実行すれば良い話では。
何回もSQL流すよりは
>>429 の方法がスマートだと思った。
いや、テーブルつくるのに何回INSERTを実行するのかと・・・ idの組が毎回同じなのであればテーブルつくってJOINでしょうね。
そもそもそのidはどうやって抜き出したのか、というのもあるな。 よそで集計して持ってきたのなら地道にやるしかない。 まあSELECTくらいならINでいいとおもうけどな。
436 :
NAME IS NULL :2008/12/30(火) 17:06:54 ID:kgoJw4fa
たくさんのアドバイスありがとうございます。
C++のプログラム内からsqlite3ライブラリを使ってDBにアクセスするのでテーブル作る方法は難しいです・・・idはデータベースとまったく別のところで計算して求めます。そのidに関連する情報をDBから抜き出すって感じです。
ためしてみたんですがクエリの文字列長か条件のORの数かわかりませんが、id=...が600個超えるあたりから結果が返らなくなります。
>>432 だとオーバーヘッド大きいかな?
>>431 みたいに100個ずつ繰り返すのは何とかなりそうです。INってのがあったんですね。ありがとうございます。
>>436 >
>>432 だとオーバーヘッド大きいかな?
>>431 みたいに100個ずつ繰り返すのは何とかなりそうです。
一概にそうとも言えんて。
ちゃんとPrepared Statement使えば1000回発行してもそうそう
遅くはならないよ。
むしろ100個パラメーターを含むクエリを何度もコンパイルする
コストと評価するコストが気になる。
(長大なinだと殆どフルテーブルスキャンになりそうな)。
>(長大なinだと殆どフルテーブルスキャンになりそうな) すみません。ここのところは大ボケだったので忘れて下さい。
質問です。 DB:oracle10g TABLE:IdMaster ----------------------------- ID flag time updateName 001 0 2008/12/24 002 0 2008/12/25 003 0 2008/12/26 004 0 2008/12/27 005 0 2008/12/28 欲しい結果: flagが'0'かつtimeが一番古いレコードからn件flagを'1'に更新する。 この時に複数件トランザクションが実行さても同一のレコードに対して 更新がされないこと。 ちなみに以下のUPDATE文を試してみたが order by句でエラーが出ます、orderby句をはずすと実行出るが 2つのトランザクションを走らせた時は後のトランザクションが0件で 返ってきて更新できません。 宜しくお願いします。 UPDATE IdMaster AS A SET A.flag = '1' A.udateName = 'hoge1' WHERE A.ID IN (SELECT B.ID FROM IdMaster AS B WHERE A.flag = 0 AND rownum = 1 order by time asc ) 蛇足ですが、サブクエリ内の[A.flag=0]を[B.flag=0]にすると、同一のレコードが更新されます。 なぜ先に更新した結果を実行時に読みこんでないのでしょうか?
WHERE A.flag = 0 AND A.ID IN (SELECT B.ID FROM IdMaster AS B WHERE B.flag = A.flag AND B.rownum = 1 order by B.time asc )
>>439 こうじゃないの?(n件を一度に更新)
update IdMaster
set FLAG = 1,
UPDATENAME = 'hoge1'
where ID in (select ID
from (select ID
from IdMaster
where FLAG = 0
order by TIME)
where rownum <= n)
;
442 :
NAME IS NULL :2009/01/02(金) 23:10:44 ID:TtPfawPZ
SQLを解析するプログラムを作りたいのですが、 SQLの構文の定義みたいなのってどこかにありませんか?
XMLデーターベースってどうなの?
XPath と、 XQuery をざっと見てきな。 RDBMSごとに仕様が違うとはいえ、SQLの常識が通じない世界にびっくりするよ。 今から本気で取り組んでおけば、XMLDBが当たり前になった頃に頭角を現すことが出来るかもね。
いまはまだ 全然はやってないってこと?
まだまだ。 SQLとXMLが相互変換可能になった頃に流行ると睨んでる。
SQLとXMLの相互変換ってなんだ? それはさておき、XMLDBはXMLを直接格納・検索する大きな需要が 発生しない限り流行らんと思う。ってそのまんまだけど、逆に言うと、 数年前にXMLDBが注目された際に言われたような汎用DBとしての 普及はしないだろうということ。
DDLはXML Schema、DMLは参照に関してはXQueryが標準として 利用できるけど、更新に関して標準が存在せず、各社独自規格。 ここのところが標準化されない限りRDBMSを置き換える存在には なかなかならないと思う。
sqlmangr.exeなんですが起動したときにウインドが表示されてしまいます 引数で非表示に出来たと思うのですがどうやればいいんでしょうか?
SQL文のスレであってSQL Serverのスレではありません
そうなのですかーすみませんでした 他で聞いてみることにします
テーブルが select * from test; ROWID ID word 1 1 abc 2 1 def 3 2 def のときに select DISTINCT ID from test as TA where (TA.word = 'abc' AND exists (select ID from test as TB where TA.ID=TB.ID AND TB.word='def') ); の結果が ID=1 なのは期待どおりとして、ここで AND exists ではなくて OR exists にしてみると select DISTINCT ID from test as TA where (TA.word = 'abc' OR exists (select ID from test as TB where TA.ID=TB.ID AND TB.word='def') ); ID=1,2 が返るのが、なんか釈然としない。 exists の中の TA.ID = TB.ID は、「外側の TA.word='abc' で選ばれた row の ID について」という意味ではなくて、 「ID が等しい全rowについて」という意味になる、ということ ?
exists以前にandとorが分かってない気が。 >「外側の TA.word='abc' で選ばれた row の ID について」という意味ではなくて てのが違う。 TAの条件は 1.TA.word='abc' 2.exists (select ID from test as TB where TA.ID=TB.ID AND TB.word='def') のいずれかを満たすもの、なわけだから 1を満たさなかったから即除外、なんてことは出来ない。 それはANDの場合の考え方。
>>454 > exists の中の TA.ID = TB.ID は、「外側の TA.word='abc' で選ばれた row の ID について」という意味ではなくて、
> 「ID が等しい全rowについて」という意味になる、ということ ?
そういうこと。
existsの外側に何があろうとexists自身の結果には関係ない。
457 :
454 :2009/01/08(木) 07:10:23 ID:???
>>456 >existsの外側に何があろうとexists自身の結果には関係ない
明確にしてもらって、ありがたい。
>select DISTINCT ID from test as TA where (TA.word = 'abc' AND exists (select ID from test as TB where TA.ID=TB.ID AND TB.word='def') );
次のクエリと混同していた。
select DISTINCT ID from test as TA where (TA.word = 'abc' AND TA.ID = (select ID from test as TB where TA.ID=TB.ID AND TB.word='def') );
exists を使うと、「外側に何があろうと」結果を返してしまうから、結果が違ってくる。
大変参考になりました。ありがとう。
>>457 existsを使う使わないは関係ないよ
and と or それぞれがどういう挙動になるか把握できていないわけではない?
>次のクエリと混同していた。
混同も何も同じことだ。
>>457 の後者をorに変えても結果は
>>454 の後者と同じだぞ。
「existsが分かってなかっただけ」と思い込もうとしてしまうと
また同じ間違いを繰り返すことになる。
andとorの挙動っていうか、「条件」の区切りが分かってないのかな。
>>457 の例で言えば
TA.word = 'abc'
でひとつの条件、
TA.ID = (select ID from test as TB where TA.ID=TB.ID AND TB.word='def')
でひとつの条件であって、それぞれの条件は別々に評価される。
で、最後にandなりorなりで合体される。
どうでもいいが上の TA.ID = (select・・・ は
TA.ID = any (select・・・ とか書かないと
サブクエリで複数行返ってきたら怒られるんじゃないの?
461 :
457 :2009/01/09(金) 03:54:01 ID:???
御教示かたじけなく。 やはり付け焼き刃ではだめだ。一から勉強をやり直すことにします。
うん。 WHERE句の初期で学ぶ内容だから、今回の問題となったところも すぐに理解できると思うからがんばって。
どんだけ上から目線w
気に入らないなら人に訊かずに自己学習すればいいのに。
ざっくりした質問になってしまうがすまない SQL Serverの2000と2005で同じSQL文を発行したとき、 ・2005の乗っているサーバの方がはるかにハイスペック ・データベースの中身は同じ(互換レベル80) ・統計情報とかはちゃんと寸前に更新した という条件で、2005の方が結果が出るのがはるかに遅いっていう 現象を経験したことある人いない? 大量にデータを抜いてくるようなSQL文なんだけど、2000のだと ものの10秒とかで抜いてくるんだけど、2005だと6分くらいかかる 結構複雑っていうかスパゲティなSQL文なんで実行プランも結構 違うんだが、2000の方はソート、2005の方は外部結合に時間を 一番割いている模様
>>466 DB2では似たような経験アリ
DB2は統計情報を手動でいじれるんでそれで解決した
SQL Serverはシラネ
てかスレ違いだろ ここはSQLのスレであってSQL Serverのスレではない
>>467 thx
やっぱ統計情報の問題なのかね?
>>468 まあま、いちお「SQL文をどう解析・実行してるか」という点も重要かと
思うんで、固いこと言わずにw
ゲイツってなんでいつも変な名前つけるんだろうね SQLの製品にSQLとか。
「ぽすぐれ?さいべーす?聞いたこと無いな。SQL何とか?あーなんか聞いたことあるな、よしそれでいこう」 的な効果を狙ってるんでは
アポーも割と一般名詞の機能付けて検索しづらいぜ。
>>472 AIRPORTにはびびった。そんな一般的な名詞を使うなと。
SQLを製品名(の略称)だと思ってる奴もいるよな 「SQL使えるか?」の意味が「SQL Server使えるか?」だったりして、 紛らわしいことこの上ない
うちの上長(SE)がそれ。 話しにならんわw
MS的には「してやったり」だろうな
入社してすぐの頃、自称SE(50くらい)が「SQLを使うな!」というから、 汎用系触ったことねーよとちょいびびっていた。 ふたを開けてみたら「SQLServerは糞!ORACLEかDB2しかいかん!」といいたかったらしい。 理由は外注が実装した処理が糞重くて使い物にならないから。 テーブルもインデクスも設計が糞。さらにAPPソースも糞。 最初の1年でアプリごと総取っ替えプロジェクトに組み込まれて死にそうになった。 でも、きちんと設計しなおしたら、パフォーマンスがン千分の1になった(ベンチマーク上) で、SQLServerが悪いのかい、自称SEさん? (でも、MySQLかPostgreSQLで十分だと思う。 自称SEさんは知らなかったみたいだけどね。)
メモリ足りなかっただけじゃないの? DBでメモリ少ないのは致命的だし。 総取っ替えプロジェクトもまたSQL鯖だったのか?
どうでもいいけど「パフォーマンスがン千分の1になった」ってのは パフォーマンスが悪くなったみたいな感じするね 「処理時間がン千分の1になった」ならわかるけど
そこは、まあ、ふいんき(なぜry)で解るんだが、 「SQL」はそれが効かない
481 :
NAME IS NULL :2009/01/11(日) 17:30:24 ID:XyLcHKyX
Oracle 11g を使用しています。 scott スキームの EMP テーブル(以下のような感じのもの)で、 +-------+-------+------+--------+ | EMPNO | ENAME | (中略) | DEPTNO | +-------+-------+------+--------+ | 7369 | SMITH | (中略) | 20 | (以下略) DEPTNO ごとにまとめてのレコード数を求めるために SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO; とすると、 DEPTNO COUNT(*) -------- --------- 10 3 20 5 30 6 という結果が得られました。 そこで「一番レコード数が多い DEPTNO」を取得したい場合は どう SQL を記述すれば良いでしょうか? (希望する結果は以下のようなものです) DEPTNO COUNT(*) -------- --------- 30 6 SELECT MAX(COUNT(*)) FROM EMP GROUP BY DEPTNO; だと以下のような結果が得られるのですが、 COUNT(*) --------- 6 ここに DEPTNO を併せた形で取得したいと思っています。 何卒お知恵をお貸しください。よろしくお願いします。
最初のSQL文をorder by してrownum=1で取れる。 もっとマシなやり方あったっけ
483 :
481 :2009/01/11(日) 17:56:28 ID:???
>>482 レスありがとうございました。
残念ながら
SELECT DEPTNO, COUNT(*) FROM EMP
WHERE ROWNUM=1 GROUP BY DEPTNO;
だと
DEPTNO COUNT(*)
-------- ---------
20 1
と予想外の結果となってしまいました。
そこで更に試行錯誤している時にピンときて、解決策を見つけることができました。
それは副問い合わせを使用する方法で、
SELECT DEPTNO, COUNT(*) FROM EMP
HAVING COUNT(*) = (
SELECT MAX(COUNT(*)) FROM EMP GROUP BY DEPTNO
)
GROUP BY DEPTNO;
で
DEPTNO COUNT(*)
-------- ---------
30 6
が取得できました。大変お騒がせしました。
あー
>>482 で言いたかったのは
SELECT DEPTNO, CNT FROM
(
SELECT ROWNUM RN,DEPTNO, COUNT(*) CNT FROM EMP GROUP BY DEPTNO
ORDER BY COUNT(*) DESC
)
WHERE RN = 1
て事ね
485 :
481 :2009/01/11(日) 18:17:13 ID:???
>>484 なるほど、勘違いしていました。
そちらのやり方の方が断然スマートですね。
そのままだと何故か「GROUP BYの式ではありません」
とエラーになってしまいましたが、
SELECT DEPTNO, CNT FROM
(
SELECT DEPTNO, COUNT(*) CNT FROM EMP
GROUP BY DEPTNO
ORDER BY COUNT(*) DESC
)
WHERE ROWNUM = 1;
で期待する結果が得られました。
重ね重ねありがとうございました。
>>477 > ふたを開けてみたら「SQLServerは糞!ORACLEかDB2しかいかん!」といいたかったらしい。
実際、昔の SQL Server は糞だったんだよ。
ダーティリードは平気でするし、ロックのエスカレーションは普通におきるしw
行レベルロックサポートしてなかったんだよね。だから、更新系のトランザクションが
ガンガン走るようなシステムでは SQL Server は選択子のうちに入らなかった。
まあ、今はそんなことないけどどね。
商用のRDBMSでは各ベンダーの機能実装競争が終焉し、いい意j未でどれも
似たりよったり。高いレベルにいきついまったね。差が無くなってしまった。
今じゃ、SQL Server も行レベルロックをサポートしてるし・・・。
MySQLやPostgreSQLが商用RDBMSに追いつこうとがんばっている状況かな。
> でも、きちんと設計しなおしたら、パフォーマンスがン千分の1になった(ベンチマーク上)
ありがちな話w。
つーか、SQL文が書けて、プログラムが組めるというだけで・・・(以下略
行レベルロックをサポートしてないのになんでロックエスカレーションが起きるんだ? ページロックからテーブルロックへのエスカレーション?
>>487 > ページロックからテーブルロックへのエスカレーション?
そう。
Oracle が行レベルロックを実装していたにも関わらず、その頃の SQL Server は、
最小のロックの単位がページ単位だった。おまけに、ページからテーブルロックへの
エスカレーションがおきるというシロモノだったんだよ。
20世紀の話だよ
>>488 Oracleはロックっていうよりバージョニングでしょ。
(古いデータと新しいデータの両方を保持する。)
Postgresもそう。
DB2はロックだね。
だから未だにエスカレーションは起きる。
(もちろんチューニングは可能だけども。)
SQL ServerとMySQLはどうなん?
490 :
489 :2009/01/11(日) 23:43:30 ID:???
あれ?俺なんかすごい変なこと言ってるな・・・ 酔っ払ってるから、忘れてくれ・・・
>>489 >Oracleはロックっていうよりバージョニングでしょ。
Oracle は ロックとバージョニング(ロールバックセグメント)の両方
を実装してるよ。で、自分以外のトランザクションに対して未コミット
状態の変更を隠してるのがバージョニング機能の方でしょ。
Postgresはバージョニングって言っていいんでしょうね(多分w)。
なんだか、スレ違いになってきましたが・・・
俺も、SQL Server とMySQLについて知りたいかも
492 :
489 :2009/01/12(月) 00:32:52 ID:???
>>491 俺が自分の発言を変だと思ったのは、バージョニングであっても
ロックもしているわけで、ロックエスカレーションの話と
バージョニング云々は直接関係なかったな、と。
で、調べてみた。
Oracle、Postgres、MySQL(InnoDB) ・・・ エスカレーションしない
DB2、SQL Server ・・・ エスカレーションする
みたい。
エスカレーションしないDBは、その必要がない、効率のよいロック機構を
備えている、らしいけど、それがどんな機構なのかまでは調べてない。すまん。
493 :
NAME IS NULL :2009/01/12(月) 12:11:56 ID:AvSts/fL
もう解決してるからいいんですが、
>>481 のクエリって単純に
group by〜 以下
having DPETNO=MAX(DPETNO)だけで目的の結果が得られるんじゃないですかね?
494 :
NAME IS NULL :2009/01/12(月) 12:22:45 ID:AvSts/fL
↑あ、よく読んでみたら一番多くのレコード数のDEPTNOでしたね…すみません そしたら、 having count(*)=max(count(*))で取得できないですかね?
>>494 maxとcountのグループ化単位が違うんだから無理だろ
できるんじゃね?
違う
違うか?
どなたか教えてください。 ORACLE 10.2.0.2.0です。 (問) key data ---------------- 1 a 2 b 2 c 3 d 3 e 4 g というテーブルから key data --------------- 1 a 2 b 3 d 4 g というデータを取り出したいのですが、どういうSQLになりますか? keyには、同じ値が複数ありますが、その場合は、それぞれ1つのデータのみを 取り出したいです。 その際、同じkeyで1つを取る場合は、どのデータでもよいです。 つまり、上記のデータの場合ですと、keyが2のデータは、2件ありますが、 「key=2、data=b」と「「key=2、data=d」のどっちかが取れればよいという ことです。
>>500 Oracle専用の解:
select key,
data
from (select key,
data,
row_number() over (partition by key order by key) as RN
from TableName)
where RN = 1
;
dataがUNIQUE、もしくはkeyとdataの組み合せでUNIQUEとかの制限がないと
一般解は無理かな?
502 :
500 :2009/01/13(火) 22:22:34 ID:???
>>501 ありがとうございます。
ぐぐろうとしても、いい検索語が思いつかずこまっていました。
明日さっそく、試してみます。
すいません、サーバーAにあるデータ(CSVファイル)を、サーバーBに取り込むにはどうすればいいんでしょうか・・・?
>>503 スレ違い。
imp とか bcp とか、バルクインサートとか、DB にあったやつを選べ。
>>500 んじゃ汎用的な解
select key, data from a_table A
where not exists (
select * from a_table
where key = A.key
and data < A.data
)
group by key, data
select key, MAX(data) from table group by key これではあかんの?
>>505 それって
select key, min(data) data from a_table A group by key, data
と同じことだよね?
select key,min(data) from table group by key
>>505 が汎用的と書いているのはa_tableに他のカラムがあって、それも抽出したい場合を考えれば分かるかと
key dataしかカラムがないのであれば
>>507 でいいけど
苦しいw オラクル専用に対しての汎用的って事でしょ。
あれ?いきなり話題を逸らしてきたな。 じゃあ「汎用的」は結局苦しい言い訳でした、でいいの? 同じじゃないといえば、わざわざ難しく書いた挙句 「最小データが複数件あったとき正常に動かない」というバグを持ってるねw
column A と column B が一致(重複)している行の一覧を 取得したい場合は、どういう SQL になりますでしょうか?
ID A B 1 a b 2 b a 3 c c とあったとき「A と B が一致(重複)している」というのは、 ID=3 だけ ? それとも、ID=1,2 も含むの ?
>>515 あ、すみません。例を出すと
ID A B
1 a b
2 b a
3 c c
4 a b
という状態で
1 a b
4 a b
を表示したいということです。
>>516 SELECT * FROM Table WHERE (a,b) IN (SELECT a,b FROM Table GROUP BY a,b HAVING count(*)>1);
SQLServerでOracleのシーケンスのようなプロシージャを、 テーブル参照しないで実現したいのですが、どのように実装すればよいでしょうか?
ORDER BY使って日付ソートしてるんですが、 NULLの値も含まれてて先にそれが表示されてしまいます。 NOT IS NULLを使って表示しない事もできますし、DESC使えば可能ですが、、 ASCの状態で且つNULLを後に表示させたいのです。 NULL無しとNULLのみのクエリで2回発行するしかないですか? 例 ID 名前 日付 1 aさん 20080125 2 bさん 3 cさん 20090115 を ID 名前 日付 1 aさん 20080125 3 cさん 20090115 2 bさん とソートしたいです。
NULLを先頭にするか末尾にするかは設定で変更可能な場合があるよ
銀行システム作ってるんだけど、 数値を1増やす、って処理をするとき、 PHPで1増やし済みの変数を用意して、 それをupdateでデーターベースにぶちこんだほうがいいのか、 それとも、 SQLの命令で、「1増やせ!」って命令を送り込んで データーベースの内部で1増やしたほうがいいのか、 おしえてけろ。
>>519 order by case when 日付 is null then 1 else 0 end
というようなことをやってみたらどうだろう
>>519 >>520 の指摘どおりだけど
SELECT文の中でどうにかするのなら
order by句でnvlなりisnullなり使えばいいんでは
524 :
523 :2009/01/14(水) 19:56:18 ID:???
525 :
521 :2009/01/14(水) 20:38:21 ID:???
え。 それをするべきか、ロックを取得できたことを確認した状態で更新すべきかで悩んでいたのではなかったのか
527 :
523 :2009/01/14(水) 21:23:44 ID:???
ああー名前が残ってたしまたリロードしてなかったし
529 :
521 :2009/01/14(水) 21:37:18 ID:???
>>526 違う。
純粋にどういうコードを書いたらいいのか
わからなかった。
他に注意すべき点があるなら教えろ
てことはsequenceだのauto_incrementだのの存在も知らなそうだな しかしこんなPGが作ってる銀行システムって・・・
531 :
521 :2009/01/14(水) 22:06:52 ID:???
>>530 ああ、銀行っていっても
本番系でなくて、ゲームの中の銀行です。
でも実質的に、ネットバンクとかと
動きはほとんど同じですけどね。
532 :
521 :2009/01/14(水) 22:26:00 ID:???
update bookmark set count=count+1 where id=1 このコードで、アップデートしたいフィールドだけ、 ピンポイントで増加させることができるようになった。 感動。
533 :
521 :2009/01/14(水) 22:26:33 ID:???
だれか一緒に、 ゲームの中の銀行システム 作りたい人いる?
スレ違いだな。そろそろ消えてなくなれよ。
銀行システム作ってるんだけど、 って書き始める必要あったの?
536 :
521 :2009/01/14(水) 22:31:42 ID:???
>>535 もちろん。どういうシステムなのか、
イメージさせないと、ぴったりのアドバイスは
出ないでしょう?
537 :
521 :2009/01/14(水) 22:32:58 ID:???
そんで、次の質問。 データーベースで数字をカウントアップさせるとき、 ファイルロックとかって気にする必要あるの? たしかMySQLは、読み込み、書き込み時に 何も指定しなくても、勝手にファイルロックかかるって 読んだ記憶があるけど? SQLiteでもそうなるの? それとも、トランザクションを使わないとだめ?
これ、このスレの範囲か? プログラム系のスレに行った方がいいと思うぞ・・・。 シーケンスのカウントアップ単体なら、明示的にロックする必要はないだろ。 他のデータ処理が伴うなら、当然トランザクションが必要。ロックとは直接 関係ない概念だけどな。
539 :
NAME IS NULL :2009/01/14(水) 22:58:42 ID:LMJsYGpi
しょうもないことなんですが、教えて下さい。 INSERT DELETE SELECT UPDATE などをまとめて呼ぶ時の呼称をを教えて下さい。 ini conf exe などを拡張子(extention)と呼ぶような感じです。 (他のスレで質問したのですが、ここの方が適切かと思いました。)
541 :
NAME IS NULL :2009/01/14(水) 23:02:38 ID:4hR9j4JG
mysql版では答えてもらえず、webプログラム版でもスレ違いといわれて ここにきました たとえば、 購入者A は 商品B,C,D 購入者B は 商品B,C,D,E 購入者C は 商品B,C,D,E,F,G の場合に購入者AにE,F,Gがお勧め商品という風に出したいんですが たぶんアマゾンのはそうなっていると思うのですが どうやってやっているのでしょうか? 教えてください
542 :
NAME IS NULL :2009/01/14(水) 23:03:57 ID:LMJsYGpi
>>540 すごいありがとうございます!
ネットで調べても全く分かりませんでした(調べ方が悪いんですが・・・)
ちなみにDMLとは何の略でしょうか。
543 :
521 :2009/01/14(水) 23:04:10 ID:???
>>530 シーケンスとか、ちょっと違う。
ボタンを一回押すごとに、
数字が1増える、
っていうのが、作りたいシステムだから。
545 :
521 :2009/01/14(水) 23:04:55 ID:???
>>542 データー マニュピレーション ランゲージ
data manupilation language
546 :
521 :2009/01/14(水) 23:05:36 ID:???
>>542 ググるクセをつけような。Data Manipulation Language
Create Table とかの DDL (Data Definition Language) と対。
>>543 SQL 関係ないなら、消えてなくなれよ。
549 :
NAME IS NULL :2009/01/14(水) 23:14:25 ID:4hR9j4JG
serial menberid name syouhinnid syouhin 1 1 aaa 1 うどん 2 2 bbb 2 かつ 3 1 aaa 3 そば 4 1 aaa 2 かつ このときに bbbにお勧め商品としてうどんとそば をだしたいです。(amazon)みたく テーブルがきたなくてすいませんが、要するに重複したやつを削除 してお勧め商品をだしたいです。 よろしくお願いします。
551 :
NAME IS NULL :2009/01/14(水) 23:15:09 ID:4hR9j4JG
serial menberid name syouhinnid syouhin 1 1 aaa 1 うどん 2 2 bbb 2 かつ 3 1 aaa 3 そば 4 1 aaa 2 かつ
サブクエリ使っていいならできるけど ダメなんだっけ?
553 :
NAME IS NULL :2009/01/14(水) 23:25:40 ID:4hR9j4JG
いいです。お願いします。
遅いだろうけど、 select * from tbl where memberid in (select shouhinid from tbl where name = 'bbb') and name <> 'bbb' and shouhinid not in (select shouhinid from tbl where name = 'bbb')
555 :
NAME IS NULL :2009/01/14(水) 23:29:43 ID:4hR9j4JG
ありがとうございます。
556 :
NAME IS NULL :2009/01/14(水) 23:30:17 ID:4hR9j4JG
本もかいます
select distinct syouhinnid,syouhin from table where syouhinnid not in ( select syouhinnid from table where menberid = ユーザー) and syouhinnid in ( select syouhinnid from table where menberid in ( select menberid from table where syouhinnid in ( select syouhinnid from table where menberid = ユーザー ) ) )
>>533 ゲームの中の銀行システムを作ろうとしてるけどアップデート文もままならない状態なので
代わりに作ってくれる人いる?と意訳してみたけど、あってる?
>>539 CRUDといったりするよ。
>>541 システムの機能やSQLでどうとでもなりそうな気がする。
オープンソースのCMSソフトでもよくある機能なので、インストールしてソースを見るのもいいかも。
561 :
NAME IS NULL :2009/01/15(木) 00:08:44 ID:/DtyTV7F
328 名前: すずめちゃん(埼玉県)[] 投稿日:2009/01/14(水) 10:43:37.00 ID:WwgLtqYD 中身見たんだけど、特許庁サーバーへの接続手順かなぁ だったら今回のお漏らしの最大の問題点 特許庁は大急ぎでサーバーODBCデータベースのパスワード変えないと ODBC.mdb *参考 mdbのパスワードは既弱性があって一瞬で解除できる フリーのツールでも所要時間ゼロ秒
563 :
519 :2009/01/15(木) 10:48:07 ID:???
>>522 これで上手くいきました!
ありがとうございましたm(_ _)m
これ画像の登録が無い行を後に表示したりとか、
使う用途結構ありあそうで便利ですね(^^)
564 :
NAME IS NULL :2009/01/15(木) 20:59:52 ID:g1b8HDNJ
565 :
NAME IS NULL :2009/01/18(日) 17:18:44 ID:hDKyghRK
Transact-SQL @id char(3) 変数@idに全て数字がセットされているか、 又は全て英字がセットされているかを判定したいのですが、 やり方を教えていただけないでしょうか? 宜しくお願いします。
isnumeric ってのがあるな。isalpha はないみたいだから、一文字ずつコードを確認したら?
PCRE正規表現(関数)は使えないの? '^[0-9]+$' とか '^[a-zA-Z]+$' など。
568 :
NAME IS NULL :2009/01/18(日) 18:40:36 ID:hDKyghRK
>>566 レス有難うございます。
英字は
if (@id >= 'a' and @id <= 'z') or (@id >= 'A' and @id <= 'Z')
でやろうと思います。
>>567 レス有難うございます。
正規表現は使えるんですかね・・
使えたら最高なんですが。
SQL Server で正規表現は無理。CLR ストアドで・・・ ってことだな。
制約つけりゃいいんじゃないの
他板から誘導されて来ました。 ご指導願います。 Vb.netで UPDATE テーブルA LEFT JOIN テーブルB ON テーブルA.CD = テーブルB.CD SET 〜を 実行すると、「キーワードLEFT付近に不正な構文があります」と エラーが出ました。 MS-ACCESSだといけたので大丈夫かと思ったのですが、 悪い所を教えて下さい。 よろしくお願いします。
>>571 ここが MS SQL Server の話題を扱う所だと勘違いしていませんか?
573 :
571 :2009/01/20(火) 01:09:33 ID:???
>>572 ごめんなさい、では何を扱う所なのですか?
SQL文についてお聞きしていいのかと思って書き込んだのですが…失礼があったならすみません。
全然スレチじゃないですよ。でもDBMS名を明記して欲しいところですが。MSSQLかどうかなんてわかんないし。 両方のテーブルを更新したいのならちょっとわかんないんだけど、テーブルAだけでいいなら update テーブルA set hoge = B.hoge from テーブルA left join テーブルB using(CD) とかでいけないかな
>>574 あんたもdbms名いいなよw
mssqlにはusingないよ。
576 :
571 :2009/01/20(火) 09:03:00 ID:???
>>574 うわ、ごめんなさい!
Microsoft SQL Server 2005です。
方言あるなら専用のスレ行ったほうが答えもらえるのが早いとは思うけどね。
でも
>>573 の言い方はSQL=MS SQLと思ってる気がしないでもないw
>>577 方言のないDBMSって何がありますか?
>>578 きみは「キーワードLEFT付近に不正な構文があります」
で何かわかるのかね?
少なくとも、元質問者はあっちでは使えたSQLがこっちでは使えなかった という質問なんだから専用スレのが速いだろうな。
>>579 良く分からないけど、方言のあるDBMSは専用スレへってことですよね
だったら方言のないDBMSもしくは規格について話すスレなのかなと思って、
方言のないDBMSを教えて欲しかったんです
LEFT付近に不正な構文があるんでしょ
方言なしってのは SQL92や99の構文だけで書くってこと 方言を一切持たないDBMSは見たことない
ここはSQL92質疑応答スレになりました。 SQL99以降は実装状況を見てもまだ殆ど方言だ。
製品名を教えてくれないと、SQL92の範囲で回答するしかないんだな。
それで「LEFT付近に不正な構文がある」としか言えなくなってしまう。
>>571 は別にスレ違いじゃないからね。念のため。
思考錯誤してみましたが、うまい解が浮かびませんでした。 是非ともご教示お願いいたします。 1.DBとバージョン SQLite 2.x 2.テーブルデータ CREATE TABLE a.tbl ( number integer, start integer NOT NULL, end integer ); (1) 既存のデータ number start end --------------------- 1 1 3 2 4 10 3 11 13 3.欲しい結果 2の(1)に対し、(a)を挿入して結果(b)を得たいと考えています。 (a)挿入するレコード number start end --------------------- null 7 null (b) (a)の挿入結果 number start end 1 1 3 2 4 6 3 7 10 4 11 13 以上、よろしくお願いいたします。
>>585 トリガでどうにかしたいってことでいいのかな
削除とか更新とかも必要になりそうな気もするけど
・startが7よりも大きいレコードのnumberをnumber + 1にする ・以下のレコードを挿入する startが7よりも小さいレコードのうち、一番大きなもののnumber+1 7 startが7よりも小さいレコードのうち、一番大きなもののend ・startが7よりも小さいレコードのうち、一番大きなもののendを7 - 1にする の3クエリだろうか
誰も正確に答えてないので・・・
>>571 SQL92だと、UPDATE文は
UPDATE <テーブル名> SET 〜 [WHERE 〜]
の形式しかない。
つまりUPDATE句に複数テーブルは書けない。
ちなみに標準から外れているという意味では
SQL ServerだとなぜかUPDATE文にFROM句が使えたりするけど
質問とは直接関係ないな。
情報不足ですみません。
>>586 現状、SQLiteを弄っている言語の方で削除や更新処理を行っているので
クエリだけでなんとかできないものかと思案していました。
>>587 おおお、なるほどありがとうございます。
うまく分解できていませんでした。ちょっと考えてみます。
590 :
NAME IS NULL :2009/01/20(火) 23:02:48 ID:13ofr99R
T-SQLです。 CREATE PROCEDURE test AS BEGIN 何かの処理 自作のデータ追加関数() 何かの処理 自作のデータ追加関数() END 自作のデータ追加関数を、上記のストアドで定義・使用したいのですが、 どのように定義すればよいのでしょうか?
management studio使うと楽に定義できますよ
592 :
590 :2009/01/20(火) 23:32:31 ID:13ofr99R
>>591 できません・・・
ストアド内に自作関数は定義できないのでしょうか・・
selectするときにソートするのではなく、insertやupdateのときにソート済みの状態にしておくようなことはできませんでしょうか。 select * from table_name order by column_name がボトルネックになっているのがわかったので、データを書き込むときにソート済みの状態にできればと思い、質問させて頂きました。 なお当方MySQLを使っていますが、MySQLに限らずこのような機能があれば紹介してください。 識者の方、よろしくお願いします。
>>594 大変参考になりました。
データを並べ替えて格納するのはできなくても、インデックスの値を順番に並べておくことはできるわけですね。なるほど。
ありがとうございました。
質問させてください。 ORACLE10g 10.2.0.1 以下のSQLを流した結果が1になるのはなぜでしょうか。 SELECT COUNT(*) FROM (SELECT (CASE WHEN 0 = (SELECT COUNT(*) FROM DUAL T2 WHERE T2.DUMMY = T1.DUMMY) THEN 'A' ELSE 'B' END) AS CODE FROM DUAL T1) MAIN WHERE 'X' = (SELECT T3.DUMMY FROM DUAL T3 WHERE MAIN.CODE = T3.DUMMY) ※DUAL表にはDUMMYカラムがあり、値'X'の1レコードのみ存在する。
>>597 何でだろうね?見た感じ0になりそうなもんだけど。
オラクル手元にないのでPostgreSQLで試したら0だった。
参考まで。
DB2も0だ。 バグ発見しちゃった?
600 :
590 :2009/01/21(水) 23:29:24 ID:j/lQSEbc
>>596 >ユーザー定義関数のことを指しているのであれば、ストアド内で作成も使用も出来る。
すみませんが、サンプルコードを教えていただけないでしょうか。
601 :
596 :2009/01/22(木) 00:09:53 ID:???
>>600 CREATE PROCEDURE [dbo].[std1]
AS
BEGIN
--作成
EXEC (N'
CREATE FUNCTION dbo.scalar1 ()
RETURNS int
AS
BEGIN
RETURN 100
END')
--使用
SELECT dbo.scalar1()
END
ストアド内でこんなことは普通しないと思うけど。
テーブルロックについて質問です。 1・mysqlで書き込み、書き換えを行った時、テーブルロックは自動的にかかるのですか? 2・自動でかかる場合、そのロックはリードロックになるのかライトロックになるのかどちらでしょうか? 3・「そんなもん設定による」という場合、設定の確認方法はありますか? 質問が重なってすみませんが宜しくお願いします。
質問する前になぜDBにはロックという機能が必要か考えた方が良い。
>>603 ありがとうございます、自己解決できました。
重ねて質問なのですが、
現在作成中のアプリケーションは全体からの読み込みが多く、
一行単位の書き込み・書き換えもそれなりに多いです。
そこで、
・一行単位の書き込み・書き換えのみ行ロック
・読み込みその他はテーブルロック
という動作が一番効率が良さそうなのですが、
MyISAMでクエリ発行毎に、能動的にテーブルロックを行ロックに変更することは可能ですか?
(InnoDBで行ロックをテーブルロックに変更、でもOKです)
>>604 MyISAMでは行ロックはできない。
InnoDBならデフォルトで行ロック、明示的にテーブルロックも可能、
バージョニングのため読み込み時にロックは不要。
だったような。
というか、トランザクションの分離レベル(Isolation Level)について
ちゃんと勉強したほうがいいと思う。
>>597 1になるね。
SELECT COUNT(*)
FROM (SELECT (CASE WHEN 0 = (SELECT COUNT(*) FROM DUAL T2 WHERE T2.DUMMY = T1.DUMMY) THEN 'A' ELSE 'B' END) AS CODE, ROWNUM
FROM DUAL T1) MAIN
WHERE 'X' = (SELECT T3.DUMMY FROM DUAL T3 WHERE MAIN.CODE = T3.DUMMY)
上のようにすると(ROWNUMを追加)0になる。
元の文と上の文では実行計画も違う。
SQL文を最適化する過程に問題がありそうだけど、
あくまで想像だし、厳密に原因を知りたいのであれば
オラクル社に問い合わせるしかないやろね。
607 :
597 :2009/01/22(木) 20:28:29 ID:???
>>598 >>599 >>606 レスありがとうございます。
とりあえずOracleの最新パッチ(10.2.0.4?)を手に入れ次第、もう一度検証してみようと思います。
Oracle10gで create table 商品 ( 商品コード integer, 商品ジャンル integer, 商品名 varchar(40), 仕入先 integer, 単価 integer, primary key (商品コード) ); みたいなテーブルで、 select * from 商品 where max(単価) = 単価 and 商品コード % 10 = 0 group by 商品ジャンル, 仕入先; みたいなイメージのSQL文ってどう書けばよいのでしょうか? 日本語で書くと ・商品ジャンルと仕入れ先でグループ化して ・グループの中で単価が最大で ・かつ商品コードの下1桁が0 こんな感じです。 ジャンル | 仕入 | 単価 | コード 1 | 1 | 100 | 1 1 | 1 | 200 | 0 1 | 2 | 300 | 0 1 | 2 | 400 | 1 ↑だとすると単価が200円のレコードしかひっかからない感じ
>>608 select *
from 商品 A
where not exists (select *
from 商品 B
where A.商品ジャンル = B.商品ジャンル
and A.仕入先 = B.仕入先
and A.単価 < B.単価)
;
動かしてないけど、 select * from 商品 A where コード % 10 = 0 and not exists(select * from 商品 where A.ジャンル = ジャンル and A.仕入 = 仕入 and A.単価 < 単価) のような感じでどうでしょう。
611 :
610 :2009/01/22(木) 22:51:28 ID:???
まるかぶりわろたw
612 :
609 :2009/01/22(木) 22:51:40 ID:???
あ、 ・かつ商品コードの下1桁が0 を入れ忘れた。。。
>>604 primary keyの取り方でロックがほとんど発生しない事もあるよ。
既にDBやTBL決まっているのであれば、周りの人に相談した方がいい。
下手すると貴方のアプリが動いてる時だけ長時間のロックが発生して問題になる。
1つのSQLでできるか分からないのですが、 category_table( [catid] INT, [cattitle] TEXT, [itemcount] INT ) items_table ( [itemid] INT, [catid] INT, [itemtitle] TEXT ) 上記のような2つのテーブルがあるのですが、category_tableのitemcountに、 items_tableに格納されているアイテム数(同じcatidを持つ行数)を格納したいのですが やり方がいまいちわかりません。 select catid, count(itemid) from items_table group by catid; として、その結果をプログラム側で処理をして update category_table set itemcount = 値 where catid = 指定行; というのをループさせることはできるのですが、できればSQLだけで書きたいとおもっています。 現行はSQLite3を使っていますが、ほかのDBにも移植したいので、できれば汎用的な SQL文を教えていただきたく、よろしくお願いします。
>>609 こういう時に正しく動かない
ジャンル | 仕入 | 単価 | コード
1 | 1 | 200 | 0
1 | 1 | 200 | 0
1 | 2 | 200 | 0
countをうまく使うんだ
>>615 select ジャンル, 仕入, 単価, max(コード)
group by ジャンル, 仕入, 単価
にするんじゃだめ?
>>614 やろうと思えば、
UPDATE category_table SET itemcount = cnt FROM (SELECT catid,count(*) AS cnt FROM items_table GROUP BY catid) AS T1 WHERE category_table.catid=T1.catid;
とか
UPDATE category_table SET itemcount = (SELECT count(*) FROM items_table WHERE category_table.catid = items_table.catid);
で、出来ると思うけど、category_tableにitemcountカラムを設けるのが間違いな気がする。
618 :
617 :2009/01/23(金) 01:59:51 ID:???
最初のUPDATE文のFROM句はPostgreSQL拡張だった。スマソ。
>>616 >単価, max(コード) ・・・・だと!?
も、問題をよく読むんだ。
>・商品ジャンルと仕入れ先でグループ化して
>・グループの中で単価が最大で
>・かつ商品コードの下1桁が0
>>615 グループ内で単価が同じものがあったときに
全件出すのか、一件に絞るのか、絞る場合はどういう条件で絞るのか
書かれてないから、
>>609 が「正しくない」とは一概に言えんな。
621 :
614 :2009/01/23(金) 09:01:10 ID:???
>>617 2つ目のクエリでうまく更新できました。ありがとうございます。
>category_tableにitemcountカラムを設けるのが間違いな気がする。
ほかにもっと良い方法があるということでしょうか?
623 :
608 :2009/01/23(金) 19:53:32 ID:???
レス遅くなってサーセンした!
>>609-610 Oh... Wonderful... これで目的が達成できました!ありがとうございます!
自分で書いたヤツだと副問い合わせが2回くらいネストしてて死ぬほど遅かったのですがこれだとすぐに結果が返ってきました
not existsはこんな便利な使い方もあるんですね 覚えておきます
>>615 なん…だと…!?
そのパターン考えてませんでした
そういうデータも有りうるっぽかったのでバグを仕込んじゃうところでした
ご指摘ありがとざす!
最終的にこんなんなりました
条件に
・単価がMAXが複数ある場合は商品コードが若いもの
を追加して
select *
from 商品 A
where
コード % 10 = 0 and
not exists(
select *
from 商品 B
where
A.ジャンル = B.ジャンル and
A.仕入 = B.仕入 and
case
when A.単価 < B.単価 then 1
when A.単価 = B.単価 and A.商品コード > B.商品コード then 1
else 0
end = 1
);
>>621 集計すれば取れる値をわざわざカラムとして持たせるな、って話だと思う。
スレ違いだけど、アクセス数の多いwebサイトで
商品のラインナップはめったに変更されることが無い、とかなら
毎回集計するよりは集計結果をカラムとして持たせた方がいい場合もある。
625 :
NAME IS NULL :2009/01/28(水) 18:01:12 ID:RRFhLZyc
SQLと集合演算がわからないので教えてください。 集合1: select * from XXX where A = 1 and B = 9 集合2: select * from XXX where A = 1 and B is null 集合3: select * from XXX where A != 1 and B = 9 という3つの集合があったとして、あらたに 集合1 + 集合2 - 集合3 という集合を求めたいんですが、これをSQLで書けますか。 使用DB:MySQL 5.0
626 :
NAME IS NULL :2009/01/28(水) 18:03:48 ID:RRFhLZyc
>>625 の続きです。途中で送信してしまいました。
これを求めるのに
select * from XXX where (A = 1 and B = 9) or ((A = 1 and B is null) and not (A != 1 and B = 9))
というSQLでいいでしょうか。
>>625 集合1 集合2のどちらも集合3の要素を一つも含まないので、-集合3の部分がいらなくなります。
まとめると、
select * from XXX where A = 1 and (B = 9 or B is null)
になるのではないかと思います。
汎用的(各SELECT文をそのまま使い回し)なら、 集合1 UNION 集合2 EXCEPT 集合3
MySQLはまったく知らんが 集合の+、−の演算が何を意味するのかわからんが 集合1,2はA=1しかなくて、集合3にはAが1のものはないんだろ (!=はノットイコールでいんだよな?) つまり、集合1や2には集合3と同じものは存在しないぞ −するの無意味じゃね? MySQLの!=が、NULLのものまでヒットしたらまた別かもしれんが
かぶったorz 最後の一文、よく考えたら=もNULLにヒットしないと同じか
>>625-626 論理代数的に言うと
A=1をX、B=9をY、B is nullをZとおいて
andを*、orを+、notを^と表記すると以下のようになる
(X * Y) + ((X * Z) * ^(^X * Y))
= (X * Y) + ((X * Z) * (X + ^Y)) ※ドモルガン律
= (X * Y) + ((X * Z * X) + ((X * Z) + ^Y)) ※分配律
= (X * Y) + ((X * Z) + ((X * Z) + ^Y)) ※吸収律
= (X * Y) + (X * Z) ※吸収律
= X * (Y + Z) ※分配律
まあ、最終的には
>>627 になるわけだが
632 :
631 :2009/01/28(水) 21:45:47 ID:???
あれ?途中間違えてる・・・ 最終的には同じだけど (X * Y) + ((X * Z) * ^(^X * Y)) = (X * Y) + ((X * Z) * (X + ^Y)) ※ドモルガン律 = (X * Y) + ((X * Z * X) + (X * Z * ^Y)) ※分配律 = (X * Y) + ((X * Z) + (X * Z * ^Y)) ※吸収律 = (X * Y) + (X * Z) ※吸収律 = X * (Y + Z) ※分配律
(X * Y) + ((X * Z) * ^(^X * Y)) なんで^(^X?
XとYの積集合が存在するかもしれないからでしょ。重複部分。
636 :
NAME IS NULL :2009/01/29(木) 08:41:10 ID:WYimhVr6
【質問テンプレ】 ・DBMS名とバージョン oracle10g ・テーブルデータ key fie1d1 --------------------- 1 a_a 2 b%b 3 c;c 4 ddd 5 eee ・欲しい結果 key fie1d1 --------------------- 1 a_a 2 b%b ・説明 禁止文字のチェックの為、_や%を含む項目を抽出したいのです。 宜しくお願いします。
639 :
636 :2009/01/29(木) 14:13:17 ID:???
自己解決しました。
640 :
NAME IS NULL :2009/01/30(金) 16:15:39 ID:tBSXSRct
質問です。 oracle10g 最終コンパイル日をチェックしたくて select object_name, last_ddl_time from user_objects where object_type = 'PACKAGE'; とするとコンパイルしたはずの日付でなくCREATEした日付が出てきました。 select * from user_objects where object_type = 'PACKAGE'; でみるとやはりLAST_DDLが全てCREATEと同じでした。 コンパイルした(しなおした)日付を知るためにはどうすればよいのでしょうか?
641 :
640 :2009/01/30(金) 17:03:53 ID:???
自己解決しました メンテナンスをCREATEでしていたため user_objectからlast_ddlを引いてもCREATEと同じになっていたようです。 dba_objectsから引いてくるとほしい日付になっていました。
642 :
NAME IS NULL :2009/01/31(土) 03:23:53 ID:RWyHsfcq
2つのテーブル(A、B)が全く同じ列(key1、key2、key3)を持っているので、 まずこの2つを結合してから処理を行いたいと思います。 そのためにはどのような操作を行ったら良いでしょうか? イメージは、 tableA | key1 | key2 | key3 | ------------------------- | A1-0 | A2-0 | A3-0 | | A1-1 | A2-2 | A3-3 | ------------------------- tableB | key1 | key2 | key3 | ------------------------- | B1-0 | B2-0 | B3-0 | | B1-1 | B2-2 | B3-3 | ------------------------- を | key1 | key2 | key3 | ------------------------- | A1-0 | A2-0 | A3-0 | | A1-1 | A2-2 | A3-3 | | B1-0 | B2-0 | B3-0 | | B1-1 | B2-2 | B3-3 | ------------------------- のようにする感じです。 SQLite ver2.8を使っています。
UNION ALLを使います。
644 :
462 :2009/01/31(土) 04:30:25 ID:???
>>642 tableA
| key1 | key2 | key3 |
-------------------------
| A1-0 | A2-0 | A3-0 |
| A1-1 | A2-2 | A3-3 |
-------------------------
tableB
| key1 | key2 | key3 |
-------------------------
| B1-0 | B2-0 | B3-0 |
| B1-1 | B2-2 | B3-3 |
-------------------------
を
| key1 | key2 | key3 |
-------------------------
| A1-0 | A2-0 | A3-0 |
| A1-1 | A2-2 | A3-3 |
| B1-0 | B2-0 | B3-0 |
| B1-1 | B2-2 | B3-3 |
-------------------------
UNION ALLを使うじゃないですか
でっ、key1のにパラメータをつけたいんですけど hoge.php?key1=A1-0みたいな感じに
結合したテーブルはパラメータをつけれないんでしょうか?
誰かーエスパーの人つれてきてー
なんだ、ほったらかしにされてたんだw
>>645 パラメータをつけるって、条件指定したいって事?それならできるよ。
hoge.php?ってなんのかわけわからんけど。
phpにコードを渡す時の、URL入力イメージ
となるとスレ違いだからよそ行って
教えて下さい SQL 2005です ■小遣いもらったtable 人ID もらった日付 もらった額 ■小遣い使ったtable 人ID 使った日付 使った額 があったとき、 人ID 今月もらった額合計 今月使った額合計 今年もらった額合計 今年使った額合計 みたいに、日付ごとの集計データを、横にならべて出力するには、どのように記述するが一番処理が速いかな? 集計したい期間は固定とします。
>>647 レスありがとうございます。
条件指定だとどうなるのでしょうか? 教えていただけますか?
>>651 select * from (ここにunion句) where key1=A1-0
ありがとうございます
>>650 2、3パターンぐらいはクエリ思いつくだろうから
それぞれで実行計画を比較するなり、
実行計画の中身見てボトルネック潰すなりすれば良いじゃない。
>>650 SQL 2005なんて名称のRDBはないよ。
MS SQLのことなんだろうけど正確に使おうよ。
質問に関してだけど、どうのように書くかわからないのではなくて、どのように書いたら一番処理が速いかってことなら
あなたが考えたSQLを書いてみせて。
それより速いと思うものを書くからさ。
>>655 一番処理が早いかな?
〜〜とします。
とか上から目線できてるけど,一行目に「教えてください」ってあるから
なんにも知らない宿題暴威じゃまいか?
>>650 実際の件数とか、キーやインデックスの有無によって変わったりするし、
今のデータベースは、SQLを書いたとおりに実行されるとは限らない
まあ、早いのは集計済みのデータを持つテーブルを作って、
もらったtableと使ったtableのトリガで更新させるのが早いんじゃね
>>655 MS SQLなんていう名称のRDBもないと思うがな
他人に正確に使えっていう前に自分が正確に使わないと
説得力がないぞ
>>657 Microsoft SQL Server (マイクロソフト エスキューエル サーバ)とは、マイクロソフトが開発している、リレーショナルデータベース管理システム (RDBMS)である。略称は「SQL Server」または「MS SQL」などと呼ばれている。
しらねえなら黙ってろ
>>658 > 略称は
なんでここスルーしてしまうん?
略称OKになったらうちではSQLって略してる、がまかりとおってしまうじゃないか
>略称は「SQL Server」 おまえはここスルーしてるんだろ? Microsoft SQL Serverって言ってんの? SQLは略称じゃねえだろ? 読解力あるの?
>>654-656 ありがとう
>それぞれで実行計画を比較するなり実行計画の中身見てボトルネック潰すなりすれば良いじゃない。
知っておくべき定石や無難な方法、自分の知らない方法があるんじゃないかと思って。
端的にいうと、ああいう集計を速く行う場合、みんなはどういう記述をするのかを知りたかったってことですね。
>SQL 2005なんて名称のRDBはないよ。
すまなかったSQL Server 2005だね
>あなたが考えたSQLを書いてみせて。それより速いと思うものを書くからさ。
了解。自分で思った奴を書いてみるので、それぞれこれは止めた方がいいとか、
こういうのは好みじゃないとか、他にもこういうやり方があるとかあったら教えて欲しい。
→SELECT HitoID,
(SELECT SUM(MorauGaku) AS MorauGaku FROM Morau WHERE (HitoID = HitoMaster.HitoID) AND (MorauDateTime >= @DateTime1)) AS KongetsuMorauGaku,
(SELECT SUM(MorauGaku) AS MorauGaku FROM Morau WHERE (HitoID = HitoMaster.HitoID) AND (MorauDateTime >= @DateTime2)) AS KotoshiMorauGaku
FROM HitoMaster
→SELECT HitoMaster.HitoID, KongetsuMorau.KongetsuMorauGaku, KotoshiMorau.KotoshiMorauGaku FROM HitoMaster LEFT OUTER JOIN (SELECT SUM(MorauGaku) AS KongetsuMorauGaku, HitoID FROM Morau WHERE (MorauDateTime >= @DateTime1) GROUP BY HitoID) AS KongetsuMorau ON KongetsuMorau.HitoID = HitoMaster.HitoID LEFT OUTER JOIN (SELECT SUM(MorauGaku) AS KotoshiMorauGaku, HitoID FROM Morau AS Morau_1 WHERE (MorauDateTime >= @DateTime2) GROUP BY HitoID) AS KotoshiMorau ON KotoshiMorau.HitoID = HitoMaster.HitoID →SELECT HitoMaster.HitoID, SUM(UNIONTABLE.KongetsuMorauGaku) AS KongetsuMorauGaku, SUM(UnionTable.KotoshiMorauGaku) AS KotoshiMorauGaku FROM HitoMaster LEFT OUTER JOIN ( SELECT HitoID, MorauGaku AS KongetsuMorauGaku, 0 AS KotoshiMorauGaku FROM Morau WHERE (MorauDateTime >= @DateTime1) UNION ALL SELECT HitoID, 0 AS KongetsuMorauGaku, MorauGaku AS KotoshiMorauGaku FROM Morau AS Morau_1 WHERE (MorauDateTime >= @DateTime2) ) AS UnionTable ON UnionTable .HitoID = HitoMaster.HitoID GROUP BY HitoMaster.HitoID →SELECT HitoMaster.HitoID, CaseTable.KongetsuMorauGaku, CaseTable.KotoshiMorauGaku FROM HitoMaster LEFT OUTER JOIN (SELECT HitoID, SUM(CASE WHEN MorauDateTIme >= CAST(@DateTime1 AS DateTime) THEN MorauGaku ELSE 0 END) AS KongetsuMorauGaku, SUM(CASE WHEN MorauDateTIme >= CAST(@DateTime2 AS DateTime) THEN MorauGaku ELSE 0 END) AS KotoshiMorauGaku FROM Morau WHERE (MorauDateTime >= @DateTime2) GROUP BY HitoID) AS CaseTable ON CaseTable.HitoID = HitoMaster.HitoID
テーブルを HitoMaster→HitoID HitoName Morau→MorauID HitoID MorauDateTime MorauGaku として、 HitoID 今月(@DateTime1)のもらった額、今年(@DateTime2)もらった額を表示するように記述してみた。 (使う額については、同じクエリで表示可能なので、省いた) 簡単に思いついたのは、以上の4つぐらい。こういうのは良くないとか、定石的にはコレとか。 もっと言いやり方があるとかあったらお願いします。
>>660 ちげえちげえ。
MS SQLは略称であって正式名じゃない。
Microsoft SQL ServerをSQLと略す現場があるらしい。(このスレおよび過去スレ参照)
MS SQLという略称を許可するのであれば、SQLがそれを指している場合についても許可しなくてはならない。
SQLじゃどれのことかわからないが、MS SQLやSQL Serverは何を指しているかわかる つまりSQLだけはだめ
666 :
597 :2009/02/01(日) 16:26:34 ID:???
結論 MS SQL -> OK SQL -> NG 以下、この話題禁止
667 :
657 :2009/02/01(日) 16:27:25 ID:???
>>660 略称は、他人がきめて公開したものしかつかっちゃだめなのか?
SQLが略称じゃないというのはどういうことだ?
>>665 のように、その略し方では意味が取りにくいからその略し方を使うなという話なら
まだ賛同する点はあるが...
そういった略称をつかうことによる無用の混乱を避けるために、用語は正確に使えって
話だろうに
>>658 そんなふうに呼ばれていることぐらいは知ってるぞ。俺は略称を使うなとは言ってないし
俺はわかる程度に略すなら問題ないと思ってる
他人に、「正確に」使えと進めるなら、自分が「正確に」つかわないと、「説得力がない」と
言ってるだけだ。
と、ここまで書いて思ったが、655の言う「正確に」ってのは、正確に略せってことで、
SQL2005は正確な略じゃないが、MS SQLは正確な略だって主張か?
今頃気づいたの? 君だけだよ?わからなkったの
略称はいいから質問に答えてやれよ 罵りあいはするが質問には答えない無能かよ
>>661 MorauDateTime >= @DateTime1 は MorauDateTime >= @DateTime2 に
必ず含まれるわけだから、2回やる必要はないな。
これでいいんじゃね?
select HitoID,
sum(case when MorauDateTime >= @DateTime1 then MorauGaku else 0 end) as KongetsuMorauGaku,
sum(MorauGaku) as KotoshiMorauGaku
from HitoMaster
where MorauDateTime >= @DateTime2
group by HitoID
私ならviewを作る。 最低単位が月なら、人IDと月でgroup byさせるね。 使用区分みたいなカラムを作ってunion allね。
>>671 パフォーマンスの質問なのにView作ったって解決にならんだろ
Materialized Viewのことを言っているならはじめからそう書くべきだし
673 :
657 :2009/02/01(日) 18:38:47 ID:???
たしかにパフォーマンスの解決にはならんが、俺がやるとしても 年月別の合計金額をもったビューをつくるな。集計期間が固定なら で、パフォーマンス的に問題になるなら、インデックス張るとか 実表に作り変えてトリガで更新とかにする つか、パフォーマンス優先するなら集計表つくってトリガで更新しろっていう 俺の意見はまったく無視ですか(インデックス付ビューつくれるならそれでもいいけど) まあ、その4つで比べるなら実際に実行計画とってみればいいんじゃね うちの環境ではデータ0件で実行計画とってみたら、 4番目が一番早いという結果になった
>>672 まあそうなんだが実際はView作るだろ。
実用できないような架空のsql書いてもしょうがない。
Viewもそうだけど・・・ 借方、貸方フラグでも付けてテーブルまとめてしまいたくなるんだがw
676 :
NAME IS NULL :2009/02/01(日) 23:46:15 ID:uL0IgRTd
person_list テーブルは id | person_name 1 あまぼー 2 ういき 3 筋肉 4 うへへ 5 きゃべつ client_list id | client | person_id 1 トヨタ 1 2 日産 2 3 スズキ 3 4 ホンダ 4 5 日野 5 6 ダイハツ 6 上記の表だと トヨタには あまぼーさんが乗ってますが トヨタに あまぼーさんと うへへさんが乗ってたらどうすればいいのでしょうか? client_list のフィールドに person_id2 とか作ったら正規化されてませんよね?
677 :
NAME IS NULL :2009/02/01(日) 23:51:50 ID:uL0IgRTd
ちょっとスレミス 失礼
> トヨタに あまぼーさんと うへへさんが乗ってたらどうすればいいのでしょうか? 何でトヨタがメーカーじゃなくてクライアントなのかよくわからんけど、 client_list から person_id なくして、代わりに relation_table person_id | client_id 1 1 2 2 3 3 4 4 5 5 6 6 4 1 ってしとけばいいだけかと。
きゃべつが人の名前ってのもすごい
みんなありがとう
>>670 そうだね。今現在からみて、今年と今月なら、確かにそれでokですね。
ちなみにcase文を選択した理由がもしあったら教えてもらってもいいかな?
>>671-673 んーViewは結局、存在する月すべてで再計算することになるので遅くなるんじゃないかなと思って。
なら、ストアドかテーブル値関数を使うことになると思うんだけど、結局、
その中身(クエリ)が重要になると思うので、クエリをどう書くかという質問と同じになるので・・
>>673 >パフォーマンス優先するなら集計表つくってトリガで更新しろっていう俺の意見はまったく無視ですか
one fact in one placeの原則がありながら、その原則を排除してパフォーマンス重視のために
集計表を作る方法論は一応理解しているつもりなんだけど、
クエリの書き方としての方法論や、これはしてはいけないというような一般論があれば知りたかったので。
最初の質問の仕方が悪かったね。
>まあ、その4つで比べるなら実際に実行計画とってみればいいんじゃね
確かに、とにかく何でもいいから書いてみて速いのを選択すればいいというのも一つの方法だね。
他に速いクエリの書き方とかありそう?
>>655 >あなたが考えたSQLを書いてみせて。
>それより速いと思うものを書くからさ。
速いSQLまだー(・∀・ )っ/凵 ⌒☆チン
684 :
657 :2009/02/02(月) 03:58:01 ID:???
>680 >>Viewは結局、存在する月すべてで再計算することになるので遅くなるんじゃないかなと思って。 そんなことはない。今のDBMSにはオプティマイザってものがあってだな、 SQLで書いてある通りに実行されるとは限らないんだよ 存在する月すべてを計算するビューがあったとしても、実際に最終的にセレクトされる 結果に含まれないデータは集計しない。 仮に全データを集計したとしたら、それは全データ集計するほうが、 該当月かどうか判断してから集計するよりコストが低い(=早い)と判断された場合だ 俺はSQLを書くときは、まずわかりやすさを第1に考えて、 なるべく文が短くなるように書く。 集計のような、いろんなところで使う可能性があるならビューを定義する 速度を追及するためにトリッキーなSQL書くと、あとの保守で泣きを見るからな 先の4つの例なら、おれなら1番目だな
685 :
670 :2009/02/02(月) 06:43:55 ID:???
>>680 質問しておきながら何この上から目線w
caseを使う理由は
>>670 に書いた通り。
今月の分は今年の分のサブセットになるわけだから2回読む必要はない。
今年の分で取り出したデータからさらに必要な分だけを選択して使う。
まあ、
>>661 とかのSQLでもオプティマイザがうまいこと最適化して
1回読むだけにしてくれるかもしれんけど。
分かりやすさとパフォーマンスのバランスをとるっていう
>>684 の意見には同意。
どこまでを「分かりやすい」とするかは判断が分かれるところだと思うけど。
ちなみに、
>>650 の文章から「今現在からみて、今年と今月」以外の
どういう解釈があるのか逆に教えて欲しい。
指定した日付から見て今月、今年じゃなかったんだ? 今現在からだけでいいならパラメータもいらないように思う
687 :
NAME IS NULL :2009/02/02(月) 12:03:26 ID:m1gVv77i
load data infile で読み込む時に エスケープ処理も同時にやってくれるんですかね
No Name Shubetu 1 a inu 3 b inu 4 c neko 5 d inu 7 e tori 8 f tori 9 g inu という感じのテーブルから 1 a inu 3 b inu 4 NULL NULL 5 d inu 7 NULL NULL 8 NULL NULL 9 g inu という結果が出せるsqlを組みたいです。 つまり 全レコードのNoを取得 各NoのレコードがShubetu=inu なら各カラム出力、違えば、No以外をNULLに置き換えて出力する です。 postgresなんですが・・
select No, case Shubetu when 'inu' then Name else NULL end as Name, case Shubetu when 'inu' then Shubetu else NULL end as Shubetu from table1 とか
>>689 OracleならDECODE関数で、
inu以外の変数をすべてNULLにしてしまえる。
Nameも?
>>690 ありがとうございます
見事にできました。
これを利用してさらにやりたいことがあったのですが、うまくいかないので再度質問させてください
データはさきほどとは変えさせていただきます。
No Name Shubetu
1 inuinu inu
1 nekoneko neko
2 nekoZ neko
3 inuZ inu
このデータから
No inu_Name neko_Name
1 inuinu nekoneko
2 NULL nekoZ
3 inuZ NULL
というSelect結果を出したいです。
とりあえず
select No,
case Shubetu when 'inu' then Name else NULL end as inu_Name,
case Shubetu when 'inu' then Shubetu else NULL end as inu_Name ,
case Shubetu when 'neko' then Name else NULL end as neko_Name,
case Shubetu when 'neko' then Shubetu else NULL end as neko_Name
from table1 order by no
このようにしたまではよかったのですが、Noをユニークにし、Noが同じレコードをマージすることができません。
非常にわかりづらい日本語と思いますが・・・
もっと簡単に書ける。FULL OUTER JOINで調べてみて下さい。
>>695 テーブルが分かれてればjoinでいけそうなんですが、
同一テーブルでも使えるのでしょうか?
他にもNULLにしたいカラムがたくさんあるなら (select No from A) left join (select * from A where Shubetu = 'inu') using (No) みたいな感じでやるといいと思う
あらごめん。 リロードしてなかった。 別の要求がw それなら select * from (select No from table1) A left join select (No, Name as inu_Name from table1 where Shubetu = 'inu') B using (No) left join select (No, Name as neko_Name from table1 where Shubetu = 'neko') C using (No) という感じでできないですかね。 他にもいい方法がありそうにも思いつつ。
>>698 どうもありがとうございます。
select結果をAやBやCとしてテーブル名として定義できるわけですね?
ただ、このSqlそのままだと構文エラーが起きます
syntax error at or near "select" at character 51 としか出ないので
さっきJOINを知った自分としては何がいけないのやら・・
>>694 SELECT * FROM
(SELECT no,name AS inu_name FROM Table1 WHERE shubetu = 'inu') AS T1
FULL JOIN
(SELECT no,name as neko_name FROM Table1 WHERE shubetu='neko')AS T2
USING(no);
>>698 構文エラーは解決できました。
select * from
(select No from table1) A
left join (select No, Name as inu_Name from table1 where xx = 'inu') B using (No)
left join (select No, Name as neko_Name from table1 where xx = 'neko') C using (No)
だったみたいですね。
ただ、No=1が重複して出てるなぁと思ったら
>>700 これで完璧になりました。
一回ファイルに落として加工するしかないかなと思ってたんですが、結局SQL一発でできてしまうわけですね。
あとはもう、実データ用に調整するくらいです。
みなさんありがとうございました。
702 :
698 :2009/02/04(水) 02:46:26 ID:???
>>701 あらら。凡ミスごめんなさい><
1が重複する件は
(select distinct No from table1) A
とやると大丈夫に思いますが、
>>700 さんのがスマートだと思いますので、そちらでw
そもそもその一行はいらんだろ。 自己結合をもう一度最初から勉強してこい。
704 :
NAME IS NULL :2009/02/04(水) 09:34:46 ID:6r/uvBzP
testテーブルに 列no 列name 列tag 1 mixi 2ch 2 raku ja 3 2chan pic 4 yaho 2chan 5 2ch gif 6 goog 2chan があって select * from test where name = 2ch and tag = 2ch で検索します。 このとき並び順を 1・列nameに完全一致したレコード 2・列nameに一致したレコード 3・列tagに完全一致したレコード 4・列tagに一致したレコード 5 2ch gif 3 2chan pic 1 mixi 2ch 4 yaho 2chan 6 goog 2chan 2 raku ja このようにしたいのですが、どうすればいいですか?
>>704 SELECT * FROM test ORDER BY CASE
WHEN name='2ch' THEN 4
WHEN name LIKE '%2ch%' THEN 3
WHEN tag='2ch' THEN 2
WHEN tag LIKE '%2ch%' THEN 1
ELSE 0 END DESC;
706 :
がけっぷち :2009/02/04(水) 11:30:28 ID:YKEasflU
13時から試験なの? 丸暗記で単位とってもあなたのためにならないと思うな
708 :
がけっぷち :2009/02/04(水) 12:36:00 ID:YKEasflU
正直そのとうりなんですが、もう切羽詰まってるんです。お願いします。 13時からではないが覚えるにはそのくらいの時間にはできてないと・・・・13時半でも。
鹿児島大学 教育学部 数学科 磯川 研究室
練習問題IIIは付け焼刃じゃ無理だと思う。 過去問にもないし、ヤマを張るならここは丸ごと捨て。 練習問題IIの問題1 ・〜ごとに = GROUP BY 〜 ・売上 = SUM(単価*販売数) ・何列? = SELECT の項目数 ・何行? = GROUP BY 〜 は何種類? 問題2 ・WHEREのテーブル結合 … 別のテーブルで同じ列名を探す ・ORDER BY … 小さいほうから並べるならASC 大きいほうから並べるならDESC 問題3 ・表示させたい列を書く ・利用するテーブルをすべて書く ・同じ列をつなぐ ・科目の絞りこみ条件を書く ・成績の絞りこみ条件を書く 問題4 ・人の数 … COUNT(*) ・2つの質問に対するすべての組み合わせ … GROUP BY 質問A, 質問B これ以上はダメ 健闘は祈らない
711 :
がけっぷち :2009/02/04(水) 13:53:11 ID:YKEasflU
ありがとう。感謝します。問題4は答え教えてくれないですよね。・・・・・・ここまでの協力感謝
問題4はただ答えだけ聞いても理解できないんじゃない?
答えは教えないが解答案の添削ならするよ
>>713 多謝。練習問題IIIについて解答案を作ってみた。
#問題1
(設問1)
主キーはデータインスタンスをただ眺めて見つける物ではなく、
データが表現している対象の構造を鑑みて自ら定義するものだ。
この販売表を使っている部門がどういうビジネスしているか
記述もないのに主キーなんておいそれと決め打ちできるか。
(設問2)
主キーを関係従属性に言い換えて、設問1と以下同様。
#問題3
いや、だからどれが主キーなんだと・・・
コードとか番号って書いてあったら自動的に主キーなのか?
ユニークに振られていると解釈すれって暗黙の了解なのか?
#問題4
問題3と同様。社員番号に関する定義が無い。
#問題5
問題3に対するクレームに加えて、分割した各リレーションの
主キーも答えさせてくれないと、無意味。
#問題6
問題5と同様。
#総じて
もちっと厳密に問題作ってくれない?
誰もa1を選ばなかったら。。
>>714 おおむねダメだな。
> この販売表を使っている部門がどういうビジネスしているか
それが分かったら主キーが決まるという発想が既にずれている
> いや、だからどれが主キーなんだと・・・
主キーがどれであるかが最重要懸念事項ではない
後続も大抵ずれてるんだろうと思うので、採点するなら大きく×をつける。
>>714 はネタだよね?
それはともかく
売上日の列がない販売表ってすごく不思議だな
問1設問1でオ以外の誤答に×をつけるには
相当行間と空気を読む必要がある
> 主キーがどれであるかが最重要懸念事項ではない アとエの両方が可能だと思うのだが、複数回答可能なのかな。
>>717 まあ、
>>714 は即席のネタなんですが、正直良くない問題だなと
思ったので。
>> この販売表を使っている部門がどういうビジネスしているか
>それが分かったら主キーが決まるという発想が既にずれている
いや、それすら分からないと主キーは決められないでしょう。
要するに問いにちゃんと答えるには与えられた情報が少なすぎる。
>> いや、だからどれが主キーなんだと・・・
>主キーがどれであるかが最重要懸念事項ではない
重要度はともかく要検討事項です。
ISBNと著者コードがそれぞれ主キーだという制約がないとアとエは
常に実行可能、ウは選択肢の解釈次第だけど条件付き可能です。
あと参照の向きも示されていない。著者テーブル->書籍テーブルの
向きだったらイだって実行可能と解釈出来なくもない。
主に正規化に関する練習問題なのに、回答する上で考慮しなければ
ならない関数従属性が明確に示されていないのは困る。
設問中にも記述が殆どないし、設問中で示されたスキーマの中でも
主キー制約の形でそれが表現されているわけでもないし・・・
・・・空気なのか。やはり空気なのか。
空気が読めなくて落第しそうです。
ISBNは一般常識で主キーにしていいと思う ま、空気でなかったら講義中に補足があったのかもね 納得いかなかったら教授とっつかまえて問い詰めればいいんじゃない?
>>720 主キーかどうかじゃなくてユニーク制約がついてるかどうかが大事なんじゃないの
主キー制約ではなくユニーク制約にするとNULLも考慮する必要が 出てきて、場合によっては問題が面倒くさくなるので。 出題者側としてはシンプルに答えさせるのであれば主キー制約を 明示しておくのが適切なのでは。
数学科の先生でデータベースは専門じゃないんだろうけど、こりゃひどい。 設問3 ア 「同一のISBNを持つ異なる書籍」が存在するなら、単独の「ISBN番号」は主キーたりえない イ 書籍テーブルの「著者コード」がNULL可なら可能 ウ ON DELETE CASCADEなら... そもそも、「リレーションを付ける」って何だw
たとえば、以下の様なデータが有ったとして、 SQL> SELECT BASE FROM TABLE_A ; BASE ---------------- /home/user/dir SQL> SELECT SYS_DIR FROM TABLE_B ; SYS_DIR ---------------- system_dir SQLだけで、以下の様な結果を得ることは可能? /home/user/dir/system_dir
SQL> SELECT BASE FROM TABLE_A ; SQL> SELECT SYS_DIR FROM TABLE_B ;
>>721 同意。
XMLの例題で必ず本を扱った問題があり、だいたい一意のものとして許容されてる。
728 :
NAME IS NULL :2009/02/05(木) 13:51:40 ID:Xu5BDpbx
いくつかのカラムに対してフリーワード検索をかけようと思うんですけど どういう方法がいいでしょうかね。 2種類思いついて一つは単純に、サブクエリーを使って例えば SELECT * FROM shop WHERE (shop.name LIKE %hoge%) OR (shop.capiton LIKE %hoge%) OR (shop.id IN (SELECT shop_area.shop_id FROM shop_area WHERE shop_area.name LIKE %hoge%)) OR (shop.id IN (SELECT shop_category.shop_id FROM shop_category WHERE shop_category.name LIKE %hoge%)) ・ ・ とひたすら書いていく方法。 もう一つはSELECT結果をひたすらUNIONALLしたVIEWを作っておいてそこに検索書ける方法。 CREATE VIEW shop_keyword AS SELECT id AS shop_id, name AS keyword FROM shop UNION ALL SELECT id AS shop_id, caption AS keyword FROM shop UNION ALL SELECT id AS shop_id, name AS keyword FROM shop_area UNION ALL SELECT id AS shop_id, name AS keyword FROM shop_category 本当はareaとかcategoryは多対多なのでjoinが必要か・・・ まあ、そんな感じなんですけど。どっちがいいでしょうか。 また、こっちのほうがいいというのがあったらアドバイスください
普通にshopとshop_areaとshop_categoryをjoin。 WHEREにLIKE条件をORで繋いで列挙。 後はオプティマイザさんよろしく。 で良いかと。別にサブクエリーやビューを使う事はないと思う。
730 :
NAME IS NULL :2009/02/05(木) 16:21:38 ID:Xu5BDpbx
レスありがとうございます shop_areaとshop_categoryはshopと多対多なのでJOINすると同じshopが複数行帰ってきちゃうので SELECT shop.* FROM shop WHERE shop.id IN (JOINしたSELECTのサブクエリー); か SELECT DINSTINCT shop.* JOIN ~ JOIN ~ WHERE ~~~~~ って感じですかね?
VIEWの利点って何ですか?
テーブル作らなくていい
>>731 好きな列や行だけを表(テーブル)として保持できる。
>>731 こんなもんかな?
利点:
・クエリが(一見)単純になる
・あらかじめパフォーマンスチューニングしたVIEWを定義することで
あとから書くクエリではパフォーマンスを考慮しなくて良くなる(場合がある)
・行や列ごとにセキュリティかけたい場合に使えたりする
欠点:
・あとからロジックを追うのが面倒(な場合がある)
・あとからパフォーマンスチューニングするのが面倒(な場合がある)
DBMSによっては実体を持つビューも作れるので、パフォーマンスに優れることも。
736 :
NAME IS NULL :2009/02/05(木) 23:33:28 ID:SoIM2kj6
下記のようにgroup by の条件が可変でかつDBに持っている場合で 以下のような結果を一回のSQLで取得する方法をご教授下さい。 vbのスプレッドに表示することが目的です。 宜しくお願いします・ 結果 部署 等級/号俸 金額 0001 10 11000 0001 9 90000 0002 3 300 0002 2 4000 社員マスター 部署 社員コード 等級 号俸 金額 0001 000001 10 5 10000 0001 000002 9 5 90000 0001 000003 10 4 1000 0002 000004 4 3 300 0002 000005 4 2 4000 グループ化マスター 0001 等級 0002 号俸
VBのコードも書いてみ。
2つのテーブル結合の例は多いですが 3つのテーブル結合ってのはあまりよろしくないんでしょうか?
なじぇに?
例を挙げるのに2テーブルで事足りただけでいくつ結合しても問題ないよ
>>736 部署, 等級, sum(金額) where 部署 in (グループ化マスターで「等級」になってる部署) group by 部署, 等級
union
部署, 号俸, sum(金額) where 部署 in (グループ化マスターで「号俸」になってる部署) group by 部署, 号俸
ってこと?
DELETE 社員マスター WHERE 金額 > 1000
PDO使うときって、ロックって概念はないの?
あるよ
>>744 トランザクションを発行すると、自動的にロックになるんではないの?
それとも、トランザクションをして、なおかつ、自分でまたロックもするの?
>>740 ありがとうございます。
3つのテーブルをJOIN結合させたいのですが、例を書いていただけませんでしょうか?
ぐぐれよ
Aテーブル Dテーブル id name u_id id f_id 1 あああ 1 1 2 2 いいい 4 2 4 3 るん。 5 3 1 Bテーブル f_id f_name 1 じゃがりこ 2 グリコ 3 あめちゃん 4 かとちゃんぺっ Cテーブル u_id u_name 1 丸丸 2 燃えも絵 3 うおおおお 4 厚い 5 さんま この結合お願いします。
>>748 select *
from Dテーブル
inner join
Aテーブル
using (id)
Cテーブル
using (u_id)
inner join
Bテーブル
using (f_id)
>>749 ありがとうございます。
けどエラーが出ます。。
>>750 Cテーブルの前にinner joinが抜けている
usingが使えなきゃon
てかエラー内容ぐらい書いたらどうなんだ?
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'id inner join Cテーブル u_id inner join Bテーブル using f_id' よろしくお願いします
MySQLのバージョンも書いておいた方がよいかも。
JOINだ何だというテーブル結合式にどうしても馴染めなくて 常にFROM句にテーブル名列挙+WHERE句に結合条件列挙 なのですが、この先何か困る事はあるでしょうか。
>>753 お手数お掛けして申し訳ないです
MYSQL 5.1.30
既に読み辛いだろう
そうですか〜 選択リストはカラム参照だけ。 FROM句はテーブル列挙だけ。 WHERE句は条件式列挙だけ。 綺麗に棲み分けて案外読みやすいと思うのですが。
SELECT句で射影 FROM句で結合 WHERE句で選択 と考えるとFROM句で結合するほうがむしろ自然な希ガス それとWHERE句だと外部結合するやりかたはDBMSごとに違うような
759 :
NAME IS NULL :2009/02/07(土) 16:00:02 ID:MqS7b1Xj
現在 Mysql で、以下のようなSQLを行っております。 CREATE VIEW tmp_db AS SELECT 顧客名,商品名,限度個数,購入数,購入数/限度個数 * 100 AS 利用率 FROM 顧客.顧客リスト INNER JOIN 売買.購入 USING(顧客名); SELECT 顧客名,限度個数,購入数,利用率 FROM tmp_db WHERE 利用率 >=90; DROP VIEW tmp_db; これを CREATE VIEW を使わずに一回で結果が返ってくるSQL文って可能でしょうか? 良い方法が思いつかないのでどなたかお教えいただけると幸いです。
age てしまった。 申し訳ない。
>>758 結合も所詮直積+制約なので、制約条件がWHERE句にあったり
FROM句の中にあったり省略されてたりするのが何とも。
SELECT句で射影
FROM句で直積
WHERE句で制約
で良いではないですか。
確かに外部結合ぐらいかなぁ。
>>759 where 購入数/限度個数 * 100 >= 90
ってやったら?
>>761 結合を直積+制約と考えるのは微妙だな
select * from Table1 A, Table2 B where A.ID = B.ID or A.ID is null
で外部結合できるかというとそうでもない
>>762 ありがとう。
where をくっつけるだけでOKでした。
>>763 すみません。内部結合の事ですね>直積+制約。
確かに外部結合はテーブル結合式使わないと書くのも面倒だし
多分遅いです。
・DBとバージョン MySQL 【エリア情報】という名前のテーブルがあります。 【エリア情報】 住所ID 郵便番号 都道府県名 市区郡町村 大字・町名 ------------------------------------------------------- 08201001000 310-0004 茨城県 水戸市 青柳町 08201002001 311-4141 茨城県 水戸市 赤塚 08201003000 310-0822 茨城県 水戸市 圷大野 : : : そこの新たに【住所】という名前のテーブルを作ることになりました。 CREATE TABLE 住所( 郵便番号 CHAR(8), 住所 VARCHAR(64) ); 【エリア情報】のデータを【住所】に入れたいと思い、以下のようなSQL文を作成しました。 INSERT INTO 住所 SELECT 郵便番号, 都道府県名 & 市区郡町村 & 大字・町名 FROM エリア情報; しかしそれだとエラーが出て正常にINSERTされません。 上手くINSERT処理が走るようにするにはどうすればよいのでしょうか?
>INSERT INTO 住所 >SELECT 郵便番号, 都道府県名 & 市区郡町村 & 大字・町名 >FROM エリア情報; INSERT INTO 住所 SELECT 郵便番号, 都道府県名 || 市区郡町村 || 大字・町名 FROM エリア情報;
768 :
519 :2009/02/08(日) 12:15:46 ID:???
【顧客データ】 日付1 日付2 名前 -------------------------------- 2009/01/01 2009/02/14 鈴木君 2009/01/15 2009/03/14 山田君 2009/02/01 2009/01/03 太朗君 こういうテーブルがあって、 SELECT 日付1, 名前 FROM 顧客データ ORDER BY 日付1 で日付1順に取り出す事はできるんですが、 日付1と日付2を別々の行で抽出したい場合は、別々のクエリーでやらないと無理ですか? 例えば上のテーブルから下記のように取り出したいです 日付 名前 -------------------------------- 2009/01/01 鈴木君 2009/01/03 太朗君 2009/01/15 山田君 2009/02/01 太朗君 2009/02/14 鈴木君 2009/03/14 山田君
Union
>>768 SELECT 日付1 AS 日付,名前 FROM 顧客データ
UNION ALL
SELECR 日付2 AS 日付,名前 FROM 顧客データ
ORDER BY 日付;
771 :
766 :2009/02/08(日) 12:58:23 ID:???
>>767 INSERT INTO 住所
SELECT 郵便番号, 都道府県名 || 市区郡町村 || 大字・町名
FROM エリア情報;
でも上手くいかなかったのですが、下のようにインサート先の項目を記入すれば上手くいきました。
INSERT INTO 住所(郵便番号, 住所)
SELECT 郵便番号, 都道府県名 || 市区郡町村 || 大字・町名
FROM エリア情報;
本当にありがとうございました。
わざわざ二重管理するってのは意味不明だけどね
後半のSELECT文でVIEW作ればいいよな
774 :
519 :2009/02/08(日) 20:28:12 ID:???
>>769-770 なんという魔法のクエリー
うまくいきました!ありがとうございますm(_ _)m
これwhere句は両方いるんだろうか・・色々試してみるか・・
UNION ALLが何を意味するかを考えればいるに決まってる
776 :
NAME IS NULL :2009/02/10(火) 10:12:10 ID:Jmz8XJsn
・DBMS名とバージョン Microsoft SQLServer 2005 ・テーブルデータ マスタ Code | Value ------+------- 0001 | abc 0002 | def データテーブル Code ---------------- 0001,0002 0001 ・欲しい結果 名称 ------------------ abc,def ・説明 データテーブルの中に、コードがカンマ区切りで入っています。 データテーブルに入っているコードを値に置き換えて、 カンマ区切りで出力したいのですが、この様なことはできますか?
ストアドプロシージャーでFOR文を使って、 SELECT Value_temp1 || ', ' || Value_temp2 FROM マスタ とかどうでしょう。
oh mygod oh my sql だな
780 :
もぐもぐ :2009/02/10(火) 19:38:22 ID:z9aBrXD5
商品テーブル t_shohin の ID=1 の商品の在庫が 10個あるとします。 今、次の2つのプログラムを同時に実行したとします。 このとき、どのような実行順序であっても、最終的に在庫は 9 個になりますか? プログラムA: BEGIN; UPDATE t_shohin SET zaiko = zaiko - 1 WHERE id = 1; COMMIT; プログラムB: BEGIN; UPDATE t_shohin SET zaiko = zaiko - 1 WHERE id = 1; ROLLBACK;
>>780 トランザクションの分離レベルをDirty Read(Uncommitted Read)にしてない限りそうなる
銀行系の例題で必ず出るよね、そういう話題。
PHP + PDO + SQLite3で銀行システム組んでるんだけど、 AとBって2人がいたとして、 Aの講座に10万円 Bの講座に0万円入っているとする そんで、AがBの口座から1万円引き落とそうとするんだけど、 つまり、Bの口座からAの口座に1万円移動させるんだけど、 このとき、当然Bの口座に少なくとも1万円以上入っていなければ ならないわけだ。 で、if B >=1 ってチェックをかけて、それで「OK」って出たら、そこではじめて Bの口座の数字を1減らす、って作業をするんだけど、このif文って PHP側で調べるものなの? それとも、SQL文で、データーベースの内部で調べるものなの?
どっちでも。 SQL に関係ないからスレ違いだな。
データーベース内部で 「1より多いか?少ないか?」 を判別するのはどうやるの?
>>783 DB 側でのチェックは必須
1) if B >=1ってチェックをかけて、それで「OK」って出たら、
2) そこではじめてBの口座の数字を1減らす、
1) と 2) の間に B が1万円引き出すこともあるから PHP だけの
チェックだとダメ。
PHP 側でもやるかどうかは組み方次第だけど、個人的には
>>784 の
言うように両方でやるというケースが多いように思う。
# て言うか、その銀行って1万円単位なのか!?
>>786 (1)PHP側でif B >=1ってチェックをかける
(2)「OK」って出る
(3)Bのバカ野郎がタイミング悪く、自分で1万円引き出し口座の残高が0になる
(4)Bの口座から1万円減らす(残高はマイナス1万円)
こういう状況を懸念しているわけですね?
でもそのためにトランザクションというものがあるのではないですか?
つまり、(1)から(4)までの間にトランザクションで
防御しておけば、(3)の割り込みは発生しないですよね?
それと、データーベース側で、 Bの口座の残高が1万円以上あるのかないのか、 調べるのはどうしたらいいですか? なんかそれらしき命令が見当たらないのですが。 SQLにif文って、あるのですか?
ちなみにゲームの中の銀行といえども、 実際の運用は本物の銀行と大差ありません。 現在の銀行はほとんどのお金が データーベース上の数字として存在しているだけです。 紙幣の受け入れとか硬貨の払い出しとかが ないだけで、それ以外は基本、全部同じと思っていいでしょう。
更新ロックかけてupdate文にwhereすればいいんでないか
また荒らしか・・・
>792に書いてあることが理解できないなら、そんなシステム捨てましょう。 >786,788での重要なポイントも理解できてないでしょ、あなた。
PHPでsqlite3の データーベースをロックするには どうしたらいいんだ?
SQLで、データーが1以上かどうか、って 判別するのって無理じゃないか?
(0)トランザクション開始 (1)SELECTでデーターを取ってくる (2)1より小さいか、if文で確認 (3)もし1より小さかったら、「残高が足りません」と表示 (4)ロールバック (5)もし1以上だったら、 (6)マイナス1するUPDATE文を発行 (7)コミット文を発行して確定 ↑これでいいんじゃない?
(6)マイナス1するUPDATE文を発行 ここのときに、 WHERE a>=1 という、条件を付け加えろ、という意味なのかもしれないが、 それって意味のない動作だよね。 だって、もし1より小さい場合はどうするの? なにも起きない、という動作になるよね。 それだと困るんです。ちゃんとエラーを出して もらわないと。
800 :
NAME IS NULL :2009/02/11(水) 01:49:45 ID:Xh0+aF+a
SELECT model, name FROM sampletable WHERE model="45" and name="△△" とかの検索をよくする場合 modelとnameをそれぞれINDEXにすることによって最適化されるのでしょうか?
>>799 (5)で1以上だったらという前提で処理を進めている中で、1以下だったらどうすんだと言われてもね。
>>800 場合にもよるが、複数列インデックスを作った方がいい。
ex.) CREATE INDEX new_idx ON sampletable (model, name);
素人だけど WHERE model="45" and name="△△" なら個別のインデックスでも使用されなかったっけ?
残念ながらどちらか片方だけだね
そうなんだ。インデックス張る順番は関係あるの?
805 :
NAME IS NULL :2009/02/11(水) 06:51:19 ID:r3GS0TFZ
SELECT *,id,max('id') as max FROM T_TABLE 名称について教えて下さい。 上のような文の場合、「*,id,max('id') as max」 の部分は一般的になんと呼べばいいでしょうか? カラムとは違いますよね?
>>788 トランザクションといっても、RepeatableRead以上である必要がある。念のため。
>>804 張る順番は関係ないよ。
古いDBならWHERE句の書く順番に関係があったが、
今時のならプランナやオプチマイザが摘便に判断する。
>>807 トランザクションにもレベルがあるんだ?
>>808 なるほど
張る順番はLIKE検索の時の関係してくるんだっけか。
それよりwhere句で条件を2つ以上使うとインデックス使われないというのは知らんかった。
どこか詳細なサイトとかある?
大抵のクエリは複数条件だろうから単一インデックスじゃほとんど意味ないのね。
そんなのエンジンの実装次第だろよ・・・
813 :
NAME IS NULL :2009/02/11(水) 18:14:13 ID:fk2Zdes0
・DBMS名とバージョン: SQLite3 ・テーブルデータ 【マスタテーブル】(idが主キー) id name kana publication # Catalog // 同人誌マスタ --------------------------- # publicationはEvent(id)を参照 01 AAAA aaaa 02 02 BBBB bbbb 02 id circle kana ext comment # Circle // サークルマスタ ------------------------------ # UNIQUE(circle,ext) 01 ・・・・・・ ・・・・ ・・・ ・・・・ 02 ・・・・・・ ・・・・ ・・・ ・・・・ id title # Title // 原作マスタ --------- # UNIQUE(title) 01 ・・・・・ 02 ・・・・・ id attribute # Attribute // 属性マスタ ------------- # UNIQUE(attribute) 01 ・・・・・ 02 ・・・・・ id event year month day place host # Event // イベントマスタ ---------------------------------------- # UNIQUE(event,year,month,day) 01 ・・・・・ ・・・・ ・・・・・ ・・・ ・・・・・ ・・・・ 02 ・・・・・ ・・・・ ・・・・・ ・・・ ・・・・・ ・・・・ 【1:N関係テーブル】 id author kana # Author // 作家リレーション ---------------- # UNIQUE(id,author),idはCatalog(id)を参照 01 ・・・・・ ・・・・ 02 ・・・・・ ・・・・ 02 ・・・・・ ・・・・ 【N:N関係テーブル】 id cid # Publisher // サークルリレーション ------- # UNIQUE(id,cid),idはCatalog(id)を参照,cidはCircle(id)を参照 01 01 02 01 id tid # Original // 原作リレーション ------- # UNIQUE(id,tid),idはCatalog(id)を参照,tidはTitle(id)を参照 01 01 01 02 02 02 id aid # Property // 属性リレーション ------- # UNIQUE(id,aid),idはCatalog(id)を参照,aidはAttribute(id)を参照 02 01 02 02 (本文が長すぎます&改行が多すぎますと怒られたので一旦区切ります)
814 :
NAME IS NULL :2009/02/11(水) 18:17:18 ID:fk2Zdes0
・欲しい結果 (カラムa) (カラムb) (カラムc) (カラムd) ------------------------------------------- ・・・・・・・・・ ・・・・・・・・ ・・・・・・・ ・・・・・・・・ ・・・・・・・・・ ・・・・・・・・ ・・・・・・・ ・・・・・・・・ ・説明 全てのテーブルを結合したうえで,求めたいカラムと検索キーを指定し,一致したレコードのみを作業テーブルに抽出する リレーション関係図 Catalog.publication <-> Event.id Catalog.id <-> Author.id Catalog.id <-> Publisher.id <-> Publisher.cid <-> Circle.id Catalog.id <-> Original.id <-> Original.tid <-> Title.id Catalog.id <-> Property.id <-> Property.aid <-> Attribute.id SELECT文 CREATE TEMP TABLE 作業テーブル名 AS SELECT DISTINCT 求めたいカラム名のリスト FROM Catalog LEFT OUTER JOIN Event ON Catalog.publication=Event.id LEFT OUTER JOIN ( SELECT id AS written, author, kana AS author_kana FROM Author ) ON Catalog.id=written LEFT OUTER JOIN ( SELECT P.cid AS publisher, C.circle, C.kana AS circle_kana, C.ext AS circle_ext, C.comment AS circle_comment FROM Publisher P LEFT OUTER JOIN Circle C ON P.cid=C.id ) On Catalog.id=publisher LEFT OUTER JOIN ( SELECT Original.tid AS original, Title.title FROM Original LEFT OUTER JOIN Title ON Original.tid=Title.id ) ON Catalog.id=original LEFT OUTER JOIN ( SELECT Property.aid AS property, Attribute.attribute FROM Property LEFT OUTER JOIN Attribute ON Property.aid=Attribute.id ) ON Catalog.id=property WHERE 検索条件 ORDER BY Catalog.id ASC カラム名のリストを「Catalog.id,name,kana」や「original,title」のように, 1つのマスタテーブルのカラムのみを指定した場合は上手くいくのですが, 「Catalog.id,name,publisher,circle」のように複数のテーブルをまたいだ検索で望んだ結果が出ません. 上の場合だと Catalog.id name publisher circle ----------------------------------- 01 aaaa 01 hoge 02 bbbb 02 foo 03 cccc 01 hoge 03 cccc 03 orz 04 dddd 02 foo という結果が欲しいのに Catalog.id name publisher circle ----------------------------------- 01 aaaa 01 hoge 02 bbbb 02 foo 03 cccc 03 orz 04 dddd NULL NULL となってしまいます. 結合が上手くいっていないような感じなのですが、どうでしょうか? #テーブル毎に検索してから結果を結合というのはナシの方向でお願いします.
ナゲー
・とりあえず外部結合が必要な要件が見つからない。 全部INNER JOINに書き換えて要観察。 ・CREATE TABLEでデータ突っ込むのにORDER BYは 無意味だし誤解の元なので止めておけ。 ORDER BYは後でテーブルから実際にデータを検索 するときに明示的に指定すること。
ごめんなさい。
>>816 はかなり外したこと言っていた。
原作無しや属性無しの同人誌もあるわけだよね。
rollback!
818 :
813 :2009/02/11(水) 21:20:57 ID:fk2Zdes0
自己解決しました。 マスタテーブルとN:Nテーブルの結合時にONで指定するカラムが間違っていました・・・ (例えば同人誌マスタとサークルマスタの結合時に「Catalog.id=Publisher.id」とするべきところを 「Catalog.id=Publisher.cid」としていたことが原因でした。)
もしかして、tableって名前のテーブルは作れない? なんかSQLがエラーになるんだけど。
820 :
813 :2009/02/11(水) 21:50:41 ID:fk2Zdes0
>>816 CREATE TABLEでORDER BYしたのは、作業テーブルに同人誌IDが無い場合はソートできないので
作成してインサート処理だけならSELECTの結果も挿入順にならないかなぁ・・・
なんて希望的観測で書いただけです
「SELECT 求めたいカラム名のリスト, Catalog.id AS sort_id」とソート用のカラムを追加した場合
「求めたいカラム名のリスト」が全てNULLのレコードが出てきてしまったので。
NULLを除外するにはWHEREで「求めたいカラム名のリスト」それぞれに対し
NOT NULLでチェックするしか方法はありませんか?
821 :
NAME IS NULL :2009/02/11(水) 21:57:49 ID:Oyh9T5ug
>>819 予約語なので普通はできない。
処理系によっては
"table" とか [table] とか書けば可能なものもある。
>>819 作れたとしても、誤解の元だからユニークな名前を付けましょう。
>>776 WITH CTE AS (
SELECT
'0001,0002,0003' AS ides,
CHARINDEX(',', '0001,0002,0003') AS comma_index,
CAST('' AS varchar) AS foo
UNION ALL
SELECT
SUBSTRING(ides, comma_index + 1, LEN(ides)) ides,
CHARINDEX(',', ides) AS comma_index,
CAST(foo + ',' +
CASE SUBSTRING(ides, 0, comma_index)
WHEN '0001' THEN 'もうね'
WHEN '0002' THEN 'アボガド'
WHEN '0003' THEN 'バナナかと'
END AS varchar) AS foo
FROM CTE
WHERE LEN(ides) > 0
)
SELECT
ides, comma_index, SUBSTRING(foo, 2, LEN(foo))
FROM
CTE
ストアドでなくてもやれる。非常にアレだがw
>>808 ・ID
・年度ID
・期間ID
・ユーザID
・値
な感じで、IDにPK、各3IDにINDEXを張ってるんだけど、
where 年度ID = x AND 期間ID = y AND ユーザID = z
と検索するとINDEX使われないの?
実際はその3つで一意に決まるからIDやめて年度と期間とユーザでPKにしたほうがいいのかな?
>>810 LIKEでもインデックスを張る(CREATE INDEX)順番は関係ないと思うがな。
>>824 DBも日々進化しているし、俺が気づいてないだけかもしれんが、
そのWHERE句の中で、一番絞り込み安いIDをINDEX検索して、
他のIDでフィルタを掛ける感じになる。
どのIDでINDEX検索するかは、プランナが判断する。
3IDで一意になるなら、ユニークインデックスを作っていた方がいいと思う。
っていうかさ、SELECT文がどのように実行されるか、クエリープランを出力してみりゃわかるでしょ。
例えばPostgreSQLならEXPLAIN文がそう。
DB2にもそういうコマンドあるよ。
CREATE TABLE m_arrange( name char(6) NOT NULL, priority int NOT NULL, attr int NOT NULL, PRIMARY KEY(name, priority, attr) ); PRIORITYには正の整数、ATTRには0〜2の整数が入る。 全てのカラムを抽出するが、下記の条件で行を絞り込みたい。 ・nameは重複してはいけない。する場合は下記の順に並び替え先頭に来たもののみ絞り込む。 ・ATTRが1のものが最優先、次に0、最後に2。 ・priorityが高いもの。 DBMSはMySQL5.0.67です。 お願いします。
宿題をやらせるなら、せめて文言をそれらしく変えなよ…
こういう primary key の設定って、うっかり duplicate key になったりしないものなんだろうか。
>>827 ヒント:order byにcase式を使う
case文なんか使う必要ないだろ
boolでソートできるからね
>>827 GROUP BY 絡みがMySQL専用で、
SELECT * FROM (SELECT * FROM m_arrange ORDER BY name,CASE WHEN attr=1 THEN 'A' WHEN attr=0 THEN 'B' ELSE 'C' END,priority DESC) AS T1 GROUP BY name;
>>833 つFIELD(attr, 1, 0, 2)
てかbooldでソートというのは意図がよく分からんがどういうこと?
835 :
827 :2009/02/13(金) 17:26:01 ID:???
GROUP BYでどれを取り出すかってサブクエリのORDER BYで制御できるんですね ありがとうございます!
836 :
NAME IS NULL :2009/02/13(金) 19:43:39 ID:aq0eggL/
部門(departments)と従業員(employees)が 1 : N の関係のとき、 従業員をひとつも持たない部署の一覧を得るための select 文はどうなりますか。 select departments.id, count(employees.id) count from departments, employees where departments.id = employees.department_id とやると、部門と従業員数は出てくるのですが、そこから先がわかりません。 よろしくお願いします。
not in でいいじゃん。
not existsだろ普通
select id from departmetns where id not in (select department_id from employees)
サンプルDBレベルじゃ違いが分からんだろうが
実環境で
>>840 なんかやったらとんでもなく遅い
社員数千人レベルなら余裕だなw
ま、それはそれとして、速いクエリがあるなら教えてやれよ。
俺はわからんから
>>840 でいいけど。
>>837-841 どうもありがとうございます。
not exits と not in のどちらでもできることがわかりました。
select * from departments where not exists(select 'X' from employees where departments.id = employees.department_id);
select * from departments where id not in (select department_id from employees group by department_id);
>>841 そうなんですか。でもORMが対応してないような。
>>836 select id from departments
except
select distinct departments.id from employees
じゃだめかな。
>>841 前にも書いたが、今の(NOT) IN は速いよ。
>>840 なら
SELECT departments.id FROM (SELECT department_id FROM employees) AS T1
JOIN departments ON T1.department_id=departments.id;
と実行しているのじゃないかなと思ったり。
場合によっては、たとえインデックスを張っていても、毎行サブクエリが実行される
(NOT) EXISTS より速い場合がある。
>>844 老婆心だが、
(NOT) EXISTS のサブクエリでは SELECT リストを'X'とはせず * にして
DB(オプチマイザ)任せにした方がいい。
847 :
846 :2009/02/13(金) 22:23:56 ID:???
ゴメソ、
>>846 で上げたSQLは、NOTじゃないIN述語と同等のものになっていた。
( ;∀;) イイハナシダナー
850 :
NAME IS NULL :2009/02/14(土) 19:55:36 ID:hb0oePnz
>>850 宿題を手伝うのはどうかと思うが一応自分でも考えてるようなので
2は1のSQLのselect句に
case count(評価値) when 5 then '合格' else '不可' end
を追加
3は1のSQLに
having count(評価値) = 5
を追加
せっかく学校でDBを体系的に学べる機会をもったいねぇ
>>850 厳密に言うと、1も違う。同名の学生が居た場合困るがな。
1) SELECT 学生名 FROM 学生 JOIN (SELECT 学籍番号,sum(評価値) AS 合計 FROM 課題 GROUP BY 学籍番号)AS T1 USING (学籍番号) ORDER BY 合計 DESC;
2) SELECT 学生名,可否 FROM 学生 JOIN (SELECT 学籍番号,sum(評価値) AS 合計,CASE bool_and(提出状況) WHEN TRUE THEN '合格' ELSE '不可' END AS 可否 FROM 課題 GROUP BY 学籍番号)AS T1 USING (学籍番号) ORDER BY 合計 DESC;
3) 2がでれば簡単だろ。
>>851 count(評価値) は非NULLをカウントするので、常に5になるんじゃね。
854 :
853 :2009/02/14(土) 21:15:30 ID:???
補足 同名の学生が... って書いておきながら、学籍番号を出力しないのは片手落ちだったか。 と、PostgreSQLじゃなかったら bool_andはeveryでおね。
855 :
851 :2009/02/14(土) 21:29:10 ID:???
>>853 > count(評価値) は非NULLをカウントするので、常に5になるんじゃね。
未提出の場合評価値をNULLにする、もしくはレコードなし
となっていれば常に5にはならない。
てか所詮宿題レベルだし出題者の意図を満足させればいいかと。
2がcaseを使わせることを意図しているかどうかは微妙だけど、
3がhavingを意図しているとするとこれでいいと思う。
856 :
850 :2009/02/14(土) 21:30:58 ID:???
1と3は皆様のご意見から SELECT 学籍番号,sum(評価値) as 合計点 FROM 課題 group by 学籍番号 order by 合計点 desc; SELECT 学籍番号,sum(評価値) as 合計点 FROM 課題 where 提出状況 != 'FALSE' group by 学籍番号 having count(*)=5 order by 合計点 desc; のようにしました。 2は皆様のを参考にもう少し考えて理解したいと思います。 ありがとうございます<(_ _)>
>>851 課題テーブルが提出状況のboolean値を持っているので、可不可の判定
もこれを使うのが適当じゃないのかな。
相関サブクエリーで提出状況がtrueの数を数え上げるのが良いと思う。
858 :
853 :2009/02/14(土) 21:38:03 ID:???
>>855 スマソ、提出状況と評価値を混同してた。
>>856 学生名を出力しないのはどうかとおもうぞ。
859 :
850 :2009/02/14(土) 21:42:22 ID:???
課題のテーブルなども自分で考えて作ったので必要ない属性や 間違っているところもあるかもしれません;
こんどvistaのノートパソコンを買うつもりなんですが、 Common SQL Environment はvistaに対応されてないので使うことができないかもしれません。 使えなかったときのためにこれに代わるソフトウェアを教えてください。
861 :
853 :2009/02/14(土) 21:46:12 ID:???
>>857 俺も最初そう思った。でも、
>>851 の言うように提出状況は他のカラムから判断できるのよね。
課題が増えたりすると面倒だけどさ。
>>859 で課題テーブルは850が作ったって言ってるし。
どうみてもスレ違いだな・・・
>>861 う〜ん、問題に
「各課題のデータは学籍番号と提出の有無、および評価値を持つ」
と書いてあるので、提出状況カラムの存在はマストだと思った。
あと未提出の課題の得点をNULLにするのは運用として有りだけど、
それだと「未提出課題の得点はマイナス一万点!」なんてのたまう
お茶目な教官のリクエストに応えられない。
本当はこれぐらいに分けた方が良いのだけど。 学生マスタ (学籍番号, 学生氏名) PK: 学籍番号 課題マスタ (課題番号, 課題名) PK: 課題番号 配点マスタ (優良可, 得点) PK: 優良可 課題状況 (課題番号, 学籍番号, 提出状況, 優良可) PK: 課題番号, 学籍番号 FK: 課題番号, 学籍番号, 優良可
配点マスタって何?
質問いいですか? Hyou1(Pk,...) Hyou2(Fk,...)において、 FkはPkと同じドメインじゃないと、 Fkが外部キーだと言える条件の一つを満たさないんですよね?
質問 SQL文というのは、基本的に、 必ずテーブル名を指定して使うものなの? つまり、テーブル名の指定無しに 使うというのは、無理なの?
そんなことない
>>865 > 配点マスタって何?
何でかは知らんけど、元々のデータは得点 (1, 3, 5) なのに
>>864 は優良可で
保持するように勝手に変更してるので、わざわざ優良可から得点を求めるための
テーブルが必要になってみたい。
簡単な問題をわざわざ複雑にして、得意がるタイプの人なんじゃないかな。
>>869 RDBMSのパラメーター変更にもSQLを使うことがあるので、
その言い方は必ずしも正しくない。
あなたは「CREATE DATABASE」をテーブル名が指定されていると思いますか?
select 1; だって、from table_name がないけど、立派なselect 文でしょ。
CREATE DATABASEがSQLかっていうと少なくとも標準SQLではない
>>873 も標準SQLではない
それはさておき、
>>869 は質問の意図がよくわからんが
「どのテーブルでもいいから条件にマッチするデータを全部もってこい」
みたいなことを言っているなら、無理
>
>>873 も標準SQLではない
そうなのか、それはすまなかった。撤回する。
>>846 oracleの無料セミナーだと*にするとライブラリだかディクショナリを読みに行くから定数にしたほうが速いらしいよ。
他のDBMSは知らんけどまあ納得して*は対話実行のときしか使ってない。count(*)もcount(1)にしてる。
>>876 それいつ頃のセミナー?
昔は確かにSELECT 1 とかcount(PKカラム)なんかも言われてたけど、
今でもそうなの?
>>877 いや最近はオプティマイザに任せるほうが速い。
意味的には変わってくるな select count(*) // レコードの行数 select count(field) // filedがnullでないものの件数
880 :
877 :2009/02/15(日) 20:00:16 ID:???
>>878 ですよねぇ。
まぁ、DBよっては代わる部分もあるでしょうけど。
>>879 だからPKカラム(Primary Key)と断ったんだ。
count(*)はテーブルスキャンだけど、count(PK)ならインデックススキャンだとか?
メインで使っているPostgreSQLは変わらないから、そんな事したことないけどね。
・DBとバージョン orcle10g ・テーブルデータ MainTable key … ------- 001 … 002 … 003 … 004 … 008 … 010 … 014 … 020 … 034 … SubTable key ----------------- 001 1 … 002 1 … 004 1 … 010 1 … 020 1 … 020 2 … 034 1 … ・欲しい結果 MainTableのkey ---- 003 008 ・説明 MainTableの子データとしてSubTableを作成しています。 (SubTableのキーはMainTableのキー+順番号) 欲しい結果はSubTableを作成していないMainTableのキーになります SQLを1回で出来ると思うのですが方法がよくわかりません、よろしくお願いします
882 :
881 :2009/02/15(日) 22:22:33 ID:???
すいません上の例だと014も結果として必要ですね 御免なさい
ちょっと前に似たようなのあるだろ・・・ 少しは過去ログ参照しろよ
884 :
881 :2009/02/15(日) 22:29:49 ID:???
申し訳ありませんでした、有難うございます
>>881 oracleの差集合は「MINUS」で取得できる。
フィールドとカラムってどう違うの?
用語の組み合わせが違う。 数学的にはリレーションは「ドメインの直積の有限部分集合」と考えるけど、 この時はリレーション(関係)・タプル(組)・アトリビュート(属性)という用語の 組み合わせを用いるのが一般的。 で、このリレーションを具体的に表現する方法としてはグラフやクロス表 (cross tabulation)もあるけれども、もっとも一般的なのは行・列の表形式。 この時はテーブル(表)・ロウ(row, 行)・カラム(列)という組み合わせになる。 さらにリレーションをデータの出し入れをするストレージとして捉えるときに ファイル・レコード・フィールドといった用語を用いる事もある。 実際の用法としてはごっちゃになっているけれども、少なくともリレーション から始まる三つ組みとテーブルから始まる三つ組みは混ぜない方が良い と思う。
質問です ・DBMS名とバージョン MySQL 5.0.45 ・テーブルデータ tag entry_id ----------- a 1 a 2 b 2 b 3 c 4 ・欲しい結果 entry_idに複数のtagが付く場合があります。 上記例の場合、エントリIDの「2」にタグ「a」と「b」が付いています 欲しい結果はタグ「a」を渡されたときに「b」を求めたい。 ・説明 以下のSQLで実現は可能でした。 SELECT tag FROM tag2entry t1 INNER JOIN ( SELECT entry_id FROM tag2entry WHERE tag = 'a' ) AS t2 ON t2.entry_id = t1.entry_id WHERE tag != 'a' GROUP BY tag LIMIT 5 しかし実際はタグが数千、エントリが数十万あり、結果が返ってくるまでに10分以上かかってしまいます。 より高速に実現できそうな方法はありますでしょうか? 宜しくお願いします。
sumなんだけど、 これってカラム名しか入れられないの? sum(1,2,3) とかってしたら、そんなカラム名おかしいよ、って エラーになった。
>>888 ・インデックス張ってる?
・GROUP BYの誤用は止めよう。重複を省きたいのならDISTINCT
・サブクエリを結合に展開してオプティマイザに任せた方が多分速い
SELECT DISTINCT t2.tag AS tag
FROM tag2entry t1, tag2entry t2
WHERE t1.entry_id = t2.entry_id AND t1.tag = 'a' AND t2.tag != 'a'
LIMIT 5
>>887 ちょーさんこうになった。
886じゃないけどさんくす。
>>888 ,
>>891 個人的にはEXISTSのほうが好きだな
速さはやってみないと分からんけども
SELECT DISTINCT tag
FROM tag2entry t1
WHERE EXISTS (SELECT *
FROM tag2entry t2
WHERE t2.tag = 'a'
AND t1.entry_id = t2.entry_id)
AND tag != 'a'
LIMIT 5
894 :
888 :2009/02/16(月) 19:32:44 ID:???
>>891 >>893 ありがとうございます!
tagにのみINDEXつけていたのをentry_idにもつけたら数万倍速くなりましたw
めちゃめちゃ恥ずかしい。
結果的には
>>891 さんの方法が最速で700万行近くあるのに0.0004でした。
今後は質問する前にまずインデックスをつけます・・・
MySQLで既存のインデックスを変更するには、いったん削除してから作成するしか方法はないでしょうか。 SQL一発で変更する方法があれば教えてください。
「変更」というか、MYISAM なら myisamchk -rq というので作り直せるが…
ALTER 無いの?
DISTINCTって遅いイメージがあったんだがな。
GROUP BYが速くなる理由もあまりない。
一応10万entryで10tag/entryの合計100万レコードのダミーデータ 作って試してみたら断然DISTINCTの方が速い。 DISTINCT: 0.0007s GROUP BY: 0.03s このクエリの場合はLIMIT 5が効いている。 これがないとDISTINCTも0.03秒かかる。
LIMITの功績じゃねえか
どういうSQLだ?
SQLで、重複した行を消したいんですけどどうしたらいいですか。 たとえば id=1, name=あああ, title=今日のおかず, created_at=2009-02-15 id=2, name=かかか, title=明日のこんだて, created_at=2009-02-16 id=3, name=あああ, title=今日のおかず, created_at=2009-02-17 のようなデータがあったときに、id=1とid=3は重複しているので id=3のほうを消したいのですが、SQLが分かりません。 select name, title, count(*) as count from table1 group by name, title having count > 1 で重複するデータは抜き出せますが、その先がわからないので アドバイスをいただけたらと思います。
905 :
NAME IS NULL :2009/02/17(火) 17:04:46 ID:BoDPs+dN
MySQL5の文字コードで質問です。 eucjpmsとujisは何が違うのでしょうか? どちらを使った方がいいのでしょうか? ちょっとググっても分らなかったので、分かる方、教えて下さい。
>>903 何処を見て重複していると判断するのか、
どういう基準で残す行を決めているのかワカランがな。
とりあえず、nameとtitleが同じなら重複。
idはユニークで、値の小さい方を残す。
と言うのなら、
DELETE FROM table1 AS T1 WHERE id != (SELECT min(id) FROM table WHERE name=T1.name AND title=T1.title);
何を持って重複なのかがイマイチ不明。 消しちゃいけない行を消しそうな予感。
なんで
>>906 を言い換えただけの内容で書こうと思ったの?
なんで直前のレスを言い換えただけの内容で書こうと思ったの?
910 :
NAME IS NULL :2009/02/18(水) 20:02:21 ID:05nLCNr6
SQLであるひとつのテーブルのデータをすべて抽出して、 ORDERBYで並び替えてから同じテーブルに登録しなおすにはどうしたらいいですか?
>>910 RDBの概念にレコードの順番という概念はない。
特定の実装ならあるかもしれんから、環境をちゃんと書け。
>>903 >906のやり方でできるんだけど、
相関クエリーは考え方に慣れが必要だからわかりにくいかも
重複してる行を消すということは、それぞれ1行だけのこして全部消すってことだから、
DELETE FROM table1 WHERE id not in (SELECT min(id) FROM table1 group by name, title )
でいけると思う。重複とのこす基準は>906と同じな
not in 使うと遅いとか言う話があったりして、これを改良すると>906になる
>>910 何のためにそれをしたいの?
Oracleの索引構成表とかDB2のクラスター化表とかなら
ある意味はじめから順序どおり格納されるとも言えるけど、
そういうことをしたいんでもないだろうしなあ・・・
>>910 いったんテンポラリのテーブルに出力して、元を削除して、再度 INSERT
915 :
906 :2009/02/18(水) 22:14:42 ID:???
俺、やっちまったなーw
先だってから、「今の(NOT) INは遅くない」って書いてたのに、ついつい慣れから相関クエリを書いてしまう。
name,titleにインデックスがない場合、確実に
>>906 は遅い。
name,titleにインデックスを張っていても、
>>912 のサブクエリが一度だけしか実行されない
様になっているDBなら
>>912 の方が速い場合がある。
で、重複行を消したいという質問が偶にあるけど、本来重複行が出来ないようにすべきで、
せいぜい、設計や仕様変更に伴う時に一度使う程度なんだったら、どちらでもいいっちゃいいよな。
うおお、COUNT(1)が理解されて無いなww selectされたレコードすべてに数値の定数1を返す。すなわちどのカラムがヌルだろうが選択されたレコード件数になるんだよ。 カラム番号じゃないよ。
AQL辞典見たほうが早いよ。本屋へ急げ。
918 :
NAME IS NULL :2009/02/23(月) 12:23:40 ID:m+mY0xtA
これまで映画データベースを カテゴリで管理してたのですが、 泣きたい時、2人で見たい、昔TVでよく見た 等のタグ付けをしてタグ管理に変えたいと思ってます。 タグテーブルを作り id description ----------------------- 1 泣きたい時 2 1人で見たい 3 昔TVでよく見た 元々の映画データベースにtagカラムを追加して id name tag ----------------------------------------- 1 バックトゥザフィーチャー 2,3 2 ショーシャンクの空に 1,2 3 死霊のはらわた 2 のようにtagカラムの中にカンマ等でタグ付けしたらいいかなと思っていますが、 もっと効率が良い方法あったりしますか?
別にテーブル追加で、 id tag ------ 1 2 1 3 2 1 2 2 3 2 とかでいいじゃない。
カンマで切った tag は、どうやって検索するつもりですか ? 映画名の id name のテーブルはそのままにしといて id movie-id tag-id 1 1 2 2 1 3 3 2 1 4 2 2 5 3 2 … などとする方が楽ではないかと思いますが…
かぶった。すまぬ。
>>918 それはテーブル設計の問題で、SQLの問題じゃないからな
まあ、普通にやるなら
>>920 のやり方だろうけど
923 :
918 :2009/02/23(月) 14:24:06 ID:m+mY0xtA
なるほど!そうですよね・・ ブログのコメントなんかはそうやって管理してるのに、 なんで思いつかなかったんだろ・・ これ、複数タグで検索する時は タグテーブルをJOIN して tag=1 and tag=2 and tag=3 ... みたいに何個もand使う感じでいいんでしょうか?
sybaseはこちらでいいのでしょうか。 CGIで、パラメータ取り込んでDB updateするプログラム書いてるのですが(PERL-DBI) SQL文をストアド使わないで直書きでやろうとしてます そのとき、transactionって、使えるのでしょうか。 begin tran update 〜 if(@@rowcount = 0 or @@error !=0) rollback tran else commit tran ↑のようなSQL文をソース内に書いて実行はできるのでしょうか。 今、SQLサーバに接続できないので、確認が出来なくて よろしくお願いします。
複合PKは嫌い
通し番号が必要かどうかわからなかったら、とりあえずつける。 アプリが出来てから判断してもいいんじゃね。
select * from (values (1,2),(3,4)) as dummy(a,b);
みたいなことをOracleでやろうとしたとき、
select * from (select 1 as a, 2 as b from dual union all select 3,4 from dual) dummy;
って書くしかない?
いや、
>>923 みたいなことを
http://oraclesqlpuzzle.hp.infoseek.co.jp/12-5.html のようにやろうとしたとき、Oracleだと書き難いなと思って。
一時テーブル作るのもバカバカしいし。
929 :
NAME IS NULL :2009/02/24(火) 22:22:10 ID:hJlBxWQB
使用DB:MySQL5 +-------+------------+------+ | id | name | rank | +-------+------------+------+ | 45577 | nakano | aaa | | 45578 | nakano | bbb | | 45579 | nakano | ccc | | 45580 | nakano | ddd | | 45581 | satou | bbb | | 45582 | satou | ccc | | 45583 | satou | ddd | | 45584 | ikeda | ccc | | 45585 | ikeda | ddd | +-------+------------+------+ 上の様なデータで rank に bとc のデータを持つ name を表示したい(nakanoとsatou)のですが どのように書けばいいのでしょうか?
where rank = 'bbb' or rank = 'ccc' でdistinctかければいいのでは?
ごめんorじゃなくてandか
>>929 bとかcとかいったランクがクエリで与えられるので
あればセルフジョインでおしまい。
select distinct A,NAME as NAME
FROM T A, T B
WHERE A.NAME = B.NAME AND
A.rank = 'bbb' AND B.rank = 'ccc'
もし検索したいランクの組がリレーションに入っているので
あれば外部結合を使う。
なにこれ?かっこいい自演をしようと思ってこじれたのかな?
>>933 最後の部分kwsk
少なくともOUTER JOINではないと思うけど
>>935 あ、ごめんなさい。このケースではOUTER JOINは必要なかったです。
ただ外部結合を使うと厳密にbbbとccc「だけ」を持つ集合を出せるんです。
select distinct A,NAME as NAME
fromT A left outer join ランクだけ B
on A.RANK = B.RANK
having count(A.NAME) = (select count(RANK) from ランクだけ)
and count(B.RANK) = (select count(RANK) from ランクだけ)
みたいな感じで。
つ GROUP BY NAME 付け忘れました・・・酔っぱらったまま書くととろくな事がないなぁ。
938 :
NAME IS NULL :2009/02/25(水) 11:41:53 ID:K3R0lD3x
SQLServerでの自動インクリメントで、決まったフォーマット形式を埋め込むことはできますか? 例えば G0001 G0002 G0003 ・ ・ のようなデータを作りたいのですが
よく考えたら自動インクリメントに文字列フォーマット入れるなんて無理ですね すいませんでした
朝の8時ですよ?
>>938 ,939
SQLServerは弄ったことないけど、あるカラムの値をG0001,G0002と増やしたいのなら可能だろう。
そのカラムのデフォルト値を 'G' || to_char(nextval(sequence_name),'FM0000') にすれば桶。
ちなみに || は連結子な。SQLServerは違うかも。
普通で考えれば、取り出すときに'G'を連結する方がいいと思うけど。
>>938 それは、一つのカラムの中に、固定部分と連番部分の二つの項目を入れてることになる
固定部分と連番部分で素直にカラムわけるべき
固定部分はカラム必要ないかも知れんし、合体した形式で扱いたいなら
カラム(または固定文字列)を連結したビューを作れ
>>941 SQL-Server は、シーケンスじゃなくてフィールドの属性として
自動インクリメント指定する方法だから、その方法は取れない。
まあ、Excel じゃないんだからほかの人が言ってるように取り
出し時にフォーマッティングするのがいいと思う。
DB: SQLServer 2005 id | names --------------------- 1 | 佐藤,小林 2 | 小林,鈴木 3 | 鈴木,田中,佐藤 上のテーブルを下のテーブルに変換したいのですが、どのようなSQLを書いたらよいでしょうか。 id | names --------- 1 | 佐藤 1 | 小林 2 | 小林 2 | 鈴木 3 | 鈴木 3 | 田中 3 | 佐藤 PostgreSQL だと regexp_split_to_table で一発でできそうなのですが、 調べた限りでは SQLServer にはなさそうです。
つ SQLCLR
「idが1」で、 なおかつ、 「valueが1より大きい」、 場合のみ、valueを1減じたくて 次のようなSQLを書いたのです。 UPDATE tb1 SET value = value - 1 WHERE id = '1' AND value > '1' ところが、valueがー3とかの場合にも、 ガンガンvalueが減ってしまいます (こちらの意図した通りに動くなら、 valueが1より小さいときは動作しない はずなのに、、、) どうしてでしょうか?
>>946 は自己解決したのでもういいです。
下のほうに、もう一個SQL文書いてた。
次の質問。 UPDATE tb1 SET value = value - 1 WHERE id = '1' AND value > '1 このSQL文で、最初の1回は実行されて valueが減るのですが、 2回目以降は減りません。 なぜでしょうか? エラーも出ません。
最後のクオーテーション抜けてました UPDATE tb1 SET value = value - 1 WHERE id = '1' AND value > '1' 誰か原因教えてください
SELECT value FROM tb1 WHERE id = '1' AND value > '1' これで検索されてこないよ なんで?
自己解決した SELECT value FROM tb1 WHERE id = '1' AND value > 1 にしたらできた。
>>946-951 まずおまえは数値と文字列について勉強しれ
つぎに、暗黙の変換についても勉強しとけ
いきなりUPDATEとか、 危険な奴っちゃな〜
自己解決したのでもういいです。
冗談抜きで頼むからもう来ないでください。
957 :
NAME IS NULL :2009/02/27(金) 06:08:02 ID:+HgOwZAx
SELECT *, CASE WHEN column_a THEN column_a ELSE column_b END AS hoge avg(hoge) と書いたのですが Unknown column 'hoge' in 'field list' と言われてしまいます。 別名カラムに集計かけることはできないんでしょうか? どうすれば実現できますか?
958 :
NAME IS NULL :2009/02/27(金) 06:08:32 ID:+HgOwZAx
hogeの後にカンマ抜けてました
>>957 SELECT *,
avg(CASE WHEN column_a THEN column_a ELSE column_b END)
FROM ...
> 別名カラムに集計かけることはできないんでしょうか?
SELECT リストには FROM句で参照しているものしか書けません。
例えば以下のような物も本来は無理。
SELECT column_a AS tmp , tmp*2 FROM ....
>>957 >>1 >質問するときはDBMS名を必ず付記してください。
>>959 >SELECT リストには FROM句で参照しているものしか書けません。
本来は、って話なんだが、これは、標準的なSQLの話なのか?
俺の記憶では、定数とカラムの計算式はSELECTリストにかけたと思うんだ
つか、FROM句じゃなくてGROUP BYで参照してるカラム、じゃないのか?
その場合でも定数と式はかけたと思ったが
記憶で書くなよ…
>>957 >別名カラムに集計かけることはできないんでしょうか?
少なくとも MS SQL Server でも Oracle でも、それはできない。
>どうすれば実現できますか?
インラインビューにするか、面倒でも case 〜 end をもう一度書く。
962 :
960 :2009/02/27(金) 14:51:01 ID:???
記憶で書いてすまんのう あと言っとくが、俺は別名カラムで集計できるとはいってないぞ 別名で集計できないので、GROUP BYとSELECTで同じケース式書けってのが正解で、 それはすでに>959で提示されたとおりだと... どっちもGROUP BYのとこ省略してるからわかりにくいか つか、961=959なのか? だったら、 >SELECT リストには FROM句で参照しているものしか書けません。 のソースを教えてくれ ついでに、参照いているもの の もの ってなんだ? ほんとにFROMで参照してない定数はセレクトリストにかけないのが本来の動作なのか?
なんか揉めてますね。第三者ですが一応ちゃんとした本から引用 して書いておきます。 1. FROM・WHERE・GROUP BY・HAVING句を評価した結果をT1 2. T1に指定された選択項目を評価して生成された結果をT2 3. その後、DISTINCTとかORDER BYとか・・・ で、選択項目が以下の形式をとる場合、 (スカラー式) AS 列 左のスカラー式はスカラー一次子として「列名」・「定数」・集約関数・ 行サブクエリーを含むことが出来る。 このスカラー式は「テーブルT1の」行ごとに評価される。よって列名 はT1の列名。集約関数の引数となるスカラー式についても同様。 右のAS以下は「T2の」カラムに対してつけられる列名。 なので、T1を構築するFROM・WHERE・GROUP BY・HAVING句では 利用する事は出来ない。T2構築後のORDER BY句では使用すること が出来る。 あとSELECT句の中でAS以下の列名の参照を認めると以下の様な 巡回参照も書けてしまいます。 T.A * X AS Y, T.B * Y AS X
引用元も明記しないとか駄目すぎ
ごめん。ど忘れ。Dateの標準SQLガイド改訂第4版。
966 :
960 :2009/02/27(金) 18:39:55 ID:???
なんか勘違いされてるような気がするが、俺は別名を問題にしてるんじゃないぞ
セレクトリストに定数や式が書けないのが本来の仕様か?ということを聞いてるんだが
>SELECT column_a AS tmp , tmp*2 FROM ....
が禁止だってことに異論はない
で
>>963 の資料だと、「列名」・「定数」・集約関数・行サブクエリーからなる
スカラー式ならOKだって話だろ。ただし列名はT1の列名であること、って条件で
列名使わない定数や行サブクエリーは自由に書くことができるということだ
だから、
SELECT リストには FROM句で参照しているものしか書けません。 ではなくて、
SELECT リストの列名には FROM句で参照しているものしか書けません。 が正解だろうと
自分で書いてて、かなり揚げ足取りくさいな
まあ揚げ足取りついでに、
>集約関数の引数となるスカラー式についても同様
引数となる列名についても、の間違いじゃないのか?
そもそも集約関数の引数はスカラー式に限らないと思うんだが
もういいよ 不毛
968 :
963 :2009/02/27(金) 19:57:21 ID:???
>>966 >SELECT リストの列名には FROM句で参照しているものしか書けません。
>が正解だろうと
そうですよね。
自分も
>>959 の書き方は少しいい加減で良くないだと思います。あと、
>そもそも集約関数の引数はスカラー式に限らないと思うんだが
これなんですが、正確には集約関数の引数はスカラー式もしくは「*」
(ただしCOUNT限定)で、スカラー式は項もしくは項同士の足し算引き算で、
項は因子のかけ算割り算で、因子はスカラー一次子かスカラー一次子に
正負の符号がついたものでスカラー一次子は列名・定数・集約関数の参照
(ただし集約関数の引数となるスカラー式の場合は除く)・括弧でかこまれた
スカラー式・括弧でかこまれた行サブクエリーということでした。
長いので定義を端折って書きましたが、誤解を招いたようで申し訳ない。
969 :
959 :2009/02/27(金) 21:02:06 ID:???
おースマン、書き方が悪かった。 元質からの流れと俺の語彙の少なさで、あのような書き方になってしまった。
おまいらDUAL表使って定数返し放題だろw あれは何もDUALじゃなくて1レコードだけ格納された表つかえば 全くおなじ結果になんだよ
特定の実装と、標準SQLの仕様の話の区別ぐらいつけようぜ
972 :
NAME IS NULL :2009/02/28(土) 00:21:42 ID:G9jKJuyf
>>957 SELECT *,
CASE WHEN column_a THEN column_a ELSE column_b END AS hoge
avg(CASE WHEN column_a THEN column_a ELSE column_b END) AS avghoge FROM
ソースとしては汚いね
973 :
NAME IS NULL :2009/02/28(土) 00:34:55 ID:G9jKJuyf
あっ * 書いたらサムやAveの集計関数は書けねえわw GROUP BY * 使えるのあんかなAveなら用途ありそうだね
そもそもSelectリストって表現がおかしい。
Selectリストって表現使われてるのは見かけるな。英語のマニュアルとかで。 日本語だと選択リストって感じかな。
PostgreSQLの日本語マニュアルでも選択リストだね。
SQLiteのrandom関数、 1−5の値を出したいんだが、 どうしたらいいのかな?
SELECT abs(random()) % 5 + 1;とか?
「ボタンを一回押したら、数値が3−5増える」 というプログラムを作ったんだが、上限を100で固定したい。 いまのままだと、「97」のときに、ボタンを押して、 「5」がランダム生成されると、 97+5=102 になってしまって、100をオーバーしてしまう。 これを、100以上にしないようにしたいのだが、 SQL文で、上限の固定とかできるの?
DBがサポートする仕様によっては出来る事もあるけど、DBの バージョンも「・・・というプログラム」をどういったSQLで実現した のかも書いていないのでは恐らく誰もコメント出来ないと思う。
ん、、、少なくとも、SQLの標準機能では 無理そうだというところまでわかりますた。
ちょうど
>>970 が書いていたが、ランダム値を1個返すサブクエリを使えばいいんじゃね。
SELECT CASE WHEN T1.rand + T2.num >100 THEN 100 ELSE T1.rand + 95 END
FROM (SELECT cast(random()*3+3 AS INT) AS rand)AS T1 , (SELECT num ...) AS T2;
985 :
984 :2009/03/03(火) 03:32:48 ID:???
一ヶ所間違えてた。 SELECT CASE WHEN T1.rand + T2.num >100 THEN 100 ELSE T1.rand + T2.num END FROM (SELECT cast(random()*3+3 AS INT) AS rand)AS T1 , (SELECT num ...) AS T2;
sage
>>981 単純にやるなら select LEAST(n + floor(3 * Random()) + 3, 100) from ...
でいいと思うが。
LEAST() ないなら、case でがんばれ。
>>984 ,985,987
ん、、、みんなありがとう
自分の知識が足りなくて
書いてあることが理解できないよ
>>SQL文で、上限の固定とかできるの テーブルの項目に制約をつけることによって上限の固定はできるだろう もしくは、トリガでチェックするって方法もある
自分がイメージしたのは、 MAX(100) みたいな、シンプルな命令がもしあれば 使いたいな、ってことだったんです。
>>990 いやだからさ、
>>981 だと情報が少なすぎて何をどうやりたいのか
さっぱりなんだわ。
>「ボタンを一回押したら、数値が3−5増える」 というプログラム
をどういうSQLで実現したのかSQL文の抜粋程度は書かないと、
それをどう変更すれば望みの「100で固定」を実現出来るか答え
ようがない。
あと「標準SQL」でもこの機能は実現出来るけど、残念ながら全て
のDBMSが「標準SQL」で定義されている機能を全部持っている
わけではない。DBMSによっては持っていない機能もある。
だからDBMSの名前とバージョンを書かないと答えようがない。
なのでまずは
>>1 のテンプレと
>>4 ,5の質問を参考にして必要十分
な情報を書くこと。
あるいはエスパーをご所望ならそう明記を。
SQLと言うよりもプログラム側でランダム値を生成すればいいだけのような気がする。
sage
エスパーすると、これはSQLと関係なくて、 >「ボタンを一回押したら、数値が3−5増える」 で得た値と 100 を比較して小さい方を返す、 という関数を作るなり、 組み込み関数を使うなりすればいいと思うよ。
SQLfでやることじゃねーわなw
997なら最高のオナニーができる
もう終わりでいいな。
うめ。
うめ。
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。