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

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

SQL質疑応答スレ 7問目

1 :NAME IS NULL:2008/10/09(木) 13:11:14 ID:???
このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。

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

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

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

前スレ:SQL質疑応答スレ 6問目
http://pc11.2ch.net/test/read.cgi/db/1210940477/


2 :NAME IS NULL:2008/10/09(木) 13:11:59 ID:???
SQL言語リファレンス一覧
Oracle Database
http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05750-02/toc.htm
Microsoft SQL Server
http://msdn.microsoft.com/ja-jp/library/bb510741.aspx
IBM DB2 Database
http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp (目次から参照情報→SQL)
PostgreSQL
http://www.postgresql.jp/document/pg833doc/html/sql.html
MySQL
http://dev.mysql.com/doc/refman/5.1/ja/sql-syntax.html


参考リンク
http://sql.main.jp/cont/sql/map.html
http://www.atmarkit.co.jp/fnetwork/rensai/sql01/sql1.html
http://oraclesqlpuzzle.hp.infoseek.co.jp/
http://www.techscore.com/tech/sql/


3 :NAME IS NULL:2008/10/09(木) 13:12:31 ID:???
過去ログ

SQL質疑応答スレ http://pc8.2ch.net/test/read.cgi/db/1056973582/
SQL質疑応答スレ Part 2 http://pc8.2ch.net/test/read.cgi/db/1103113155/
【帰ってきた】SQL質疑応答スレ http://pc8.2ch.net/test/read.cgi/db/1124178925/
【帰ってきた】SQL質疑応答スレ 2問目 http://pc8.2ch.net/test/read.cgi/db/1141622643/
【帰ってきた】SQL質疑応答スレ 3問目 http://pc11.2ch.net/test/read.cgi/db/1160458216/
【帰ってきた】SQL質疑応答スレ 4問目 http://pc11.2ch.net/test/read.cgi/db/1176553195/
SQL質疑応答スレ 5問目 http://pc11.2ch.net/test/read.cgi/db/1193486961/


4 :NAME IS NULL:2008/10/09(木) 13:13:10 ID:???
よくある質問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
;


5 :NAME IS NULL:2008/10/09(木) 13:14:25 ID:???
よくある質問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
;


6 :NAME IS NULL:2008/10/09(木) 15:40:31 ID:???
いちょーつ

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

以上、よろしくおねがいします。


10 :NAME IS NULL:2008/10/10(金) 02:39:38 ID:???
>>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で無事に動きました。とても助かりました。

12 :NAME IS NULL:2008/10/11(土) 08:05:59 ID:???
だれか

SQLServerとOracleでの

文字列→日付
日付→文字列

をフォーマット付きで指定できる奴の
テンプレ作っておいてくれ
俺が帰ってくるまでにw

なかったら俺が探して書くw

13 :NAME IS NULL:2008/10/11(土) 15:19:19 ID:???
PCとActiveSync接続中のネット接続ON/OFF切り替えするメニューどこでしたか?

14 :NAME IS NULL:2008/10/11(土) 15:19:51 ID:???
誤爆しました。

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に出力しないとできないものでしょうか?

16 :NAME IS NULL:2008/10/12(日) 00:20:35 ID:???
>>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を教えていただけますとうれしいです。

18 :NAME IS NULL:2008/10/12(日) 00:38:17 ID:???
>>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に反映させたいのですが、方法がわからないのです。

どうかよろしくお願いします。

21 :NAME IS NULL:2008/10/12(日) 01:04:19 ID:???
>>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

23 :NAME IS NULL:2008/10/12(日) 09:36:40 ID:???
>>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じゃうまくいきません。

27 :NAME IS NULL:2008/10/12(日) 10:19:19 ID:???
>>26
当たり前。

次の方どうぞー

28 :15:2008/10/12(日) 10:30:29 ID:kBgP9NuQ
見捨てないで、方法をおしえてください。INを使った方がいいのかな?むつかしい。。

29 :NAME IS NULL:2008/10/12(日) 10:33:27 ID:???
>>28
>> 基本的な SQL 文を勉強した方が良いんじゃないかと。
> SQLの勉強は進めたいと思いますが
> やってみたけど、25じゃうまくいきません。

勉強する気がないかの能力がないのかは知らんが、お前には無理。

30 :15:2008/10/12(日) 10:35:10 ID:kBgP9NuQ
そうですか、残念ですが、あきらめます。

31 :NAME IS NULL:2008/10/12(日) 10:40:49 ID:???
この手の新人が入ってきたら苦労しそうだが…

この連載でも読んでみたら。買って読むべき本もわかるでしょう。
ttp://codezine.jp/article/detail/460?p=1

32 :NAME IS NULL:2008/10/12(日) 14:42:23 ID:???
SQLServer2005です。
列A+列B>5000のような条件を指定してSELECTしたいのですけれども
これって1000万行とかあったら恐ろしく応答遅くなりますか?

33 :NAME IS NULL:2008/10/12(日) 14:54:16 ID:???
ちょー初心者な質問で申し訳ないですが、
http://msdn.microsoft.com/ja-jp/library/ms188366.aspx
USE AdventureWorks;
GO
という例が載ってて、類似の書き方を他のサンプルでも見かけるけど
このセミコロンって何で要るの?
あとセミコロンってSQL構文の一部なんでしょうか。それともGOみたく別物?


34 :33:2008/10/12(日) 15:03:22 ID:???
自己解決したスマンヌ;
http://msdn.microsoft.com/ja-jp/library/ms177563.aspx
によると、Transact-SQL ステートメントのターミネータの意味。
今は書かなくてもいいが将来に備えて書いといた方がいいっぽい。
しかしTransact-SQLって複文書くときもセミコロン要らんのがウリだとオモタが
将来必要になるかもってどういうことだろう、

35 :NAME IS NULL:2008/10/12(日) 15:03:47 ID:???
>>32
列A+列Bというインデックスが張ってあればいいけど
そうじゃなきゃフルテーブルスキャンだな。

>>33
SQL構文の一部としてのセミコロンも存在するけどその場合は違う。
SQL Server固有の区切り文字だろう。
(SQL Serverはよく知らんけども。)

36 :NAME IS NULL:2008/10/12(日) 19:22:12 ID:???
T01Prefectureってなに?

37 :NAME IS NULL:2008/10/12(日) 19:33:55 ID:???
>>36
http://ja.uncyclopedia.info/wiki/%E3%82%B0%E3%82%B0%E3%83%AC%E3%82%AB%E3%82%B9

38 :NAME IS NULL:2008/10/14(火) 04:06:48 ID:???
データーベースの設計で、primary keyって必須なのか?
そういうことにきづいた最初の人は誰?

39 :NAME IS NULL:2008/10/14(火) 04:22:49 ID:???
リレーショナルデータベースを
関係データベース って呼ぶキチガイって本当にいるのか?

40 :NAME IS NULL:2008/10/14(火) 08:02:27 ID:???
>>38
インデクシングをBツリーで実装したデータベースエンジンの場合、Primary Keyは効率上必須(無いと線形探索しかできない)。
誰が言い出したかは知らんが、最初のBツリーの実装時に生まれたんだろ常考
(テーブル内のレコードは一意でなければならない、というレベルでならデータベースの関係モデルを最初に提唱した
Coddがすでに言ってたが、知っての通りPrimary Keyはそれ+αなので明らかにCoddより後)


41 :NAME IS NULL:2008/10/14(火) 20:05:02 ID:???
データベース:SQL2000
NULLに足し算した結果、NULLとならないようにするオプションありますか?

例:NULL+1=1

42 :NAME IS NULL:2008/10/14(火) 20:09:45 ID:???
>>41
NULLというものの意味をもう少し勉強したほうがいい

43 :NAME IS NULL:2008/10/14(火) 20:10:59 ID:???
>>41
NULL は NULL であって 0 じゃないから、そんなオプションはないと思う。
SQL2000 ってのが何か分からないが、SQL Server のことなら
ISNULL って関数を使えばいいんじゃない?

44 :NAME IS NULL:2008/10/15(水) 08:28:31 ID:???
確かに、NULLと0を等価で扱いたいことはあるけどな。


45 :NAME IS NULL:2008/10/15(水) 09:55:06 ID:???
そのためのCOALESCE

46 :NAME IS NULL:2008/10/18(土) 18:41:10 ID:???
テーブル作るときに
varchar(100)
って指定した場合と
varchar
って指定しない場合はどう違うんですか。
あとH2使おうとしてるんですけど
varchar2はどう違うんですか

47 :NAME IS NULL:2008/10/19(日) 12:44:50 ID:Mvsa6eQB
>>46
指定しないんなら、default値じゃんえーの?

48 :NAME IS NULL:2008/10/19(日) 15:08:58 ID:???
>>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になるんだね。
最初から試せって話だね。

51 :NAME IS NULL:2008/10/20(月) 09:39:43 ID:???
>45
全くスペルが覚えられない俺に一言

52 :NAME IS NULL:2008/10/20(月) 09:59:23 ID:???
>>51
おれもw

53 :NAME IS NULL:2008/10/20(月) 11:30:04 ID:???
なんというか単語にNull値をどうにかしてやるぜ!感(?)がまるで感じられないから嫌い。
もっと直接的にIsNullとかIfNullとかNVLとかNzとかだったら喜んで使うんだけど

54 :NAME IS NULL:2008/10/20(月) 17:07:35 ID:???
環境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は無理なのでしょうか。

55 :NAME IS NULL:2008/10/20(月) 17:30:48 ID:???
結合するよりも相関クエリの方が適している場合があるというだけで、
単純にテーブルから抽出するだけなら前者でよいと思うよ。

56 :NAME IS NULL:2008/10/20(月) 17:37:29 ID:???
分りました。ありがとうございます。

57 :NAME IS NULL:2008/10/21(火) 06:15:27 ID:???
回答がすでに出ているので蛇足だが、仮に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)
と書けてなかなか趣き深い。


58 :NAME IS NULL:2008/10/21(火) 13:12:24 ID:???
蛇足に駄レスだが、col1で一意になるなら where col1 = 4 だけでいいよね。

59 :NAME IS NULL:2008/10/21(火) 18:45:23 ID:???
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

60 :NAME IS NULL:2008/10/21(火) 18:47:14 ID:???
上記の様なテーブルがあり
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を表示させたいのです。

61 :NAME IS NULL:2008/10/21(火) 18:49:32 ID:???
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>);

の様な形では、自身が所属していないタイプにも属していた場合は弾かれずに表示されてしまい
困っております。
どのような形で記述すれば、希望の形で取得出来ますでしょうか。。。

62 :NAME IS NULL:2008/10/21(火) 18:50:59 ID:???
書き忘れました。。。mysql 5.0.22です。
ご指南のほど、宜しくお願い致します。

63 :NAME IS NULL:2008/10/21(火) 19:32:09 ID:???
>>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全部?

64 :NAME IS NULL:2008/10/21(火) 19:39:21 ID:???
解けそうでとけねー。つーか頭が溶けてきた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で結合すれば桶。

65 :NAME IS NULL:2008/10/21(火) 19:46:13 ID:???
俺も>>60の前者は5,3,EEEEの間違いだと思う。

どのtypeにも属さないユーザーも含みます

って書いてるからもうちょっと脳を溶かしてがんばってw

66 :NAME IS NULL:2008/10/21(火) 19:47:21 ID:???
自分がどれにも属していなければ、いずれかに属しているユーザが所有する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

70 :NAME IS NULL:2008/10/21(火) 20:21:46 ID:???
これでいいんかな?

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>
;

71 :NAME IS NULL:2008/10/22(水) 03:28:27 ID:???
100レコードあるテーブルから10件SELECTするのと
100000レコードあるテーブルから10件SELECTするのとではパフォーマンスに違いはありますか?

72 :NAME IS NULL:2008/10/22(水) 04:02:02 ID:???
インデックスがちゃんと使われていれば気にするほどじゃないと思う

73 :59:2008/10/22(水) 10:23:18 ID:???
>>70
有難う御座います!
これで漸く作業を進める事が出来そうです。
NOT EXISTSの存在、今の今まで浮かびませんでした

一緒に考えて下さった63-67の皆様も、本当に有難うございました。

74 :NAME IS NULL:2008/10/22(水) 14:22:42 ID:???
>>72
ありがとうございます。
インデックスが適切に張られていたと仮定しての話でしたが、
素人目に考えるとファイルオープンや二分木探索のときに総レコード数が多い方が
明らかにオーバヘッドが高いように思うのですが、そんなに変わらないもんなんでしょうか。

75 :NAME IS NULL:2008/10/22(水) 15:49:07 ID:???
2分探索で最悪のケースで17回比較で、それが10回分なら最良のケースと比較しても170回の差でしかないし
これは一瞬だ

76 :NAME IS NULL:2008/10/22(水) 15:57:24 ID:???
>>74
> ファイルオープン
インデックスは多くの場合において随分小さいです。

> 二分木探索
この言葉が出てくるならレコードが100の場合におおむね6回の比較、
100000件でおおむね17回の比較でよいことも分かりますよね。

パフォーマンスの違いはもちろんあるよ。

77 :NAME IS NULL:2008/10/22(水) 19:09:44 ID:???
EXISTSの使いかたを見ても分かりません。
どこかに詳しく解説書いてあるページありますか?

78 :NAME IS NULL:2008/10/22(水) 19:14:47 ID:???
>>75-76
ありがとうございます。
レコード数は必要がない限りそれほど気にせずにやってみます


79 :NAME IS NULL:2008/10/22(水) 19:15:21 ID:???
http://www.geocities.jp/mickindex/database/db_optimize.html

80 :NAME IS NULL:2008/10/22(水) 19:16:39 ID:???
クエリの処理がボトルネックになっているということが判明するまでよけいなことしない方がいいよ。

81 :NAME IS NULL:2008/10/22(水) 19:30:15 ID:???
>>77
これとか?
http://www.techscore.com/tech/sql/07_02.html

82 :NAME IS NULL:2008/10/22(水) 19:45:03 ID:???
>>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の実装次第と言われたらそれまでだろうけど。



83 :NAME IS NULL:2008/10/22(水) 21:22:24 ID:???
>>71
あんまり意味ない。
パフォーマンスを気にするのは10万行以上の単位。

84 :NAME IS NULL:2008/10/22(水) 22:02:48 ID:???
いやいや、>>71は装置制御とかでmsオーダーのレスポンスの話をしているのかもしれないぞw

85 :57:2008/10/24(金) 00:23:37 ID:???
>>58
それはcol1=4の行の内容が(4,5,6)であると最初から分かってる場合だけなりよ。

86 :NAME IS NULL:2008/10/24(金) 00:34:45 ID:???
>>71
WHERE句の内容と書き方にもよるが、
ある列にインデックスが張ってあってその列による選択性が高い(WHERE句の最初の方に出てくる等)場合、
レコード件数に対して検索時間はO(log n)なりよ。

理想条件だと、100件からの検索と、10000件からの検索の検索時間非は大体2倍(=log 1000/log 100)がセオリー。
実測値はケースバイケースなので責任持たない。

87 :NAME IS NULL:2008/10/24(金) 01:43:08 ID:???
>>85
> col1の値でテーブル内のレコードを一意に特定できる
いや、こういう仮の前提を作ったのは>>57でしょ?
その上でcol2 col3を見るだなんてなんと非効率的な。

88 :NAME IS NULL:2008/10/24(金) 02:26:21 ID:???
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?)に対してすまなかったので心の中でロールバックしといた

92 :NAME IS NULL:2008/10/25(土) 08:28:53 ID:???
時に、EXISTS を使うとき、SELECT 句では何を返してる?

具体的なDB名を挙げられないのだが、
昔は、定数を返した方が速かったそうだが、
現在のオプティマイザでは、* を返した方が速いらしい、ということをどこかで聞いた。
まあ、ms, ns の世界だとは思うが、必要な場合には試してみてくれ。


93 :NAME IS NULL:2008/10/25(土) 14:53:56 ID:???
今から言うことはオフレコで。

EXISTS(SELECT 1 FROM foo WHERE ...)と、
EXISTS(SELECT * FROM foo WHERE ...)と、
EXISTS(SELECT a, b, c, d FROM foo WHERE ...)とでは
データベースエンジンがやるべきことに違いが生じないっていうか原理的に生じ得ない。
というのは、いくら列の指定に凝ってみても、
データベースエンジンにしてみればテーブルを検索して指定条件をテストすれば済み、
戻し値を生成する必要がない、というシチュなので。

ただし、より複雑な状況において、具体的な列指定がオプチマイザに対して
テーブル検索回数を減らす最適化のヒントを与えることもあるかもしれんがよくわからない

94 :NAME IS NULL:2008/10/25(土) 17:35:23 ID:???
>>93
ということはキーではないカラムdを抽出するようなクエリであったとしても、
エンジンはexistsの中に書かれていることから、dを抽出しない動作になると?

95 :NAME IS NULL:2008/10/25(土) 18:12:58 ID:???
>>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のインデックスではない。

97 :NAME IS NULL:2008/10/25(土) 19:49:21 ID:???
>>95-96
で結局だな、>>92が書いたようにEXISTS述語のサブクエリでは
カラム名を指定せずに SELECT * としておいて
DBのプランナもしくはオプチマイザ任せにしておくのが吉。
って結論になっている。ってことで桶だよな。

98 :NAME IS NULL:2008/10/26(日) 00:48:36 ID:???
>>97
同意。
参考: http://q.hatena.ne.jp/1224631145



99 :NAME IS NULL:2008/10/26(日) 00:51:02 ID:???
んじゃ、existsのなかでシーケンスを使ってみたりなんかすると?
使い道は思い浮かばないけど、文法上書くことはできるはずで。
DB依存の挙動になるのか、プランナの気分次第、未定義、どうなるんだろ。

100 :NAME IS NULL:2008/10/26(日) 01:08:59 ID:???
大手ECサイトのヨドバシドットコムが、サイトリニューアルから大規模な障害を3日間...
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail.php?qid=1220150877

506 :目のつけ所が名無しさん:2008/10/26(日) 00:47:20
大手ECサイトで、ここまで派手なリリース失敗は初めて見た。
エンジニア向けIT情報誌や関連サイトは、ぜひ取材して原因を明かして欲し
いは。


101 :NAME IS NULL:2008/10/26(日) 01:52:08 ID:???
>>99
シーケンスという特性上、カウントアップされるべきなら、実行されるんじゃね。
と言うか、プランナとかオプチマイザって思っている以上によくできてる。

IN述語よりEXISTS述語の方が高速で、IN (サブクエリ)形式の多くは
EXISTS (相関サブクエリ)に書き換え可能だから、そうするのはよく言われることだけど、
今じゃ下手すっとIN述語の方が速い。
行数にもよるだろうけど、IN述語=遅い という固定概念は捨てた方がよさげ。

102 :NAME IS NULL:2008/10/26(日) 02:03:01 ID:???
おそっ
なにこれw

103 :NAME IS NULL:2008/10/28(火) 20:59:28 ID:???
>>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

ご教授お願いいたします。

105 :NAME IS NULL:2008/10/29(水) 02:37:18 ID:???
*=ってどこの方言?
というか、こういうの(*=)ってどうやってぐぐるの?

106 :NAME IS NULL:2008/10/29(水) 02:38:13 ID:???
ああ、でも雰囲気からいって 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
ここの時点でエラーがでるようです。

よろしくお願いします

108 :NAME IS NULL:2008/10/29(水) 17:51:32 ID:???
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を先に実行することを教えて頂き、解決しました。
ありがとうございました!

111 :NAME IS NULL:2008/10/30(木) 00:35:45 ID:???
>>105
そういえばこのスレだったかもしれんが、「どこの方言?」って聞いたら
いきなり火病おこしたやつがいたな。
馬鹿にされたと思ったのか、田舎にコンプレックスを持っていたのか。

112 :NAME IS NULL:2008/10/30(木) 02:37:21 ID:???
>>111
まじでw
方言確認気をつけるようにするわww

113 :NAME IS NULL:2008/10/30(木) 09:59:53 ID:???
結局、*= を使えるのはどのDBMS?
もしくは*=で検索する方法でもいいけどw

114 :NAME IS NULL:2008/10/30(木) 19:51:20 ID:???
SQL Serverみたいだな。
ttp://www.gplivna.eu/papers/sql_join_types.htm#p6.6
ttp://forums.oracle.com/forums/thread.jspa?threadID=694322&tstart=0

=* は RIGHT OUTER JOIN で、
*= は LEFT OUTER JOIN みたいだ。

115 :NAME IS NULL:2008/10/30(木) 19:52:05 ID:???
ちなみに
"asterisk equal" join
でググッタらでた。

116 :NAME IS NULL:2008/10/31(金) 00:40:34 ID:???
しまったカタカナがまずかったか

117 :NAME IS NULL:2008/11/01(土) 20:48:26 ID:???
>>4 のパターンで日付が同じデータが複数ある場合、全部持ってくるんじゃなくて 1件だけ
適当に取ってくる方法はないかなぁ。
秒数まで持ってるし、データ量や更新タイミングから言うとまず起こらないんだけど。

118 :NAME IS NULL:2008/11/01(土) 21:13:37 ID:???
>>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と同じ)にしてる。
当然逆も可能。(念為)

120 :NAME IS NULL:2008/11/01(土) 22:49:30 ID:???
117です。言うのを忘れていましたがMySQLでした。

>>118-119
うひょぉっ
本当だ。動いた。
>>4みたいにGROUP BYしたのと結合してたのが馬鹿みたいだ。

取り出し方は適当で大丈夫なので、これで完璧です。
ありがとうございます!

121 :118:2008/11/02(日) 00:44:07 ID:???
あぁ、今更なんだが、
PostgreSQLの様に独自拡張の文法が用意されているのならともかく、
MySQLのは「そんなんありか!?」って仕様だからなぁ。いつ仕様変更されるかワカランし。
これが身に染みついちゃうと、後で苦労しても知らないYO。

122 :NAME IS NULL:2008/11/02(日) 02:19:12 ID:???
>>121
まあ現行のMySQL特有ということは頭に置いておきます。
これ以外で方法なさそうだしなぁ…。

123 :NAME IS NULL:2008/11/03(月) 12:05:30 ID:???
MAXかMIN使えば普通にどのDBでも複数行から一行だけ持ってこれる。みんな普通はそうやる。
MySQLだけ仕様がおかしい。

124 :NAME IS NULL:2008/11/04(火) 00:58:32 ID:???
そうやって取得したものがいずれかの1行とは限らないからねえ

125 :NAME IS NULL:2008/11/04(火) 05:35:08 ID:???
確かに。
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

よろしくお願いします。


128 :NAME IS NULL:2008/11/04(火) 22:16:47 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による削減結果件数なども併記すべし。

131 :NAME IS NULL:2008/11/04(火) 22:57:54 ID:???
きびしー><

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万件

文法についてですが、
エラーはなく正しく実行されているのですが・・・

134 :NAME IS NULL:2008/11/04(火) 23:31:39 ID:???
>>126
それだとa_nameに代入されるb_nameの値が必ずしも一意に決まらないと思うが?

135 :NAME IS NULL:2008/11/04(火) 23:40:26 ID:???
update に from が使えるのは SQL Server か
世の中広いな

136 :NAME IS NULL:2008/11/04(火) 23:44:26 ID:???
それにしても直感的におかしな文法だな。
select 列 from 表 なら「表から列を選ぶ」だけど
update 表 set 列 = 値 は「列に値をセットして表をアップデートする」だから
from(から)の出番はないような気がするんだが。

137 :NAME IS NULL:2008/11/05(水) 02:30:42 ID:???
ほええ。
やっぱ各DBMSの方言もしっとくべきだなあ。

138 :NAME IS NULL:2008/11/05(水) 11:54:51 ID:???
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が存在する場合に行い、
共に存在しない場合は出力しない。

こんな感じでよろしくお願いします。

139 :NAME IS NULL:2008/11/05(水) 12:09:46 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) ;

140 :NAME IS NULL:2008/11/05(水) 13:32:03 ID:???
>>139
sql server に usingがなかったので一瞬焦りましたが、できました。
ありがとうございました。

141 :NAME IS NULL:2008/11/05(水) 13:45:04 ID:???
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

よろしくおねがいします

143 :NAME IS NULL:2008/11/08(土) 01:25:26 ID:???
>>142
group by して count()

144 :NAME IS NULL:2008/11/08(土) 01:47:43 ID:???
>>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;

145 :NAME IS NULL:2008/11/08(土) 02:03:02 ID:???
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をよく調べたいと思います

147 :NAME IS NULL:2008/11/09(日) 22:42:28 ID:???
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




149 :NAME IS NULL:2008/11/10(月) 16:37:34 ID:???
>>148
>>4

150 :NAME IS NULL:2008/11/10(月) 16:40:25 ID:???
A,B毎というのがよくわからんかった

151 :NAME IS NULL:2008/11/10(月) 16:42:33 ID:???
例を見る限りだと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].[登録時刻]


154 :NAME IS NULL:2008/11/11(火) 13:56:47 ID:???
>>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のみで実現は可能でしょうか?


156 :NAME IS NULL:2008/11/11(火) 22:09:27 ID:???
>>155
くだらん誤変換を放置してるようなことするからエラーが起きるんだよ。

INSERT INTO table_B SELECT 1,id,blood FROM table_A;

157 :NAME IS NULL:2008/11/12(水) 00:32:34 ID:???
>>153
A,Bでグルーピングして登録日が最大かつ登録時刻が最大の行ってことだよね
http://oraclesqlpuzzle.hp.infoseek.co.jp/10-111.html

158 :NAME IS NULL:2008/11/12(水) 04:32:53 ID:???
>>153
select a, b, max(登録日+登録時刻) from t group by a, b, 登録日+登録時刻;
こういうのってできないんだっけ?

159 :NAME IS NULL:2008/11/12(水) 09:54:51 ID:???
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から連番を付与する仕様になっています。
よろしくお願いします。


162 :NAME IS NULL:2008/11/15(土) 19:27:13 ID:???
>>161
AUTO_INCREMENT 型

163 :161:2008/11/15(土) 19:51:47 ID:x3mReOjA
>>162
IDENTITYのことでしょうか?

164 :NAME IS NULL:2008/11/15(土) 20:59:58 ID:???
答えわかってんじゃん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のレコード数を別々に
もってくればいいのは分かるのだけど。。。



167 :NAME IS NULL:2008/11/15(土) 21:50:40 ID:???
常に1を返す式と、1位のときに1を返す式を SUM して、後者を前者で割る

168 :NAME IS NULL:2008/11/15(土) 21:57:21 ID:???
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行のテーブルになるわけで、
それだけで処理が止まってしまうんじゃないかと思います。
実際のところどうなのでしょうか?

171 :NAME IS NULL:2008/11/16(日) 21:42:21 ID:???
>>170
普通はWHERE句を先に処理するなどの最適化が行われる。

それより多対多という単語の使い方を間違っていないか?
3つのテーブルの結合イコール多対多ではない。

172 :NAME IS NULL:2008/11/16(日) 21:43:43 ID:BeWlaJjJ
叩いた?

173 :NAME IS NULL:2008/11/16(日) 21:57:29 ID:???
結合するテーブルの数と一対一、一対多、多対多の間には何の関係もないな

174 :NAME IS NULL:2008/11/17(月) 04:39:34 ID:???
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;



175 :NAME IS NULL:2008/11/17(月) 06:25:14 ID:???
>>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です。
・説明
可能でしょうか。

177 :NAME IS NULL:2008/11/17(月) 20:59:27 ID:???
>>176
スレ違い

178 :NAME IS NULL:2008/11/17(月) 21:11:25 ID:???
>>168

それでできるけど、アクセスするユーザ数が多い場合は更新待ちでパフォーマンス悪いかも。

179 :NAME IS NULL:2008/11/17(月) 21:27:10 ID:???
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

180 :NAME IS NULL:2008/11/17(月) 21:30:15 ID:???
>>179
個別にやって、最大1ってことにして、それぞれ足し込めば?

181 :NAME IS NULL:2008/11/17(月) 22:00:24 ID:???
>>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;

182 :NAME IS NULL:2008/11/17(月) 22:01:53 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
とか。

前方一致とかインデックスが使える条件ならパフォーマンス的に
もう少し考えるべきところだけど、部分一致じゃどうせインデックス使えないから
テーブルスキャンを一回で済ませる形がいいかと。

183 :NAME IS NULL:2008/11/17(月) 22:02:51 ID:???
>>174
INSERT INTO TABLE_A
SELECT
B.*,
5
FROM
(SELECT * FROM TABLE_B
WHERE ID = xxxxxx) C

ではどう?
oraはAS CつけたらNGだっけ。

184 :NAME IS NULL:2008/11/17(月) 22:14:27 ID:???
>>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 |


187 :NAME IS NULL:2008/11/18(火) 22:01:20 ID:???
likeで一旦拾ってからnot likeで外してくしかないんじゃね?

188 :NAME IS NULL:2008/11/18(火) 22:02:29 ID:???
case文でゴリゴリしたらできるんじゃないかな

189 :NAME IS NULL:2008/11/18(火) 23:15:32 ID:???
状況が分からないから何とも言えないが、データの内容がGETパラメータなのであれば、以下で事足りるような?
str like '%code=58' or str like '%code=58&'

190 :NAME IS NULL:2008/11/18(火) 23:16:46 ID:???
str like '%code=58' or str like '%code=58&%'
の間違い

191 :NAME IS NULL:2008/11/20(木) 09:58:39 ID:???
http://www.jitec.jp/1_04hanni_sukiru/mondai_kaitou_2007h19_2/2007h19a_fe_pm_qs.pdf
基本情報技術者試験19年度秋午後の試験の問2で考えると下のそれぞれのSQL文ってどうなりますか?

@支店コードS01が管轄している地区をすべて求めるSQL文
A集配センターA02が管理している支店が配達を受け持つすべての地区を求めるSQL文
B一番多くの配達品を受け付けた支店のコードを求めるSQL文
C集配センターA02が管理している支店が受け付けた配達品の依頼元氏名をすべて求めるSQL文
D集配センターA02が管理している支店を通過した配達品の届け先住所をすべて求めるSQL文

192 :NAME IS NULL:2008/11/20(木) 10:05:46 ID:???
マルチするなタコ
http://pc11.2ch.net/test/read.cgi/prog/1224422384/889

193 :NAME IS NULL:2008/11/21(金) 08:39:00 ID:???
マルチのなにが悪いかいってみろ

194 :NAME IS NULL:2008/11/21(金) 13:49:07 ID:???
>>193
存在


195 :NAME IS NULL:2008/11/21(金) 19:42:28 ID:Ee0sJ6k2
マルチダさぁぁぁぁぁぁぁぁぁぁぁぁぁぁんんんんんん!!!!!!!

196 :NAME IS NULL:2008/11/21(金) 19:49:18 ID:???
ヒンギスか

197 :NAME IS NULL:2008/11/22(土) 13:56:31 ID:ai39yrzb
insert文の中に、select文を埋め込むことはできますか?

イメージ的にはこんなことがしたいです。
insert into hoge values((selec max(id) from hoge), 'hello');




198 :NAME IS NULL:2008/11/22(土) 14:04:17 ID:???
>>197
できないから、普通にこうしとけ。
insert into hoge
selec max(id), 'hello' from hoge;


199 :NAME IS NULL:2008/11/22(土) 18:25:51 ID:???
セレク

200 :NAME IS NULL:2008/11/23(日) 04:22:01 ID:???
セレク!!そこにいるのはセレク!!

お前なんだね?!

201 :NAME IS NULL:2008/11/23(日) 08:05:57 ID:???
はい、ご主人様

202 :NAME IS NULL:2008/11/23(日) 10:42:36 ID:???
エス・キューエル家の人々

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では無理ですか?

205 :NAME IS NULL:2008/11/24(月) 15:19:14 ID:???
>>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と入れるようにと問題に書かれてて混乱してました。
明日学校で聞いてみます。

207 :NAME IS NULL:2008/11/24(月) 20:29:42 ID:???
問題文をきちんと読んでないに3クエリ

208 :NAME IS NULL:2008/11/24(月) 20:42:38 ID:???
Moneyは$であることが前提なんざんしょ

209 :NAME IS NULL:2008/11/25(火) 23:27:37 ID:???
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形式です。

212 :NAME IS NULL:2008/11/26(水) 18:04:46 ID:???
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で、テーブルがあって、何か機能を付け加えろと言われたのですが、
具体的にはどんな機能が加えられるのでしょうか?
初心者なのでよくわからないんです…
ちなみに検索機能はもう実装してあります。
スレ違いかもしれませんがどうか答えていただけないでしょうか。

215 :NAME IS NULL:2008/11/27(木) 20:31:05 ID:???
そういう人間はDBをいじっちゃいけないと思うんだがなぁ w

216 :NAME IS NULL:2008/11/27(木) 20:40:36 ID:???
分析機能でも付け咥エロってことじゃないの?
統計、チャートとか

217 :NAME IS NULL:2008/11/27(木) 21:50:44 ID:???
>>214
更新可能なデータを扱うのがDBと思ってくれれば、自ずと用途が決まると思うんだけどな〜

よくあるのは社員情報や商品の在庫管理。

218 :NAME IS NULL:2008/11/27(木) 21:57:53 ID:???
>>214-217
> 何か機能を付け加えろと言われたのですが、

よくわからんのなら、こんなところでクダ巻いてないで、
言われた奴に聞き返せよ。

って言うか、釣りだろ。

219 :NAME IS NULL:2008/11/28(金) 02:19:08 ID:???
>>218
そんな冷たい事いうなよ。
Accessの入門書くらい本屋行けばいくらでもあるのに、スレ違い承知でわざわざ書き込んでるんだぞ。
それにググればいくらでも参考になりそうなサイトが見つかるのに、わざわざ書き込んでるんだぞ。

それぐらいこのスレが大好きなんだ。

もっと優しく接してあげなければ。

220 :NAME IS NULL:2008/11/28(金) 16:05:25 ID:???
やさしく接してあげた結果
SQLに全く関係のない内容で埋め尽くされたら
おまえは全裸で土下座でもしてくれるのか?


221 :NAME IS NULL:2008/11/28(金) 18:11:34 ID:???
なんじゃそりゃ

222 :NAME IS NULL:2008/11/28(金) 18:25:33 ID:???
アクセスに機能を追加するとか凄腕ハッカーじゃね?

223 :214:2008/11/28(金) 20:31:44 ID:1YXDKRyt
>>218
教えてくれないんです…
実は、学校の課題なんです。
何か一つでもいいから具体例を教えていただきたいのです。

224 :NAME IS NULL:2008/11/28(金) 20:38:41 ID:???
>>223
・DBに対するフォームが存在して、それに検索機能は実装してある。
これに機能を追加するということでいいの?
今ある機能がCRUDのうちRだけなのであれば、CでもUでもDでも作ればいい。
Rを強化するんであれば、検索条件の細分化でもすれば?

225 :214:2008/11/28(金) 20:50:09 ID:1YXDKRyt
>>224
それは駄目なんです。

226 :NAME IS NULL:2008/11/28(金) 20:51:36 ID:???
ここは課題を代わりにやってあげるスレじゃないから。

今まで出てきたヒントで十分だろ。

227 :NAME IS NULL:2008/11/28(金) 20:52:14 ID:???
>>225
はぁ。いったい何がしたいのか分からん。
テーブル増やすとかそういうことをしたいの?

228 :NAME IS NULL:2008/11/28(金) 20:53:45 ID:???
つーか、SQL 関係ないからスレ違いだな。
これ以上荒らさないでね。お願いだからさ。

229 :NAME IS NULL:2008/11/28(金) 20:56:52 ID:???
CRUD関連の追加がだめなら確かにスレ違いだな
レコードのファイルパスカラムのデータを元にフォームに画像を表示とか、、、まあどうでもいいや。スレ汚しごめん

230 :NAME IS NULL:2008/11/28(金) 22:59:04 ID:???
つーか、宿題スレとか Access スレとか行くとこいっぱいあるだろ。
楽したいなら、にちゃんとかグーグルの検索ぐらい覚えろよ。

しつこくアゲてるから、どうせ釣りなんだろうけど。

231 :NAME IS NULL:2008/11/28(金) 23:08:46 ID:???
質問者だからIDのためにageてんじゃないの?

232 :NAME IS NULL:2008/11/29(土) 09:42:04 ID:???
おこちゃまなんだよ

233 :NAME IS NULL:2008/11/29(土) 23:21:15 ID:???
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言語はほとんどわかりません。
そんな人居ますか?

235 :NAME IS NULL:2008/11/30(日) 00:59:52 ID:???
数学関係無いし

236 :NAME IS NULL:2008/11/30(日) 12:37:14 ID:???
>>234
SQL だけだと無理でしょ。
チューニングとかのノウハウ持ってるなら何とかなると思うけど、
そう言うやつはこんな質問しないだろうし。

237 :NAME IS NULL:2008/11/30(日) 12:37:21 ID:???
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 みたいにかければよかったんだけど・・・

239 :NAME IS NULL:2008/12/01(月) 01:24:11 ID:???
maxなものを1つだけとは、
col1 2006年 col2 2007年 col3 2008年 とあったら、col3がほしいてことです。

ID惜しい・・・

240 :NAME IS NULL:2008/12/01(月) 08:29:27 ID:???
DBMSの方言もしくは提供ファンクションを使わない限りはcase文ですっきり書くしかないと思うよ。

241 :NAME IS NULL:2008/12/01(月) 19:55:15 ID:bNYYQYag
>>236
チューニングって
既存システムのDB改修の事?
それとも
OracleなどDBソフトの機能のカスタマイズの事?

242 :NAME IS NULL:2008/12/01(月) 21:11:03 ID:???
>>241
パフォーマンス上げる為の調整のことだと思うけど?

243 :NAME IS NULL:2008/12/02(火) 01:39:25 ID:???
それならできるよ!とか、そういう考えを持ってたんだろうか?
プランを見て、ああ、これにインデックス貼らなくっちゃ。とかそんな程度のチューニングはその辺の
PGでもできて当たり前で、DBで食っていくためには規模、システム構成にあわせたメモリチューニング
だったり物理ファイルの配置レイアウトを考えたり、最低でもそういったことが求められるんじゃないかな。
俺はただのPGなのでその辺を任せられる人がいたら助かるなあと思うこともあるよ。

244 :NAME IS NULL:2008/12/02(火) 11:16:37 ID:2PdMcQOD
>>242
>>243
様は処理速度は速くするためにDBをSQLでチューニングするって事ですね。
でも現在は処理速度の速いCPUと大容量のメモリを使用できる時代に不思議ですね。
よほどスペックの低い鯖がたくさんのこっているのでしょうね。

245 :NAME IS NULL:2008/12/02(火) 11:54:20 ID:???
いつまでも あると思うな メモリと親のすね

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です。

247 :NAME IS NULL:2008/12/02(火) 16:13:33 ID:???
>>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);

248 :NAME IS NULL:2008/12/02(火) 18:28:10 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を書けばいいか教えてください


249 :NAME IS NULL:2008/12/02(火) 19:09:41 ID:???
>>248
ヒント:ifnull()もしくはcoalesce()

250 :NAME IS NULL:2008/12/02(火) 20:49:39 ID:???
>>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
↑このようにしたほうがいいということですか?

252 :NAME IS NULL:2008/12/02(火) 21:33:03 ID:???
Subtableに"ID:0 name:noitem price:0 ..."を突っ込んで、item2のnullの
代わりに0を使う、みたいな。

253 :NAME IS NULL:2008/12/02(火) 21:48:50 ID:???
>>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

テーブル設計を見直すならそのほうがいいけど
その場合は結果の出し方も考え直したほうがいい

254 :NAME IS NULL:2008/12/02(火) 22:13:14 ID:???
>>251
costすごそうね

255 :NAME IS NULL:2008/12/02(火) 22:46:05 ID:???
>>244
SQL で チューニングって何か勘違いしてないか?
スペック云々で不思議がるってことはほとんど何もしたことがないからなんだろうか。

例えば、低スペックマシンで3時間かかるクエリがあって、それを高スペックマシンで
動かしたら10分で終わるようになりました。
けれど、インデックス、DBの設定を見直すことで、低スペックマシンでは20秒で
終わるようになりました。

こういうことが当たり前に起こる世界なので、高スペックなのに遅いのは単に処理が
面倒だからで片付けるのではなく、適切な設定などを行った上でも遅いのかどうかを
吟味する必要がある。

256 :248:2008/12/02(火) 23:04:16 ID:???
>>253
そんなにすっきり結合させる方法があったのですね。もっと精進しなくては・・・
どうもありがとうございました。

257 :NAME IS NULL:2008/12/02(火) 23:40:49 ID:???
>>255
なんか説得の方向性が間違ってるような。

低スペックで3時間かかるものを高スペックに変えただけで10分になるとする。
しかし低スペックのままでもチューニングによって20秒まで縮めることができるとする。
あなたはどちらを選びますか?

みたいな感じじゃね?

もちろんチューニングにかかる人件費より高スペックに変える設備投資のほうが
安くて効果も充分だと思えばそういう選択肢もアリなわけで。

258 :NAME IS NULL:2008/12/03(水) 01:21:05 ID:???
まあチューニングでごろっと変わるのはぼらくるだと思う。
MSSQLは普通に使っても効率よく動いてくれる。

259 :NAME IS NULL:2008/12/03(水) 10:03:15 ID:???
えーと、どんなヘタなSQLでも、ですか?

260 :NAME IS NULL:2008/12/03(水) 12:54:40 ID:???
DB自体の設定じゃないの?

261 :NAME IS NULL:2008/12/03(水) 17:51:40 ID:???
Oracleも6〜7.3ぐらいまでなら、
DBの設定やcreateやりなおし技術とSQLの最適化だけで食うことができたが
今はどうなんだ?
設定ぐらいで劇的に変わるの?


262 :NAME IS NULL:2008/12/06(土) 13:58:04 ID:???
>>244
プロセスが使えるメモリ空間の最大知ってる?

チューニングだけ専門に人をつけるってことは
その金を払うだけのメリットを見込める規模があるってことだよ
そもそも構築後の環境変更にかかる工数って
ただ買ってきたメモリを挿せばいいってレベルじゃない
当然ながら全テストやり直し
影響範囲の狭いやり方は常に求められる
最新スペックですら32ビットの壁で苦労してんだよ

話を最初に戻すけどSQL専業って工数圧縮の為に
派遣にやってもらうってことはあるけどSQLだけやってればいい上位職ってないと思うよ

DB構築時に全体を見渡せる人って重宝されるけどな
まぁ、PGっていうよりインフラ系になるんだろうが・・・

263 :NAME IS NULL:2008/12/06(土) 20:11:39 ID:???
> その金を払うだけのメリットを見込める規模があるってことだよ
> 最新スペックですら32ビットの壁で苦労してんだよ

規模がどうのこうの言う割には、32bit って... 馬鹿ですか?

264 :NAME IS NULL:2008/12/07(日) 02:30:22 ID:???
>>263
確かにとっとと64Bit環境に移行しろよと思うことはある。
だけどなぁ、同じ鯖上で動くアプリが32bitでしかテストしてないとか色々理由があって、
64bitに出来なかったりすんのよ。

64bitOSでDB鯖作って、アプリは別鯖に切り出せよとかは無しな。

265 :NAME IS NULL:2008/12/07(日) 09:16:06 ID:???
規模がどうのこうの言う割には、DBとAPが同じ鯖 って... 馬鹿ですか?

266 :NAME IS NULL:2008/12/07(日) 09:42:44 ID:???
規模とかそういうのはスレ違いです。

267 :NAME IS NULL:2008/12/08(月) 11:52:58 ID:???
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つけ忘れてました

269 :NAME IS NULL:2008/12/08(月) 19:40:43 ID:???
このスレで初めてワロタ


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を書けばいいか教えてください。
よろしくお願いします。

271 :NAME IS NULL:2008/12/13(土) 01:02:50 ID:???
>>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

273 :NAME IS NULL:2008/12/13(土) 02:52:08 ID:???
質問です。

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については見つけられなかったので、
どなたか分かる方がいらっしゃれば助言をよろしくお願いします。

274 :NAME IS NULL:2008/12/13(土) 02:54:19 ID:???
あ、ソフトウェアはmySQLです。

275 :NAME IS NULL:2008/12/13(土) 05:35:18 ID:???
update と参照(select)の相対頻度、総レコード数などの諸元によるのでは。
update は、24時間に一回未満(だって日付しか記録してない)、
select は、5分に一回とかいうなら、レコード数によっては index 張り直しても引き合いそう。


276 :NAME IS NULL:2008/12/13(土) 12:08:19 ID:???
>>273
> インデックス化させた方が良いのどうか判断出来ずにいます。

測定すればいいだけだろ。

277 :270:2008/12/13(土) 13:54:35 ID:S9gQei/+
>>271,272 様
ありがとうございます。早速やってみます。

278 :NAME IS NULL:2008/12/13(土) 22:21:01 ID:???
質問です

Web上で年と月を指定するとその月の勤務表が現れるようにしたくて
日付を年月と日に分けて、IDと合わせ3つのフィールドで管理したいと思います

初歩的な質問だと思うのですが
日付を年月と日に分けるにはどうしたら良いのでしょうか?
また実際のデータの記述はどのように分かれているのでしょうか?

どなたか教えて頂けないでしょうか?

279 :NAME IS NULL:2008/12/13(土) 22:27:17 ID:???
>>278
日付型ファンクションは処理系によって全然違うけど
一般的には文字列型に変換してからsubstr系の関数じゃね?

> 実際のデータの記述はどのように分かれているのでしょうか?
は質問の意味がワカンネ

280 :NAME IS NULL:2008/12/13(土) 22:51:18 ID:???
日は要らなくね?年と月に分けるならわかるけど
てかSQLの質問なんだろうか・・・

281 :NAME IS NULL:2008/12/13(土) 23:24:28 ID:???
質問させてください。
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です。

282 :NAME IS NULL:2008/12/13(土) 23:30:38 ID:???
>>278
> 日付を年月と日に分けて、IDと合わせ3つのフィールドで管理したい
> と思います

年月とに日に分ける?
日付は普通に日付型で管理した方がいろいろな組み込み関数が使えるか
ら分けないほうがいいと思うぞ。

>>280
勤務表だからデータとしては、日までいるだろうと思う。
ただ、>>278 の質問がいまいち要領を得ないので、なんとも言えないけど。

283 :NAME IS NULL:2008/12/13(土) 23:51:56 ID:???
>>281
俺は同じだと思うけど
中には左辺にしかインデックス使わないとかいう処理系もあるのかもね

284 :NAME IS NULL:2008/12/13(土) 23:55:13 ID:???
>>278
日付は1つの列で扱った方が、他のRDBMSやSQL上での比較に使いやすいよ。
下手に年月日で分けると単純な日付の比較でcastが必要な気がする。

2009/1/1 > 2008/12/31
等が実現できるDATE型をおすすめします。

285 :NAME IS NULL:2008/12/14(日) 00:39:00 ID:???
>>281
> と書いたのですが人に指摘され

昔の覚えた変な知識から脱却できないじじいの
言うことなんて無視しとけばいい。

286 :NAME IS NULL:2008/12/14(日) 01:09:27 ID:???
年月しか分からないから年月日のフィールドではダメだから分けるしかない><とか。
y年m月1日 <= 年月日 < y年m+1月1日 で指定年月のレコードとれるよ

287 :NAME IS NULL:2008/12/14(日) 01:11:23 ID:???
>>285
古い知識がまだ有効であるような環境かもしれないじゃないか。

その書き方の差で結果が変わってた時代があるなんて俺には想像もつかないが。。。
けどきっとなんかあったんだろうなぁ。

288 :NAME IS NULL:2008/12/14(日) 01:37:44 ID:???
>>280
> 年月しか分からないから年月日のフィールドではダメだから
> 分けるしかない><とか。

そういう時でも、便宜的に日のフィールドは1日固定にしとくとか
したほうがいいと思う。

>>227
> 古い知識がまだ有効であるような環境かもしれないじゃないか。

その状況で「自分で調べろと言われた」んだったら、職場から腐っ
てるんだろう。

289 :NAME IS NULL:2008/12/14(日) 10:46:39 ID:???
質問です。
もともとはhtmlのみで作っていたのですがデータが変更になると関連ページすべてを
手作業でしなければならなくなり修正が大変になるので、DBからデータを参照して
HTMLを生成するPHP+SQLというものを最近知りました。
調べていくうちにセキュリティの項目にぶちあたったのですが、データを参照するのみで
サイト利用者がデータを追加したり検索したりといった入力フォームがない場合でも
SQLインジェクションというものを考慮した方がいいのでしょうか。


290 :NAME IS NULL:2008/12/14(日) 10:49:16 ID:???
>>289
スレ違い。

HTML から SQL を投げる形であれば、いずれにせよ SQL インジェクションの対応は必須。

291 :NAME IS NULL:2008/12/14(日) 11:16:19 ID:???
>>290
該当するようなスレが見当たらなかったのですが失礼しました。
SQLインジェクションは考慮する形で調べてみようと思います。

292 :NAME IS NULL:2008/12/14(日) 11:20:38 ID:???
>>291
DB な話じゃなくて、DB に投げるまでの話だから。

Web 技術とかム板とかかね。

293 :NAME IS NULL:2008/12/14(日) 20:44:40 ID:???
prepared statement が有効だから、必ずしもDBの前の話とは限らないのでは。
prepared statement を使うと、ちゃんと実行計画してくれない、とかいう話が絡んでくるから。

294 :NAME IS NULL:2008/12/16(火) 16:06:39 ID:???
場合によってはSQLインジェクション気にする必要はないけどね。
今回の話で行けば対応すべき箇所がないということになってそうに思う。

295 :NAME IS NULL:2008/12/16(火) 20:30:04 ID:???
こんばんは。
下記のような処理を実施したいのですが、
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



296 :NAME IS NULL:2008/12/16(火) 20:45:47 ID:???
select col1, col2, col3, max(col4) from table_a group by col1, col2, col3
以外のレコードを削除すれば良いのでは

297 :NAME IS NULL:2008/12/16(火) 20:55:20 ID:???
こうかな?(未検証)
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)

298 :NAME IS NULL:2008/12/16(火) 21:21:14 ID:???
Oracle10gを使っています。
確か、サブクエリーが使えない句があったと思うのですが
忘れてしまったので教えていただけませんか。
よろしくお願いします。

299 :NAME IS NULL:2008/12/18(木) 07:20:13 ID:???
次のような演算をしたいのですが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を買っていても他の商品を買っていると
取ってきてしまいます。どうしたらいいでしょうか?



300 :NAME IS NULL:2008/12/18(木) 07:30:11 ID:???
>>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つにしぼりたいのです。お願いします。

302 :NAME IS NULL:2008/12/18(木) 12:53:49 ID:???
>>301
その要件と質問から読みとるあなたのスキルなら、
悪いことは言わないから外注に出すことをおすすめする。

303 :NAME IS NULL:2008/12/18(木) 12:56:16 ID:???
やろうとしていることはシステム構成設計そのものだからな。
幅広い知識が求められる。
まあ、それ以前にスレ違い。

304 :NAME IS NULL:2008/12/18(木) 22:43:52 ID:???
おれも >>302 に一票。

て言うか、お願いされたやつに「できません」と言えよ。

顧客の個人情報なんて一番危ないやつだから、

> ・個人情報なのでセキュリティはしっかりと

のところでミスすると下手したら会社傾くぞ。

305 :NAME IS NULL:2008/12/19(金) 00:39:57 ID:???
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になってしまいます

308 :NAME IS NULL:2008/12/19(金) 07:46:42 ID:???
inner join

309 :NAME IS NULL:2008/12/19(金) 07:54:45 ID:???
item.id が null なら 0、非null なら 1 として sum()

310 :NAME IS NULL:2008/12/19(金) 08:22:59 ID:???
count(*)をcount(i.categoryId)にすればいいだけでは?

311 :NAME IS NULL:2008/12/19(金) 08:34:53 ID:???
>>308-310
ありがとうございました
勉強になりました

312 :NAME IS NULL:2008/12/19(金) 15:43:09 ID:???
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



313 :NAME IS NULL:2008/12/19(金) 15:57:01 ID:???
オールカラムのデータをコンテインしてないからじゃないのかな

314 :NAME IS NULL:2008/12/20(土) 11:50:46 ID:NTPL7EOm
自己非等値結合とは、どのような概念でしょうか?

315 :NAME IS NULL:2008/12/20(土) 12:08:11 ID:???
>>314
>>297とかかな

316 :NAME IS NULL:2008/12/20(土) 15:22:24 ID:???
>>313
意味がわかりません

317 :NAME IS NULL:2008/12/20(土) 21:41:23 ID:???
どうしたらそれが出たのかも書いてくれないか

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 〜〜〜となります。

319 :NAME IS NULL:2008/12/20(土) 23:03:19 ID:???
エラーをそのまま読むとデータの列が足りないように見えるが

320 :もくもく:2008/12/20(土) 23:38:21 ID:vBt0wfGB
テーブルのカラムに flag1, flag2, flag3 があり、すべて ブール型であるとします。
これらを1つの整数型のカラム flags のビットで表現するように変更したいのですが、
パフォーマンスの劣化や、プログラムの保守性の低下などは、あり得るでしょうか?

321 :NAME IS NULL:2008/12/20(土) 23:42:50 ID:???
create index test_f1 on test(flag1);
のようなインデックスが張れなくなるから、
フラグの有無を検索するときのパフォーマンスが劣化するよ

322 :もくもく:2008/12/20(土) 23:44:12 ID:???
>>321
なるほどそうですね。

323 :NAME IS NULL:2008/12/21(日) 15:05:27 ID:E9EuX9rA
select 0x000a

などとしたとき、10と数値で表示したいです。
しかしmysqlではblob型として認識されてしまいました。
どのように記述すれば良いでしょうか?
mysql以外のDBMSでの情報でも構いません。


324 :NAME IS NULL:2008/12/21(日) 16:11:51 ID:???
>>319
列の多いテーブルはどうやって作るんですか?

325 :NAME IS NULL:2008/12/21(日) 18:06:17 ID:???
列をたくさん記述してある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だったりすることはありません。



327 :NAME IS NULL:2008/12/26(金) 11:59:37 ID:???
>>326
それをSQLでやるのは無理だと思うし、やったとしても、テーブルに格納する情報が足らなすぎる。
昔、駅すぱあとの開発記事かなにかで、駅から駅への方向情報や位置情報とかも情報として
持ってるとか書いてあるのを見た事がある。
「経路が何通りあるか?」ってアミダみたいな上から下な構造ならまだしも、電車の駅みたいな
構造だと、単純に経路を求めると何万通りとかザラにあると思うんだけど…。
で、どう絞るかって方法が重要で、その方法の1つとして方向情報や位置情報とかが出てくるんだろう。


328 :NAME IS NULL:2008/12/26(金) 13:15:32 ID:???
>>326
WITH RECURSIVE か CONNECT BY が使えるDBならいけそうな気がする。
気がするだけで本当に出来るかどうかわからんけど、じっくり考えると面白そうだな。

329 :NAME IS NULL:2008/12/26(金) 16:55:07 ID:???
実用なのか頭の体操なのかハッキリさせた方が良いかも。
実用なら頂点数などに関して大体のオーダーも。

330 :NAME IS NULL:2008/12/26(金) 23:15:59 ID:???
再帰でできそうなきがする

331 :NAME IS NULL:2008/12/26(金) 23:50:13 ID:???
部署、上位部署とかならともかく
山手線とか無限ループだぞ

332 :NAME IS NULL:2008/12/27(土) 10:30:12 ID:???
>>326
このあたりを一読することをお勧めする。
一番下の例がかなり近い。
http://www.atmarkit.co.jp/fnetwork/tokusyuu/01sql99/sql99_1b.html

>>331
わざわざ馬鹿だということを公表しなくてもいいのに...。

333 :NAME IS NULL:2008/12/27(土) 13:49:18 ID:???
>>332
軽く読んだけど、その記事の無限ループの回避策は不十分だと感じた。
パリを含む閉路は排除出来るけど、そうでない閉路(アメリカ一周とか)に
関してはやはりループに陥る。

ループを回避するには出発地や目的地についてではなく経路に関して
制約をかける必要があって、具体的にはin.経路にout.出発地が含まれ
ない事を調べる必要がある。
となるとin.経路をlike条件でしらべるか、in.経路をそれこそMULTISET型
とかの集合型にする必要があると思う。
いずれにしても経路カラムの内容はatomicでは無くなるのでSQLで書ける
にしてもなんか気持ち悪いなぁと思う。

334 :326:2008/12/27(土) 14:57:01 ID:dqX7NECP
おお、知らない間にたくさんレス、ありがとうございます。

>>332
参考になりそうなサイト紹介サンクス。

>>331
同じ駅は二度利用しないって制約があっても無限ループになるんですか?
しかも、駅間すべてにリンクがある訳じゃないんだけど。

>>327
格納する情報とは?
別に(ここでは)料金とか最速便とかを考慮しないんですけど。
むしろ、料金や時刻に関わらず、経路だけを見つけるということで、駅スパートなどより単純かと。



335 :NAME IS NULL:2008/12/27(土) 16:41:39 ID:???
>>333
> パリを含む閉路は排除出来るけど、そうでない閉路(アメリカ一周とか)に
> 関してはやはりループに陥る。

そもそも元ネタが閉路じゃないのに何を言ってるんだ?

>>334
>>331=>333 は、無視していいよ。

336 :NAME IS NULL:2008/12/27(土) 16:44:50 ID:???
なんか妙にケンカ腰のヤツが来たなw
コテハン入れてくれNG登録するから。

337 :NAME IS NULL:2008/12/27(土) 16:56:57 ID:???
お前がコテハンつけたほうがいいと思うぞ。

338 :333:2008/12/27(土) 17:10:30 ID:???
>>335
自分は331じゃないのですが・・・
元ネタは>>326の事だと思うのですが、この文中の

>>もちろん、同じ液を二度利用するようなことはありません。

この制約が、与えられた元データによって保障されているのか、
(駅:Node, 便:Edgeで表現された有向グラフが閉路を含まないか)
それともクエリで実現するのかの、解釈の違いだと思います。

前者であれば確かに単純な再帰で実現できます。
ただ自分は後者の事だと読んだのですが・・・

339 :NAME IS NULL:2008/12/27(土) 17:23:22 ID:???
>>335
閉路がないグラフの任意の2点間に経路がいくつあると思ってるんだ?

340 :NAME IS NULL:2008/12/27(土) 17:44:04 ID:???
>>338
それを解釈して適切なクエリを作成するのは >>326 本人だよ。
どんぴしゃのサンプルでないとだめな人なのか?

あと、MULTISET と atomic とか使うならちゃんと理解してから使ったほうがいい。
>>333 の文脈だとほとんど意味不明だよ。

>>339
自分で数えたらいいんじゃね。

341 :NAME IS NULL:2008/12/27(土) 17:44:33 ID:???
あーなんか過剰反応してる人がいるけど
>>331>>330へのレスね。

342 :NAME IS NULL:2008/12/27(土) 17:57:08 ID:???
馬鹿の上塗り?

343 :NAME IS NULL:2008/12/27(土) 18:01:14 ID:???
>>342
病んでるなぁ。
いい病院紹介するよ

344 :NAME IS NULL:2008/12/27(土) 18:11:06 ID:???
>>340
>>339が反論だということすら理解できんのか。
回りくどすぎたかな

345 :NAME IS NULL:2008/12/27(土) 18:11:17 ID:???
もしかしてなんか悔しかったの?

今後レスするなら、

> 山手線とか無限ループだぞ

について、説明してからにしてね。(w

346 :NAME IS NULL:2008/12/27(土) 18:12:42 ID:???
再帰でとれば無限ループだろ。
理解できないなら入門書でも読め。

347 :NAME IS NULL:2008/12/27(土) 18:16:53 ID:???
あおりたいだけのヤツは放置で

348 :NAME IS NULL:2008/12/27(土) 18:31:27 ID:???
>>346
> 再帰でとれば無限ループだろ。

もしかして、

int foo()
{
 foo();
}

で、うまく動かんと騒いでるレベルですか?(w

349 :NAME IS NULL:2008/12/27(土) 19:30:57 ID:???
>>340

>>335
>そもそも元ネタが閉路じゃないのに何を言ってるんだ?

そもそも元ネタ(>>326)に「閉路じゃない」なんて書いてますか?
書いていないのであれば、>>335の指摘は適当ではありません。

私には書いてあるように思えませんし、閉路を含む場合に関して
atmarkの記事での回避策は不完全です。
ですので>>333のように書きました。

350 :NAME IS NULL:2008/12/27(土) 19:55:37 ID:???
> それを解釈して適切なクエリを作成するのは >>326 本人だよ。
> どんぴしゃのサンプルでないとだめな人なのか?

351 :NAME IS NULL:2008/12/27(土) 19:56:31 ID:???

>なお、AとBの格納順序には規則性があり、A|BだったりB|Aだったりすることはありません。

と書いていることから有向ではないと考えられるし、そうであるならば、複数の経路を求めることを
想定していることから、閉路の存在を禁止してはいないと解釈するのが当然の帰結だわな。

352 :NAME IS NULL:2008/12/27(土) 20:22:52 ID:???
はいはい、君は正いよね。
これで満足かな。

353 :NAME IS NULL:2008/12/27(土) 20:26:50 ID:???
さんざん因縁つけて反論できなくなるとこれだよ。
マジコテハン付けてくれ。

354 :NAME IS NULL:2008/12/27(土) 20:33:42 ID:???
>>351
ともあれ元ネタから閉路の存在の禁止は読み取りがたいんです。
なので突然>>335の様に否定されたときには少しカチンときました(笑)。

ともあれ、閉路が存在すると仮定して、閉路を含まない単純パスだけを
列挙するSELECT文って、綺麗に書けますか?
>>333に書いた通り、likeや集合型を使う解は思いつきますが・・・

355 :NAME IS NULL:2008/12/27(土) 20:53:43 ID:???
そもそも >>335>>333 へのレスなんだから、元ネタ = >>326
じゃなくて、「その記事」の意味で書いてるし、文句をつけたい
なら「その記事」の著作者に言ってくれ。

要するにもう少し落ち着け。
でないと、>>353 みたいな奴が沸いてくるから。

356 :NAME IS NULL:2008/12/27(土) 21:12:18 ID:???
>>355
え〜、それなら。

>>335
>>>331=>333 は、無視していいよ。

無視しないで〜(笑)。いきなり無価値にされてたのもカチンの一つ。

閉路を含むグラフ一般に関しては「その記事」の方法は不完全。
でも元ネタ(>>326)からは閉路を含む可能性もあると読み取れたので
「記事の方法は不完全だよ」と指摘したのが>>333です。

この指摘、無価値ですか?

ともあれ、WITH RECURSIVEを使って単純パスの列挙、どう書きましょうか。
上手い方法、ありますか?

357 :NAME IS NULL:2008/12/27(土) 22:32:09 ID:???
人が紹介した記事についていきなり、

> 「記事の方法は不完全だよ」

と書けばカチンとこないとでも思っているんだろうか...。

358 :NAME IS NULL:2008/12/27(土) 22:35:43 ID:???
>文句をつけたいなら「その記事」の著作者に言ってくれ。
とか完全に逃げの姿勢だし、カチンと来ないんじゃないの。
「貼っただけ、中身は知らん」と思ってるかと。

359 :326:2008/12/27(土) 22:41:56 ID:dqX7NECP

うわ、なんでこんなに荒れてるんですか? もしかして僕の質問が悪かった??

閉路ってのは、出発駅に戻ってしまうことですか?
それだったら、なしです。「ある駅から、出発駅以外の駅に、同じ駅を2回経由せずにたどり着くルート」と書けば良かったのでしょうか。

360 :NAME IS NULL:2008/12/27(土) 22:56:33 ID:???
>>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

361 :NAME IS NULL:2008/12/27(土) 22:58:10 ID:???
ごめんなさい、R1間違えました。

[R1]
1|A|B
2|B|C
3|C|D
4|E|B


362 :NAME IS NULL:2008/12/27(土) 23:01:37 ID:???
あまり子供がいなくてあれない板だと思うんだけど
>ともあれ、WITH RECURSIVEを使って単純パスの列挙、どう書きましょうか。
>上手い方法、ありますか?
とかには決して答えず、「記事書いたヤツに文句言え」「人が紹介した記事にケチつけやがって」とか
ヒステリックにわめくだけのヤツがいるからねぇ。

363 :NAME IS NULL:2008/12/27(土) 23:42:19 ID:???
冬休みだよ

364 :NAME IS NULL:2008/12/27(土) 23:58:02 ID:???
親子関係のあるテーブルについての質問です

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を使用しております。

365 :NAME IS NULL:2008/12/28(日) 00:35:03 ID:???
前者は
SELECT 親コード,子コード,数量 FROM
(
SELECT 0 親子区分,子コード,数量 FROM Bテーブル
UNION ALL
SELECT 親子区分,商品コード,0 FROM Aテーブル WHERE 親子区分 = '1'
)
ORDER BY 区分,親コード,子コード
とかか。
後者はWHERE 親コード >= 指定した値、とかくっつければいいんでないの。

366 :NAME IS NULL:2008/12/28(日) 00:43:56 ID:???
親と子が多対多ってどんな商品?

367 :NAME IS NULL:2008/12/28(日) 00:54:58 ID:???
ざっくばらんに言うと、目的が分からない
親の数量は常にゼロで、子の数量がでればいいの?
指定した商品コード以下、というのは文字列としての「以下」という表現?

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
何をもって(上記の関係の場合)左側とするかは情報として持つ必要があるので
そういう意味で「方向情報や位置情報」が出てくる。

371 :NAME IS NULL:2008/12/28(日) 04:35:29 ID:???
頭の体操なのか、実務なのかどっちなんだろう。
実務だと同じ顧客に二度逝く事は有るよ。本当に二度利用しないって仕様で変更は無いの?
ある程度の想定もして仕様を決めておかないと、設計が崩れて実務では酷い事に成ると思う。

372 :NAME IS NULL:2008/12/28(日) 13:22:20 ID:???
>>360
> でも記事の方法が閉路を含むグラフ一般に関して不完全(ですよね?)
> なのは仕方がないです。改善策を探すしかないかと。

記事中の図とテーブルのデータ見ればわかると思うが、記事は別にグラ
フ一般に対応できるなんて言ってなくて、単方向のみのデータになって
るだろ。

それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う
のはどうかと思うぞ。

>>362
紹介したんだから記事の責任負えとか...、馬鹿ですか。
まあ、煽るしかできない子なんだろうけど。

373 :NAME IS NULL:2008/12/28(日) 13:25:53 ID:???
>記事は別にグラフ一般に対応できるなんて言ってなくて、単方向のみのデータになって
>るだろ。
>それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う
>のはどうかと思うぞ。

そういう、条件に合わない記事を紹介するオマエが不完全って話だろ

374 :NAME IS NULL:2008/12/28(日) 13:34:08 ID:???
もうそいつの相手はいいだろ。
「ボクちゃんが紹介した記事完璧!最高!」
「ちょっとでも異議があるヤツは馬鹿!死ね!」って繰り返してるだけじゃん。

375 :NAME IS NULL:2008/12/28(日) 13:52:42 ID:???
>>365が微妙に間違ってたので訂正

SELECT 子コード 商品コード,数量 FROM
(
SELECT 0 親子区分,親コード,子コード,数量 FROM Bテーブル
UNION ALL
SELECT 親子区分,商品コード,商品コード,0 FROM Aテーブル WHERE 親子区分 = '1'
)
ORDER BY 親コード,区分 DESC,子コード

>>369の「子商品を軸とした抽出」については
上記SQLをWHERE 親子区分 = '0'にして、親コードの変わりに子コードで並べ替えて…とかで行けると思う

376 :NAME IS NULL:2008/12/28(日) 14:33:40 ID:???
>>373-374
> そういう、条件に合わない記事を紹介するオマエが不完全って話だろ

>> どんぴしゃのサンプルでないとだめな人なのか?

まあ、>>326=>>334 が参考にしてくれそうなので、雑魚はどうでもいいんだが。

377 :NAME IS NULL:2008/12/28(日) 14:42:49 ID:???
>> どんぴしゃのサンプルでないとだめな人なのか?
そこから「記事では不十分な部分をどうするか」みたいな話をしたら
「人が紹介した記事にケチ付けやがって」みたいに顔真っ赤にしてわめいちゃうんだったら
どんぴしゃのサンプル紹介してもらわないとなぁ。

378 :NAME IS NULL:2008/12/28(日) 15:07:38 ID:???
> 「記事では不十分な部分をどうするか」

の話については、>>326 が自分で考えるなりもっと良いサンプルを見つけ
るなりすればいいだけのこと。もしくはお前さんが示してやればいいん
じゃね? 残念だが、俺には興味がないからどうでもいい。

俺が指摘してるのは、>>372
> それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う
> のはどうかと思うぞ。
の部分だけだよ。

この違いが本気でわからないなら、かわいそうな人だと思うしかない。
まあ、煽るしかできない子なんだろうけど。

379 :NAME IS NULL:2008/12/28(日) 17:08:17 ID:???
>>372
>記事は別にグラ フ一般に対応できるなんて言ってなくて、単方向のみの
>データになってるだろ。
>それに対して、勝手にグラフ一般なんて条件持ち出して不完全とか言う
>のはどうかと思うぞ。

この辺りは>>349, >>354, >>356で何度か説明しました。

「閉路を含むグラフ一般」という条件は、勝手に持ち出した条件では
ありません。元ネタ(>>326)からは閉路の存在を否定出来ないため、
設定せざるをえなかったものです。この条件は自分だけではなく、
>>331>>327も考慮の対象としていました。

もう一度繰り返しますが、元ネタ(>>326)に対して記事の手法は
不完全である可能性があります。

不完全である可能性があるのであれば、その事を指摘した>>333
を元ネタ(>>326)の主に対して「無視しろ」とした>>335のレスは妥当
ではありません。私のクレームはこの一点です。
異論があるのであれば、何故元ネタ(>>326)において>>333を無視
して問題が無いのか、元ネタ(>>326)の技術を元に説明して下さい。

あとここからは個人的感想になりますが、誰かに問題を解くための
参考を示す時は、大抵はその参考を用いて問題を解く方法の見通し
をつけてから自分は行います。なるべく的確な解を示したいですから。

で、元ネタ(>>326)の問題に対するWITH RECURSIVEを用いた解法
に関して、現在何か見通しはありますか?
そもそも「記事」を紹介した際に、元ネタ(>>326)における閉路の存在
の可能性は考慮していましたか?

380 :NAME IS NULL:2008/12/28(日) 17:11:15 ID:???
>>379
typo 「元ネタ(>>326)の技術を元に」 -> 「元ネタ(>>326)の記述を元に」

381 :NAME IS NULL:2008/12/28(日) 17:58:37 ID:???
まともなレス1回も貰ったこと無いだろうによく頑張るなw
中身について語れないから逃げ続けてるだけの奴だよ。

382 :NAME IS NULL:2008/12/28(日) 20:05:21 ID:???
>>379-380
何回も書いてるけど、俺は「かなり近い」とは書いたけど、どんぴしゃとは
書いてない。
閉路を含むかどうかは >>326 しかわからんし、>>332 で紹介した記事が役
に立たないと思えば無視すればいいだけのこと。

> 誰かに問題を解くための参考を示す時は、大抵はその参考を用いて問題を
> 解く方法の見通しをつけてから自分は行います。なるべく的確な解を示し
> たいですから。

別にその姿勢は批判しないけど、その姿勢を人に押し付けないでくれ。

> 元ネタ(>>326)における閉路の存在の可能性は考慮していましたか?

全然してないよ。あくまでも参考だし、>>378 にも書いたけど興味ないし。

あと >>333 を無視しろと書いたのは、

> MULTISET型とかの集合型
> 経路カラムの内容はatomicでは無くなる

と意味不明のこと書いてるから (>>340 で指摘済み)

>>381
お前も、よくがんばるね。
馬鹿みたい。

383 :NAME IS NULL:2008/12/28(日) 20:33:35 ID:???
>>382
>別にその姿勢は批判しないけど、その姿勢を人に押し付けないでくれ。

押しつける気はないので、「個人的感想」と書きました。
ともあれ、記事紹介時点で閉路に関しては考慮も興味もなかった事が
はっきりしたのですっきりしました。返答ありがとうございました。

>>335の理由もわかりました。確かに誤解を招く記述だったと思います。
閉路に対する注意まで十把一絡げに無視されてしまった理由が理解
出来ませんでしたが、元々閉路に対する考慮などなかったということで
あれば納得です。

というわけで、この点に関しては自分はお終いです。あとは本題です。
単純パスの列挙をWITH RECURSIVEを使ってすっきり書ける方法、
どなたか思いつきますか?
恐らく問題になるのは始点・終点だけではなく通過した全ノードの列を
表現した経路情報をどのようにカラム値として持つかだと思います。
ノード名をデリミタで連結した文字列にするか、それこそ入れ子リレーション
にする必要があると思うのですが、他の方法はあるでしょうか?

384 :NAME IS NULL:2008/12/28(日) 21:08:55 ID:???
ガキばかりで楽しいわ

385 :NAME IS NULL:2008/12/28(日) 21:18:51 ID:???
現場もこんなもんだし。
隣の席なのに、メールで同じように揚げ足取りで戦ってるんだぜwww

386 :NAME IS NULL:2008/12/28(日) 21:24:59 ID:???
あるあるw
本質的な話になるとすべて煽りでごまかして
相手を攻撃するだけで優位に立ったつもりの奴が一人いただけで
そうなっちゃうな。

387 :NAME IS NULL:2008/12/28(日) 22:15:35 ID:???
>>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でどうすればいいのでしょうか?

389 :NAME IS NULL:2008/12/28(日) 23:35:53 ID:???
Oracle の Decode関数と同等のことを SQLServer でやりたいのです。
下記の示す Oracle 上で動作する Query を SQLServer 上で同等の
結果が得られるように書き換えるとどうなるのでしょうか?

select decode(COL1, 1, COL1 * 1.5, 0) from TABLE_A


390 :NAME IS NULL:2008/12/28(日) 23:49:28 ID:???
>>389
case文使うしか無かった気がする。
あるいは自前で関数作るか

391 :NAME IS NULL:2008/12/28(日) 23:54:12 ID:???
素早いレスありがとう。
御意、早速調べてみるワ
でも・・・、シンプルじゃなくなりそうだなぁ〜
多分、コレだけで SQLServer を嫌いになれますねw

392 :NAME IS NULL:2008/12/29(月) 00:08:52 ID:???
>>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追加してみると
日付毎の和になってしまいました。

394 :NAME IS NULL:2008/12/29(月) 01:01:35 ID:???
やりたいことが見えない。
人単位では既に累計を持っていて、最新のレコードだけ取得すればいいということ?
だったら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になるレコードを集計して…
で行ける。

397 :NAME IS NULL:2008/12/29(月) 01:23:50 ID:???
>>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が消えてしまいます。)


398 :NAME IS NULL:2008/12/29(月) 01:24:36 ID:???
相関サブクエリーだとどうだろう。
概念的にはこんな感じ。

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は一発で行ける感じですよね・・

400 :NAME IS NULL:2008/12/29(月) 02:09:19 ID:???
>>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
)
にした感じ

401 :NAME IS NULL:2008/12/29(月) 02:09:40 ID:???
>>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 日付
;

もうちょっとスマートにならないものか・・・

402 :NAME IS NULL:2008/12/29(月) 02:28:11 ID:???
>>401

神!!!
いやぁ、なんとお礼を言っていいのか、分かりません・・


403 :401:2008/12/29(月) 02:33:16 ID:???
深夜でボーっとしてるのでいい案が思いつかない・・・
どうでもいいが>>401のorder byは要らないな・・・

404 :NAME IS NULL:2008/12/29(月) 15:29:28 ID:???
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

のようなことをしたいんですが、
正常にソートするためには年の部分が必須なので、悩んでます。
何か方法あるようでしたら、教えてください。

405 :NAME IS NULL:2008/12/29(月) 15:50:00 ID:???
max_updatedを再利用したいのであれば単にクエリをネストすれば
良いんじゃないかと思う。

406 :NAME IS NULL:2008/12/29(月) 16:51:38 ID:???
>>405
まったく同じクエリをネストするのもどうかと思って質問したのですが、
現時点ではネストする事で対応しようと思います。

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

407 :NAME IS NULL:2008/12/29(月) 18:48:27 ID:???
例の荒れた「各駅を一回だけ通過するパスの列挙」ネタですが、
調べてみると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 :NAME IS NULL:2008/12/29(月) 21:52:16 ID:???
スレ違いかも知れませんが
排他制御やロックが詳しく解説している本やサイトがあったら教えてください。

お願いします。

410 :NAME IS NULL:2008/12/29(月) 22:25:15 ID:???
>>409
ベンダーによって排他やロックの実装方法は違うので、ターゲットとしているRDBMSを
書いた方がいいと思いますよ。(とはいえ、RDBMSベンダーは、ライバルの他ベンダー
のイイとこ取りを互いにやりつつ今日に至っているのできてるので、現在は、どのベンダ
ーも似たり寄ったり、大差ないのでは?非常に高度化、極小化が実現できてると思
いますけどね)
つーか、RDBMS側にお任せせず、ユーザーのアプリ側で排他制御やロックを意識しな
ければならないっていう事情とはいかなるものか、ソレも書いたほうがいいかもですね。

411 :NAME IS NULL:2008/12/29(月) 22:27:49 ID:???
↑誤植訂正

× 今日に至っているのできてるので
○ 今日に至っているので

412 :NAME IS NULL:2008/12/29(月) 22:29:51 ID:???
ロックはまだしも業務排他はRDBMS側で何もやってくれんと思うが

413 :NAME IS NULL:2008/12/29(月) 22:34:52 ID:???
コレ、業務の排他制御のことを聞いてるんですかね?
だとしたら、本人の言われているようにスレ違いですねw
そのあたりを解説している書籍を紹介してくれと言われてもなぁ〜
以下、フォローよろ

414 :412:2008/12/29(月) 22:35:35 ID:???
ああすまん設計スレと間違えた。

415 :NAME IS NULL:2008/12/29(月) 23:47:44 ID:???
>>409
トランザクションの分離レベルの一般的な話はここ(↓)とかにあるけど、
http://www.postgresql.jp/document/pg833doc/html/transaction-iso.html
他の人も言ってるように実際の実装はDBMSごとに違うから、
DBMSのマニュアルかDBMSごとの書籍を当たるしかないかと。

416 :NAME IS NULL:2008/12/30(火) 01:10:20 ID:Myw6Zv98
MySQLなんだけどデータ型の再定義ってどう書くんだったっけ?

417 :NAME IS NULL:2008/12/30(火) 01:20:54 ID:???
>>416
>>2

418 :NAME IS NULL:2008/12/30(火) 01:39:05 ID:???
事故解決した

419 :NAME IS NULL:2008/12/30(火) 01:43:45 ID:???
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系で動作するように書き換えたいと思いますので
アドバイス頂けないでしょうか

420 :NAME IS NULL:2008/12/30(火) 03:53:32 ID:???
バージョンうpできないの?

421 :NAME IS NULL:2008/12/30(火) 03:55:22 ID:???
>>420
レンタルサーバに設置する物なので、自分の一存ではバージョンアップ出来ません。
それに4.0からのバージョンアップは文字コード絡み絡み等で中々進まないのが現状みたいですし・・・

422 :NAME IS NULL:2008/12/30(火) 04:30:30 ID:???
思いつかないならアプリで対応すればいいやって思っちゃうタイプなんだが、
きっと1クエリでやり遂げたいという希望をあきらめきれないんだよね?
ホームディレクトリ配下にインストールしちゃえばいいのに、とかこう、関係ないことばっかり思い浮かんでしまうわ

423 :NAME IS NULL:2008/12/30(火) 04:37:50 ID:???
一応、配布するソースですので、あまり特別な環境や条件で動かす事は避けたいです
1クエリにこだわっている訳ではないんですが、やはりアプリを複雑にすると負荷も増えるので
極力DBはDB周りで解決したいと考えています。
自分があまりSQLに関して知識が無いので、上の質問がどの程度の難易度なのか分かりかねているというのが
現状なので、どうしても実現出来ないようならアプリ側で対処しようと思っています。

424 :NAME IS NULL:2008/12/30(火) 05:00:40 ID:???
【質問テンプレ】
・MySQL5.0
・欲しい結果:最終行のある要素の値
Mysqlのある要素の最終行の値を取得するクエリがわかりません

select [ある要素] from [table名] where 〜;

こんな感じで取得するクエリを教えてください

425 :NAME IS NULL:2008/12/30(火) 06:20:58 ID:???
>>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
>>427
in使えば?

429 :NAME IS NULL:2008/12/30(火) 13:28:23 ID:???
in も上限があったような気がする。
1,000行もあるんなら、必要な id 入ったテーブル作って、
結合すればいいんじゃね。

430 :NAME IS NULL:2008/12/30(火) 13:42:06 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
  :
  :
  :

432 :NAME IS NULL:2008/12/30(火) 14:21:00 ID:???
一行抜き出すクエリを1000回実行すれば良い話では。

433 :NAME IS NULL:2008/12/30(火) 14:35:06 ID:???
何回もSQL流すよりは>>429の方法がスマートだと思った。

434 :NAME IS NULL:2008/12/30(火) 14:43:51 ID:???
いや、テーブルつくるのに何回INSERTを実行するのかと・・・

idの組が毎回同じなのであればテーブルつくってJOINでしょうね。

435 :NAME IS NULL:2008/12/30(火) 14:52:35 ID:???
そもそもその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ってのがあったんですね。ありがとうございます。

437 :NAME IS NULL:2008/12/30(火) 17:24:04 ID:???
>>436
>>>432だとオーバーヘッド大きいかな?
>>431みたいに100個ずつ繰り返すのは何とかなりそうです。

一概にそうとも言えんて。
ちゃんとPrepared Statement使えば1000回発行してもそうそう
遅くはならないよ。
むしろ100個パラメーターを含むクエリを何度もコンパイルする
コストと評価するコストが気になる。
(長大なinだと殆どフルテーブルスキャンになりそうな)。

438 :NAME IS NULL:2008/12/30(火) 17:31:11 ID:???
>(長大なinだと殆どフルテーブルスキャンになりそうな)
すみません。ここのところは大ボケだったので忘れて下さい。

439 :NAME IS NULL:2008/12/31(水) 03:56:51 ID:???
 質問です。
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]にすると、同一のレコードが更新されます。
なぜ先に更新した結果を実行時に読みこんでないのでしょうか?

440 :NAME IS NULL:2008/12/31(水) 05:44:35 ID:???
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
 )

441 :NAME IS NULL:2008/12/31(水) 10:15:18 ID:???
>>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の構文の定義みたいなのってどこかにありませんか?


443 :NAME IS NULL:2009/01/02(金) 23:25:35 ID:???
>>442
http://savage.net.au/SQL/

444 :NAME IS NULL:2009/01/03(土) 08:25:57 ID:???
>>443
ありがとうございます。

445 :NAME IS NULL:2009/01/04(日) 19:58:53 ID:???
XMLデーターベースってどうなの?

446 :NAME IS NULL:2009/01/04(日) 23:05:37 ID:???
XPath と、 XQuery をざっと見てきな。
RDBMSごとに仕様が違うとはいえ、SQLの常識が通じない世界にびっくりするよ。

今から本気で取り組んでおけば、XMLDBが当たり前になった頃に頭角を現すことが出来るかもね。

447 :NAME IS NULL:2009/01/04(日) 23:12:11 ID:???
いまはまだ
全然はやってないってこと?

448 :NAME IS NULL:2009/01/04(日) 23:42:37 ID:???
まだまだ。
SQLとXMLが相互変換可能になった頃に流行ると睨んでる。

449 :NAME IS NULL:2009/01/05(月) 01:16:31 ID:???
SQLとXMLの相互変換ってなんだ?

それはさておき、XMLDBはXMLを直接格納・検索する大きな需要が
発生しない限り流行らんと思う。ってそのまんまだけど、逆に言うと、
数年前にXMLDBが注目された際に言われたような汎用DBとしての
普及はしないだろうということ。

450 :NAME IS NULL:2009/01/05(月) 01:58:53 ID:???
DDLはXML Schema、DMLは参照に関してはXQueryが標準として
利用できるけど、更新に関して標準が存在せず、各社独自規格。
ここのところが標準化されない限りRDBMSを置き換える存在には
なかなかならないと思う。

451 :NAME IS NULL:2009/01/06(火) 14:11:20 ID:???
sqlmangr.exeなんですが起動したときにウインドが表示されてしまいます
引数で非表示に出来たと思うのですがどうやればいいんでしょうか?

452 :NAME IS NULL:2009/01/06(火) 14:24:47 ID:???
SQL文のスレであってSQL Serverのスレではありません

453 :NAME IS NULL:2009/01/06(火) 14:34:56 ID:???
そうなのですかーすみませんでした
他で聞いてみることにします

454 :NAME IS NULL:2009/01/07(水) 08:55:09 ID:???
テーブルが 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について」という意味になる、ということ ?


455 :NAME IS NULL:2009/01/07(水) 09:12:19 ID:???
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の場合の考え方。

456 :NAME IS NULL:2009/01/07(水) 18:43:03 ID:???
>>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 を使うと、「外側に何があろうと」結果を返してしまうから、結果が違ってくる。
大変参考になりました。ありがとう。


458 :NAME IS NULL:2009/01/08(木) 13:41:21 ID:???
>>457
existsを使う使わないは関係ないよ
and と or それぞれがどういう挙動になるか把握できていないわけではない?

459 :NAME IS NULL:2009/01/08(木) 14:58:40 ID:???
>次のクエリと混同していた。
混同も何も同じことだ。

>>457の後者をorに変えても結果は>>454の後者と同じだぞ。
「existsが分かってなかっただけ」と思い込もうとしてしまうと
また同じ間違いを繰り返すことになる。

460 :NAME IS NULL:2009/01/08(木) 18:50:38 ID:???
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:???
御教示かたじけなく。
やはり付け焼き刃ではだめだ。一から勉強をやり直すことにします。



462 :NAME IS NULL:2009/01/09(金) 04:26:09 ID:???
うん。
WHERE句の初期で学ぶ内容だから、今回の問題となったところも
すぐに理解できると思うからがんばって。

463 :NAME IS NULL:2009/01/09(金) 05:12:10 ID:???
どんだけ上から目線w

464 :NAME IS NULL:2009/01/09(金) 17:12:26 ID:???
気に入らないなら人に訊かずに自己学習すればいいのに。

465 :NAME IS NULL:2009/01/09(金) 17:59:39 ID:???
>>463>>462さんが誰だか知らないんだろ。
許してやれよ。

466 :NAME IS NULL:2009/01/10(土) 00:13:35 ID:???
ざっくりした質問になってしまうがすまない

SQL Serverの2000と2005で同じSQL文を発行したとき、
・2005の乗っているサーバの方がはるかにハイスペック
・データベースの中身は同じ(互換レベル80)
・統計情報とかはちゃんと寸前に更新した
という条件で、2005の方が結果が出るのがはるかに遅いっていう
現象を経験したことある人いない?

大量にデータを抜いてくるようなSQL文なんだけど、2000のだと
ものの10秒とかで抜いてくるんだけど、2005だと6分くらいかかる

結構複雑っていうかスパゲティなSQL文なんで実行プランも結構
違うんだが、2000の方はソート、2005の方は外部結合に時間を
一番割いている模様

467 :NAME IS NULL:2009/01/10(土) 00:27:01 ID:???
>>466
DB2では似たような経験アリ
DB2は統計情報を手動でいじれるんでそれで解決した
SQL Serverはシラネ

468 :NAME IS NULL:2009/01/10(土) 00:58:30 ID:???
てかスレ違いだろ
ここはSQLのスレであってSQL Serverのスレではない

469 :NAME IS NULL:2009/01/10(土) 01:09:47 ID:???
>>467
thx
やっぱ統計情報の問題なのかね?

>>468
まあま、いちお「SQL文をどう解析・実行してるか」という点も重要かと
思うんで、固いこと言わずにw

470 :NAME IS NULL:2009/01/10(土) 17:15:23 ID:???
ゲイツってなんでいつも変な名前つけるんだろうね
SQLの製品にSQLとか。

471 :NAME IS NULL:2009/01/10(土) 17:20:07 ID:???
「ぽすぐれ?さいべーす?聞いたこと無いな。SQL何とか?あーなんか聞いたことあるな、よしそれでいこう」
的な効果を狙ってるんでは

472 :NAME IS NULL:2009/01/10(土) 17:41:46 ID:???
アポーも割と一般名詞の機能付けて検索しづらいぜ。

473 :NAME IS NULL:2009/01/10(土) 17:58:07 ID:???
>>472
AIRPORTにはびびった。そんな一般的な名詞を使うなと。

474 :NAME IS NULL:2009/01/10(土) 20:15:08 ID:???
SQLを製品名(の略称)だと思ってる奴もいるよな
「SQL使えるか?」の意味が「SQL Server使えるか?」だったりして、
紛らわしいことこの上ない

475 :NAME IS NULL:2009/01/11(日) 01:48:44 ID:???
うちの上長(SE)がそれ。
話しにならんわw

476 :NAME IS NULL:2009/01/11(日) 01:52:22 ID:???
MS的には「してやったり」だろうな

477 :NAME IS NULL:2009/01/11(日) 07:00:19 ID:???
入社してすぐの頃、自称SE(50くらい)が「SQLを使うな!」というから、
汎用系触ったことねーよとちょいびびっていた。

ふたを開けてみたら「SQLServerは糞!ORACLEかDB2しかいかん!」といいたかったらしい。
理由は外注が実装した処理が糞重くて使い物にならないから。
テーブルもインデクスも設計が糞。さらにAPPソースも糞。

最初の1年でアプリごと総取っ替えプロジェクトに組み込まれて死にそうになった。
でも、きちんと設計しなおしたら、パフォーマンスがン千分の1になった(ベンチマーク上)

で、SQLServerが悪いのかい、自称SEさん?
(でも、MySQLかPostgreSQLで十分だと思う。
自称SEさんは知らなかったみたいだけどね。)

478 :NAME IS NULL:2009/01/11(日) 12:41:48 ID:???
メモリ足りなかっただけじゃないの?
DBでメモリ少ないのは致命的だし。

総取っ替えプロジェクトもまたSQL鯖だったのか?

479 :NAME IS NULL:2009/01/11(日) 12:54:58 ID:???
どうでもいいけど「パフォーマンスがン千分の1になった」ってのは
パフォーマンスが悪くなったみたいな感じするね
「処理時間がン千分の1になった」ならわかるけど

480 :NAME IS NULL:2009/01/11(日) 13:38:54 ID:???
そこは、まあ、ふいんき(なぜ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 を併せた形で取得したいと思っています。
何卒お知恵をお貸しください。よろしくお願いします。

482 :NAME IS NULL:2009/01/11(日) 17:34:47 ID:???
最初の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

が取得できました。大変お騒がせしました。

484 :NAME IS NULL:2009/01/11(日) 18:00:26 ID:???
あー>>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;

で期待する結果が得られました。
重ね重ねありがとうございました。

486 :NAME IS NULL:2009/01/11(日) 23:06:15 ID:???
>>477
> ふたを開けてみたら「SQLServerは糞!ORACLEかDB2しかいかん!」といいたかったらしい。
実際、昔の SQL Server は糞だったんだよ。
ダーティリードは平気でするし、ロックのエスカレーションは普通におきるしw
行レベルロックサポートしてなかったんだよね。だから、更新系のトランザクションが
ガンガン走るようなシステムでは SQL Server は選択子のうちに入らなかった。

まあ、今はそんなことないけどどね。
商用のRDBMSでは各ベンダーの機能実装競争が終焉し、いい意j未でどれも
似たりよったり。高いレベルにいきついまったね。差が無くなってしまった。
今じゃ、SQL Server も行レベルロックをサポートしてるし・・・。
MySQLやPostgreSQLが商用RDBMSに追いつこうとがんばっている状況かな。

> でも、きちんと設計しなおしたら、パフォーマンスがン千分の1になった(ベンチマーク上)
ありがちな話w。
つーか、SQL文が書けて、プログラムが組めるというだけで・・・(以下略


487 :NAME IS NULL:2009/01/11(日) 23:14:50 ID:???
行レベルロックをサポートしてないのになんでロックエスカレーションが起きるんだ?
ページロックからテーブルロックへのエスカレーション?

488 :NAME IS NULL:2009/01/11(日) 23:23:03 ID:???
>>487
> ページロックからテーブルロックへのエスカレーション?
そう。
Oracle が行レベルロックを実装していたにも関わらず、その頃の SQL Server は、
最小のロックの単位がページ単位だった。おまけに、ページからテーブルロックへの
エスカレーションがおきるというシロモノだったんだよ。
20世紀の話だよ


489 :NAME IS NULL:2009/01/11(日) 23:35:50 ID:???
>>488
Oracleはロックっていうよりバージョニングでしょ。
(古いデータと新しいデータの両方を保持する。)
Postgresもそう。

DB2はロックだね。
だから未だにエスカレーションは起きる。
(もちろんチューニングは可能だけども。)

SQL ServerとMySQLはどうなん?

490 :489:2009/01/11(日) 23:43:30 ID:???
あれ?俺なんかすごい変なこと言ってるな・・・
酔っ払ってるから、忘れてくれ・・・

491 :NAME IS NULL:2009/01/11(日) 23:51:32 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(*))で取得できないですかね?

495 :NAME IS NULL:2009/01/12(月) 12:54:10 ID:???
>>494
maxとcountのグループ化単位が違うんだから無理だろ

496 :NAME IS NULL:2009/01/12(月) 19:44:38 ID:???
できるんじゃね?

497 :NAME IS NULL:2009/01/12(月) 22:03:45 ID:???
>>493-4944って>>4がhaving DATE=max(DATE)でいけるんじゃね?
って言ってるのと同じだよな・・・

498 :NAME IS NULL:2009/01/12(月) 23:37:44 ID:???
違う

499 :NAME IS NULL:2009/01/13(火) 10:26:56 ID:???
違うか?

500 :NAME IS NULL:2009/01/13(火) 21:24:20 ID:???
どなたか教えてください。
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」のどっちかが取れればよいという
ことです。




501 :NAME IS NULL:2009/01/13(火) 22:00:24 ID:???
>>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
ありがとうございます。
ぐぐろうとしても、いい検索語が思いつかずこまっていました。
明日さっそく、試してみます。


503 :NAME IS NULL:2009/01/13(火) 23:14:11 ID:???
すいません、サーバーAにあるデータ(CSVファイル)を、サーバーBに取り込むにはどうすればいいんでしょうか・・・?

504 :NAME IS NULL:2009/01/13(火) 23:16:34 ID:???
>>503
スレ違い。

imp とか bcp とか、バルクインサートとか、DB にあったやつを選べ。

505 :NAME IS NULL:2009/01/13(火) 23:34:24 ID:???
>>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

506 :NAME IS NULL:2009/01/13(火) 23:47:02 ID:???
select key, MAX(data)
from table
group by key

これではあかんの?

507 :NAME IS NULL:2009/01/13(火) 23:47:04 ID:???
>>505
それって
select key, min(data) data from a_table A group by key, data
と同じことだよね?

508 :NAME IS NULL:2009/01/13(火) 23:48:02 ID:???
あー>>507の最後のdataは不要

509 :NAME IS NULL:2009/01/14(水) 01:11:11 ID:???
select key,min(data) from table group by key

510 :NAME IS NULL:2009/01/14(水) 04:11:40 ID:???
>>505が汎用的と書いているのはa_tableに他のカラムがあって、それも抽出したい場合を考えれば分かるかと
key dataしかカラムがないのであれば>>507でいいけど

511 :NAME IS NULL:2009/01/14(水) 04:38:52 ID:???
苦しいw
オラクル専用に対しての汎用的って事でしょ。

512 :NAME IS NULL:2009/01/14(水) 05:29:55 ID:???
だから、>>507>>505と同じことなわけないよね

513 :NAME IS NULL:2009/01/14(水) 06:11:18 ID:???
あれ?いきなり話題を逸らしてきたな。
じゃあ「汎用的」は結局苦しい言い訳でした、でいいの?

同じじゃないといえば、わざわざ難しく書いた挙句
「最小データが複数件あったとき正常に動かない」というバグを持ってるねw

514 :NAME IS NULL:2009/01/14(水) 10:01:43 ID:???
column A と column B が一致(重複)している行の一覧を
取得したい場合は、どういう SQL になりますでしょうか?

515 :NAME IS NULL:2009/01/14(水) 10:21:48 ID:???
ID A B
1 a b
2 b a
3 c c

とあったとき「A と B が一致(重複)している」というのは、
ID=3 だけ ? それとも、ID=1,2 も含むの ?


516 :NAME IS NULL:2009/01/14(水) 10:40:45 ID:???
>>515
あ、すみません。例を出すと
ID A B
1 a b
2 b a
3 c c
4  a  b
という状態で
1 a b
4  a  b
を表示したいということです。

517 :NAME IS NULL:2009/01/14(水) 11:17:54 ID:???
>>516
SELECT * FROM Table WHERE (a,b) IN (SELECT a,b FROM Table GROUP BY a,b HAVING count(*)>1);

518 :NAME IS NULL:2009/01/14(水) 12:26:20 ID:???
SQLServerでOracleのシーケンスのようなプロシージャを、
テーブル参照しないで実現したいのですが、どのように実装すればよいでしょうか?

519 :NAME IS NULL:2009/01/14(水) 19:07:41 ID:???
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さん 
とソートしたいです。

520 :NAME IS NULL:2009/01/14(水) 19:13:27 ID:???
NULLを先頭にするか末尾にするかは設定で変更可能な場合があるよ

521 :NAME IS NULL:2009/01/14(水) 19:14:20 ID:???
銀行システム作ってるんだけど、
数値を1増やす、って処理をするとき、
PHPで1増やし済みの変数を用意して、
それをupdateでデーターベースにぶちこんだほうがいいのか、
それとも、
SQLの命令で、「1増やせ!」って命令を送り込んで
データーベースの内部で1増やしたほうがいいのか、
おしえてけろ。

522 :NAME IS NULL:2009/01/14(水) 19:16:28 ID:???
>>519
order by case when 日付 is null then 1 else 0 end
というようなことをやってみたらどうだろう

523 :NAME IS NULL:2009/01/14(水) 19:55:41 ID:???
>>519
>>520の指摘どおりだけど
SELECT文の中でどうにかするのなら
order by句でnvlなりisnullなり使えばいいんでは

524 :523:2009/01/14(水) 19:56:18 ID:???
すまん>>522見てなかった

525 :521:2009/01/14(水) 20:38:21 ID:???
自己解決した。
update bookmark set count=count+1

これをSQL文につっこんだら、数字が1プラスされた。

http://www.atmarkit.co.jp/fjava/rensai/jsp2_01/jsp2_01_4.html
ここを参考にした。

526 :NAME IS NULL:2009/01/14(水) 21:10:50 ID:???
え。
それをするべきか、ロックを取得できたことを確認した状態で更新すべきかで悩んでいたのではなかったのか

527 :523:2009/01/14(水) 21:23:44 ID:???
>>525
それが>>521の後者の事だと思って読んでたんだ

528 :NAME IS NULL:2009/01/14(水) 21:24:16 ID:???
ああー名前が残ってたしまたリロードしてなかったし

529 :521:2009/01/14(水) 21:37:18 ID:???
>>526
違う。
純粋にどういうコードを書いたらいいのか
わからなかった。

他に注意すべき点があるなら教えろ

530 :NAME IS NULL:2009/01/14(水) 22:01:16 ID:???
てことは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:???
だれか一緒に、
ゲームの中の銀行システム
作りたい人いる?

534 :NAME IS NULL:2009/01/14(水) 22:27:53 ID:???
スレ違いだな。そろそろ消えてなくなれよ。

535 :NAME IS NULL:2009/01/14(水) 22:31:07 ID:???
銀行システム作ってるんだけど、
って書き始める必要あったの?

536 :521:2009/01/14(水) 22:31:42 ID:???
>>535
もちろん。どういうシステムなのか、
イメージさせないと、ぴったりのアドバイスは
出ないでしょう?

537 :521:2009/01/14(水) 22:32:58 ID:???
そんで、次の質問。
データーベースで数字をカウントアップさせるとき、
ファイルロックとかって気にする必要あるの?

たしかMySQLは、読み込み、書き込み時に
何も指定しなくても、勝手にファイルロックかかるって
読んだ記憶があるけど?

SQLiteでもそうなるの?

それとも、トランザクションを使わないとだめ?

538 :NAME IS NULL:2009/01/14(水) 22:35:09 ID:???
これ、このスレの範囲か?

プログラム系のスレに行った方がいいと思うぞ・・・。

シーケンスのカウントアップ単体なら、明示的にロックする必要はないだろ。
他のデータ処理が伴うなら、当然トランザクションが必要。ロックとは直接
関係ない概念だけどな。

539 :NAME IS NULL:2009/01/14(水) 22:58:42 ID:LMJsYGpi
しょうもないことなんですが、教えて下さい。
INSERT DELETE SELECT UPDATE などをまとめて呼ぶ時の呼称をを教えて下さい。

ini conf exe などを拡張子(extention)と呼ぶような感じです。
(他のスレで質問したのですが、ここの方が適切かと思いました。)

540 :NAME IS NULL:2009/01/14(水) 22:59:01 ID:???
>>539
DML

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増える、
っていうのが、作りたいシステムだから。

544 :NAME IS NULL:2009/01/14(水) 23:04:15 ID:???
>>541
まずテーブル構造をさらそうな。

545 :521:2009/01/14(水) 23:04:55 ID:???
>>542
データー マニュピレーション ランゲージ
data manupilation language

546 :521:2009/01/14(水) 23:05:36 ID:???
>>542
http://e-words.jp/w/DML.html

547 :NAME IS NULL:2009/01/14(水) 23:05:51 ID:???
>>542
ググるクセをつけような。Data Manipulation Language

Create Table とかの DDL (Data Definition Language) と対。

548 :NAME IS NULL:2009/01/14(水) 23:07:27 ID:???
>>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)みたく
テーブルがきたなくてすいませんが、要するに重複したやつを削除
してお勧め商品をだしたいです。
よろしくお願いします。
 



550 :NAME IS NULL:2009/01/14(水) 23:14:59 ID:???
>>541
この本がそういったテーマを扱ってますよ
http://www.amazon.co.jp/dp/4873113644

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 かつ


552 :NAME IS NULL:2009/01/14(水) 23:24:23 ID:???
サブクエリ使っていいならできるけど
ダメなんだっけ?

553 :NAME IS NULL:2009/01/14(水) 23:25:40 ID:4hR9j4JG
いいです。お願いします。


554 :NAME IS NULL:2009/01/14(水) 23:27:29 ID:???
遅いだろうけど、

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
本もかいます


557 :NAME IS NULL:2009/01/14(水) 23:36:10 ID:???
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 = ユーザー
)
)
)

558 :NAME IS NULL:2009/01/14(水) 23:37:29 ID:???
>>533
ゲームの中の銀行システムを作ろうとしてるけどアップデート文もままならない状態なので
代わりに作ってくれる人いる?と意訳してみたけど、あってる?

>>539
CRUDといったりするよ。

559 :NAME IS NULL:2009/01/14(水) 23:38:08 ID:???
>>541
システムの機能やSQLでどうとでもなりそうな気がする。
オープンソースのCMSソフトでもよくある機能なので、インストールしてソースを見るのもいいかも。

560 :NAME IS NULL:2009/01/14(水) 23:44:05 ID:???
>>558
警察に通報しました

561 :NAME IS NULL:2009/01/15(木) 00:08:44 ID:/DtyTV7F
http://www.amazon.co.jp/dp/4873113644
ではなくてできればmysql(なければDB本で)このことについて書いてある本
ってありますか?
なければhttp://www.amazon.co.jp/dp/4873113644 を買いたいと思うのですが
>>557さんありがとうございます。


562 :NAME IS NULL:2009/01/15(木) 00:30:08 ID:???
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
>>545 >>547
レスありがとうございます!

565 :NAME IS NULL:2009/01/18(日) 17:18:44 ID:hDKyghRK
Transact-SQL

@id char(3)
変数@idに全て数字がセットされているか、
又は全て英字がセットされているかを判定したいのですが、
やり方を教えていただけないでしょうか?
宜しくお願いします。

566 :NAME IS NULL:2009/01/18(日) 17:54:05 ID:???
isnumeric ってのがあるな。isalpha はないみたいだから、一文字ずつコードを確認したら?

567 :NAME IS NULL:2009/01/18(日) 18:24:45 ID:???
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
レス有難うございます。

正規表現は使えるんですかね・・
使えたら最高なんですが。

569 :NAME IS NULL:2009/01/18(日) 18:45:40 ID:???
SQL Server で正規表現は無理。CLR ストアドで・・・ ってことだな。

570 :NAME IS NULL:2009/01/19(月) 01:03:25 ID:???
制約つけりゃいいんじゃないの

571 :NAME IS NULL:2009/01/20(火) 00:45:08 ID:???
他板から誘導されて来ました。
ご指導願います。

Vb.netで
UPDATE テーブルA LEFT JOIN テーブルB ON テーブルA.CD = テーブルB.CD SET 〜を
実行すると、「キーワードLEFT付近に不正な構文があります」と
エラーが出ました。
MS-ACCESSだといけたので大丈夫かと思ったのですが、
悪い所を教えて下さい。
よろしくお願いします。

572 :NAME IS NULL:2009/01/20(火) 00:50:49 ID:???
>>571
ここが MS SQL Server の話題を扱う所だと勘違いしていませんか?

573 :571:2009/01/20(火) 01:09:33 ID:???
>>572
ごめんなさい、では何を扱う所なのですか?
SQL文についてお聞きしていいのかと思って書き込んだのですが…失礼があったならすみません。

574 :NAME IS NULL:2009/01/20(火) 02:00:02 ID:???
全然スレチじゃないですよ。でもDBMS名を明記して欲しいところですが。MSSQLかどうかなんてわかんないし。

両方のテーブルを更新したいのならちょっとわかんないんだけど、テーブルAだけでいいなら
update テーブルA set hoge = B.hoge from テーブルA left join テーブルB using(CD)
とかでいけないかな

575 :NAME IS NULL:2009/01/20(火) 06:44:28 ID:???
>>574
あんたもdbms名いいなよw
mssqlにはusingないよ。


576 :571:2009/01/20(火) 09:03:00 ID:???
>>574
うわ、ごめんなさい!
Microsoft SQL Server 2005です。


577 :NAME IS NULL:2009/01/20(火) 10:32:03 ID:???
方言あるなら専用のスレ行ったほうが答えもらえるのが早いとは思うけどね。
でも>>573の言い方はSQL=MS SQLと思ってる気がしないでもないw

578 :NAME IS NULL:2009/01/20(火) 13:32:54 ID:???
>>577
方言のないDBMSって何がありますか?

579 :NAME IS NULL:2009/01/20(火) 13:42:07 ID:???
>>578
きみは「キーワードLEFT付近に不正な構文があります」
で何かわかるのかね?

580 :NAME IS NULL:2009/01/20(火) 13:44:42 ID:???
少なくとも、元質問者はあっちでは使えたSQLがこっちでは使えなかった
という質問なんだから専用スレのが速いだろうな。

581 :NAME IS NULL:2009/01/20(火) 15:58:11 ID:???
>>579
良く分からないけど、方言のあるDBMSは専用スレへってことですよね
だったら方言のないDBMSもしくは規格について話すスレなのかなと思って、
方言のないDBMSを教えて欲しかったんです
LEFT付近に不正な構文があるんでしょ

582 :NAME IS NULL:2009/01/20(火) 16:02:18 ID:???
方言なしってのは
SQL92や99の構文だけで書くってこと
方言を一切持たないDBMSは見たことない

583 :NAME IS NULL:2009/01/20(火) 16:02:27 ID:???
ここはSQL92質疑応答スレになりました。

SQL99以降は実装状況を見てもまだ殆ど方言だ。

584 :NAME IS NULL:2009/01/20(火) 16:27:10 ID:???
製品名を教えてくれないと、SQL92の範囲で回答するしかないんだな。
それで「LEFT付近に不正な構文がある」としか言えなくなってしまう。

>>571 は別にスレ違いじゃないからね。念のため。

585 :NAME IS NULL:2009/01/20(火) 17:44:32 ID:???
思考錯誤してみましたが、うまい解が浮かびませんでした。
是非ともご教示お願いいたします。

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

以上、よろしくお願いいたします。

586 :NAME IS NULL:2009/01/20(火) 18:30:32 ID:???
>>585
トリガでどうにかしたいってことでいいのかな
削除とか更新とかも必要になりそうな気もするけど

587 :NAME IS NULL:2009/01/20(火) 18:35:00 ID:???
・startが7よりも大きいレコードのnumberをnumber + 1にする
・以下のレコードを挿入する
  startが7よりも小さいレコードのうち、一番大きなもののnumber+1
  7
  startが7よりも小さいレコードのうち、一番大きなもののend
・startが7よりも小さいレコードのうち、一番大きなもののendを7 - 1にする
の3クエリだろうか

588 :NAME IS NULL:2009/01/20(火) 18:55:04 ID:???
誰も正確に答えてないので・・・

>>571
SQL92だと、UPDATE文は
 UPDATE <テーブル名> SET 〜 [WHERE 〜]
の形式しかない。
つまりUPDATE句に複数テーブルは書けない。

ちなみに標準から外れているという意味では
SQL ServerだとなぜかUPDATE文にFROM句が使えたりするけど
質問とは直接関係ないな。

589 :NAME IS NULL:2009/01/20(火) 19:11:42 ID:???
情報不足ですみません。

>>586
現状、SQLiteを弄っている言語の方で削除や更新処理を行っているので
クエリだけでなんとかできないものかと思案していました。

>>587
おおお、なるほどありがとうございます。
うまく分解できていませんでした。ちょっと考えてみます。

590 :NAME IS NULL:2009/01/20(火) 23:02:48 ID:13ofr99R
T-SQLです。

CREATE PROCEDURE test
AS
BEGIN
    何かの処理

自作のデータ追加関数()

何かの処理

自作のデータ追加関数()

END

自作のデータ追加関数を、上記のストアドで定義・使用したいのですが、
どのように定義すればよいのでしょうか?


591 :NAME IS NULL:2009/01/20(火) 23:08:19 ID:???
management studio使うと楽に定義できますよ

592 :590:2009/01/20(火) 23:32:31 ID:13ofr99R
>>591
できません・・・

ストアド内に自作関数は定義できないのでしょうか・・

593 :NAME IS NULL:2009/01/21(水) 03:23:57 ID:???
selectするときにソートするのではなく、insertやupdateのときにソート済みの状態にしておくようなことはできませんでしょうか。
select * from table_name order by column_name
がボトルネックになっているのがわかったので、データを書き込むときにソート済みの状態にできればと思い、質問させて頂きました。
なお当方MySQLを使っていますが、MySQLに限らずこのような機能があれば紹介してください。
識者の方、よろしくお願いします。

594 :NAME IS NULL:2009/01/21(水) 03:52:02 ID:???
無理っす。
ただ、インデックスを作っておけば速度が改善されるかもしれません。
うまくインデックスが使われるかどうかは下記参照。(バージョンに見合ったマニュアルに読み替えてください)
http://dev.mysql.com/doc/refman/5.1/ja/order-by-optimization.html

595 :NAME IS NULL:2009/01/21(水) 15:49:38 ID:???
>>594
大変参考になりました。
データを並べ替えて格納するのはできなくても、インデックスの値を順番に並べておくことはできるわけですね。なるほど。
ありがとうございました。

596 :NAME IS NULL:2009/01/21(水) 16:41:02 ID:???
>>592
エスパーじゃないから自作関数の意味がわからない。

ユーザー定義関数のことを指しているのであれば、ストアド内で作成も使用も出来る。

ただ、590を見ると見当違いのとこで関数を使おうとしているように見えるな。
http://msdn.microsoft.com/ja-jp/library/ms190642.aspx

597 :NAME IS NULL:2009/01/21(水) 20:01:31 ID:???
質問させてください。

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レコードのみ存在する。

598 :NAME IS NULL:2009/01/21(水) 20:39:08 ID:???
>>597
何でだろうね?見た感じ0になりそうなもんだけど。
オラクル手元にないのでPostgreSQLで試したら0だった。
参考まで。

599 :NAME IS NULL:2009/01/21(水) 21:02:06 ID:???
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

ストアド内でこんなことは普通しないと思うけど。

602 :NAME IS NULL:2009/01/22(木) 03:01:55 ID:???
テーブルロックについて質問です。

1・mysqlで書き込み、書き換えを行った時、テーブルロックは自動的にかかるのですか?

2・自動でかかる場合、そのロックはリードロックになるのかライトロックになるのかどちらでしょうか?

3・「そんなもん設定による」という場合、設定の確認方法はありますか?

質問が重なってすみませんが宜しくお願いします。

603 :NAME IS NULL:2009/01/22(木) 03:30:27 ID:???
質問する前になぜDBにはロックという機能が必要か考えた方が良い。

604 :NAME IS NULL:2009/01/22(木) 06:30:30 ID:???
>>603
ありがとうございます、自己解決できました。
重ねて質問なのですが、
現在作成中のアプリケーションは全体からの読み込みが多く、
一行単位の書き込み・書き換えもそれなりに多いです。
そこで、

・一行単位の書き込み・書き換えのみ行ロック
・読み込みその他はテーブルロック

という動作が一番効率が良さそうなのですが、
MyISAMでクエリ発行毎に、能動的にテーブルロックを行ロックに変更することは可能ですか?
(InnoDBで行ロックをテーブルロックに変更、でもOKです)

605 :NAME IS NULL:2009/01/22(木) 06:49:47 ID:???
>>604
MyISAMでは行ロックはできない。
InnoDBならデフォルトで行ロック、明示的にテーブルロックも可能、
バージョニングのため読み込み時にロックは不要。
だったような。

というか、トランザクションの分離レベル(Isolation Level)について
ちゃんと勉強したほうがいいと思う。

606 :NAME IS NULL:2009/01/22(木) 07:19:17 ID:???
>>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?)を手に入れ次第、もう一度検証してみようと思います。

608 :NAME IS NULL:2009/01/22(木) 22:36:12 ID:???
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円のレコードしかひっかからない感じ


609 :NAME IS NULL:2009/01/22(木) 22:50:34 ID:???
>>608
select *
from 商品 A
where not exists (select *
         from 商品 B
         where A.商品ジャンル = B.商品ジャンル
         and  A.仕入先 = B.仕入先
         and  A.単価 < B.単価)
;

610 :NAME IS NULL:2009/01/22(木) 22:50:50 ID:???
動かしてないけど、
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
を入れ忘れた。。。

613 :NAME IS NULL:2009/01/23(金) 00:34:53 ID:???
>>604
primary keyの取り方でロックがほとんど発生しない事もあるよ。
既にDBやTBL決まっているのであれば、周りの人に相談した方がいい。

下手すると貴方のアプリが動いてる時だけ長時間のロックが発生して問題になる。

614 :NAME IS NULL:2009/01/23(金) 00:47:47 ID:???
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文を教えていただきたく、よろしくお願いします。

615 :NAME IS NULL:2009/01/23(金) 00:57:33 ID:???
>>609
こういう時に正しく動かない

ジャンル | 仕入 | 単価 | コード
1    | 1  | 200 | 0
1    | 1  | 200 | 0
1    | 2  | 200 | 0

countをうまく使うんだ


616 :NAME IS NULL:2009/01/23(金) 01:43:35 ID:???
>>615
select ジャンル, 仕入, 単価, max(コード)
group by ジャンル, 仕入, 単価
にするんじゃだめ?

617 :NAME IS NULL:2009/01/23(金) 01:50:56 ID:???
>>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拡張だった。スマソ。

619 :NAME IS NULL:2009/01/23(金) 06:12:41 ID:???
>>616
>単価, max(コード) ・・・・だと!?

も、問題をよく読むんだ。

>・商品ジャンルと仕入れ先でグループ化して
>・グループの中で単価が最大で
>・かつ商品コードの下1桁が0


620 :NAME IS NULL:2009/01/23(金) 06:44:53 ID:???
>>615
グループ内で単価が同じものがあったときに
全件出すのか、一件に絞るのか、絞る場合はどういう条件で絞るのか
書かれてないから、>>609が「正しくない」とは一概に言えんな。

621 :614:2009/01/23(金) 09:01:10 ID:???
>>617
2つ目のクエリでうまく更新できました。ありがとうございます。

>category_tableにitemcountカラムを設けるのが間違いな気がする。
ほかにもっと良い方法があるということでしょうか?

622 :NAME IS NULL:2009/01/23(金) 12:52:59 ID:???
>>619
>>609-610の結果をそういう風に挟むんだけど、だめ?

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
  );


624 :NAME IS NULL:2009/01/23(金) 21:06:12 ID:???
>>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でいいでしょうか。


627 :NAME IS NULL:2009/01/28(水) 20:49:41 ID:???
>>625
集合1 集合2のどちらも集合3の要素を一つも含まないので、-集合3の部分がいらなくなります。
まとめると、
select * from XXX where A = 1 and (B = 9 or B is null)
になるのではないかと思います。

628 :NAME IS NULL:2009/01/28(水) 20:57:39 ID:???
汎用的(各SELECT文をそのまま使い回し)なら、
集合1 UNION 集合2 EXCEPT 集合3

629 :NAME IS NULL:2009/01/28(水) 21:02:26 ID:???
MySQLはまったく知らんが
集合の+、−の演算が何を意味するのかわからんが
集合1,2はA=1しかなくて、集合3にはAが1のものはないんだろ
(!=はノットイコールでいんだよな?)
つまり、集合1や2には集合3と同じものは存在しないぞ
−するの無意味じゃね?

MySQLの!=が、NULLのものまでヒットしたらまた別かもしれんが


630 :NAME IS NULL:2009/01/28(水) 21:07:38 ID:???
かぶったorz

最後の一文、よく考えたら=もNULLにヒットしないと同じか


631 :NAME IS NULL:2009/01/28(水) 21:25:28 ID:???
>>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) ※分配律

633 :NAME IS NULL:2009/01/29(木) 00:33:17 ID:???
 (X * Y) + ((X * Z) * ^(^X * Y))
なんで^(^X?

634 :NAME IS NULL:2009/01/29(木) 01:17:42 ID:???
XとYの積集合が存在するかもしれないからでしょ。重複部分。

635 :NAME IS NULL:2009/01/29(木) 06:44:47 ID:???
>>633
>>626

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

・説明

禁止文字のチェックの為、_や%を含む項目を抽出したいのです。
宜しくお願いします。


637 :NAME IS NULL:2009/01/29(木) 11:19:28 ID:???
>>635
なんで2つめと3つめが先?

638 :NAME IS NULL:2009/01/29(木) 12:32:01 ID:???
>>637
>>626

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を使っています。

643 :NAME IS NULL:2009/01/31(土) 03:38:16 ID:???
UNION ALLを使います。

644 :462:2009/01/31(土) 04:30:25 ID:???
>>463
できました。
ありがとうございます。

645 :NAME IS NULL:2009/01/31(土) 19:33:47 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みたいな感じに

結合したテーブルはパラメータをつけれないんでしょうか?



646 :NAME IS NULL:2009/01/31(土) 22:52:37 ID:???
誰かーエスパーの人つれてきてー

647 :NAME IS NULL:2009/01/31(土) 23:03:53 ID:???
なんだ、ほったらかしにされてたんだw

>>645
パラメータをつけるって、条件指定したいって事?それならできるよ。
hoge.php?ってなんのかわけわからんけど。

648 :NAME IS NULL:2009/01/31(土) 23:07:42 ID:???
phpにコードを渡す時の、URL入力イメージ

649 :NAME IS NULL:2009/01/31(土) 23:15:11 ID:???
となるとスレ違いだからよそ行って

650 :NAME IS NULL:2009/01/31(土) 23:23:40 ID:???
教えて下さい SQL 2005です

■小遣いもらったtable
人ID もらった日付 もらった額
■小遣い使ったtable
人ID 使った日付 使った額

があったとき、
人ID 今月もらった額合計 今月使った額合計 今年もらった額合計 今年使った額合計
みたいに、日付ごとの集計データを、横にならべて出力するには、どのように記述するが一番処理が速いかな?
集計したい期間は固定とします。


651 :NAME IS NULL:2009/02/01(日) 00:14:09 ID:???
>>647
レスありがとうございます。
条件指定だとどうなるのでしょうか? 教えていただけますか?

652 :NAME IS NULL:2009/02/01(日) 00:28:13 ID:???
>>651
select * from (ここにunion句) where key1=A1-0

653 :NAME IS NULL:2009/02/01(日) 00:54:03 ID:???
ありがとうございます

654 :NAME IS NULL:2009/02/01(日) 01:12:19 ID:???
>>650
2、3パターンぐらいはクエリ思いつくだろうから
それぞれで実行計画を比較するなり、
実行計画の中身見てボトルネック潰すなりすれば良いじゃない。

655 :NAME IS NULL:2009/02/01(日) 01:16:46 ID:???
>>650
SQL 2005なんて名称のRDBはないよ。
MS SQLのことなんだろうけど正確に使おうよ。

質問に関してだけど、どうのように書くかわからないのではなくて、どのように書いたら一番処理が速いかってことなら
あなたが考えたSQLを書いてみせて。
それより速いと思うものを書くからさ。

656 :NAME IS NULL:2009/02/01(日) 01:29:31 ID:???
>>655
一番処理が早いかな?
〜〜とします。
とか上から目線できてるけど,一行目に「教えてください」ってあるから
なんにも知らない宿題暴威じゃまいか?

657 :NAME IS NULL:2009/02/01(日) 04:11:33 ID:???
>>650
実際の件数とか、キーやインデックスの有無によって変わったりするし、
今のデータベースは、SQLを書いたとおりに実行されるとは限らない

まあ、早いのは集計済みのデータを持つテーブルを作って、
もらったtableと使ったtableのトリガで更新させるのが早いんじゃね

>>655
MS SQLなんていう名称のRDBもないと思うがな

他人に正確に使えっていう前に自分が正確に使わないと
説得力がないぞ


658 :NAME IS NULL:2009/02/01(日) 15:19:52 ID:???
>>657
Microsoft SQL Server (マイクロソフト エスキューエル サーバ)とは、マイクロソフトが開発している、リレーショナルデータベース管理システム (RDBMS)である。略称は「SQL Server」または「MS SQL」などと呼ばれている。

しらねえなら黙ってろ

659 :NAME IS NULL:2009/02/01(日) 15:32:39 ID:???
>>658
> 略称は
なんでここスルーしてしまうん?
略称OKになったらうちではSQLって略してる、がまかりとおってしまうじゃないか

660 :NAME IS NULL:2009/02/01(日) 15:35:28 ID:???
>略称は「SQL Server」

おまえはここスルーしてるんだろ?
Microsoft SQL Serverって言ってんの?
SQLは略称じゃねえだろ?
読解力あるの?


661 :NAME IS NULL:2009/02/01(日) 15:35:31 ID:???
>>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

662 :NAME IS NULL:2009/02/01(日) 15:36:07 ID:???
→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


663 :NAME IS NULL:2009/02/01(日) 15:41:55 ID:???
テーブルを
HitoMaster→HitoID HitoName
Morau→MorauID HitoID MorauDateTime MorauGaku
として、
HitoID 今月(@DateTime1)のもらった額、今年(@DateTime2)もらった額を表示するように記述してみた。
(使う額については、同じクエリで表示可能なので、省いた)

簡単に思いついたのは、以上の4つぐらい。こういうのは良くないとか、定石的にはコレとか。
もっと言いやり方があるとかあったらお願いします。

664 :NAME IS NULL:2009/02/01(日) 15:42:53 ID:???
>>660
ちげえちげえ。
MS SQLは略称であって正式名じゃない。
Microsoft SQL ServerをSQLと略す現場があるらしい。(このスレおよび過去スレ参照)
MS SQLという略称を許可するのであれば、SQLがそれを指している場合についても許可しなくてはならない。

665 :NAME IS NULL:2009/02/01(日) 15:54:25 ID:???
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は正確な略だって主張か?


668 :NAME IS NULL:2009/02/01(日) 16:51:03 ID:???
今頃気づいたの?
君だけだよ?わからなkったの

669 :NAME IS NULL:2009/02/01(日) 17:21:22 ID:???
略称はいいから質問に答えてやれよ
罵りあいはするが質問には答えない無能かよ

670 :NAME IS NULL:2009/02/01(日) 17:49:23 ID:???
>>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

671 :NAME IS NULL:2009/02/01(日) 18:01:37 ID:???
私ならviewを作る。
最低単位が月なら、人IDと月でgroup byさせるね。
使用区分みたいなカラムを作ってunion allね。

672 :NAME IS NULL:2009/02/01(日) 18:12:44 ID:???
>>671
パフォーマンスの質問なのにView作ったって解決にならんだろ
Materialized Viewのことを言っているならはじめからそう書くべきだし

673 :657:2009/02/01(日) 18:38:47 ID:???
たしかにパフォーマンスの解決にはならんが、俺がやるとしても
年月別の合計金額をもったビューをつくるな。集計期間が固定なら

で、パフォーマンス的に問題になるなら、インデックス張るとか
実表に作り変えてトリガで更新とかにする

つか、パフォーマンス優先するなら集計表つくってトリガで更新しろっていう
俺の意見はまったく無視ですか(インデックス付ビューつくれるならそれでもいいけど)

まあ、その4つで比べるなら実際に実行計画とってみればいいんじゃね
うちの環境ではデータ0件で実行計画とってみたら、
4番目が一番早いという結果になった



674 :NAME IS NULL:2009/02/01(日) 18:41:54 ID:???
>>672
まあそうなんだが実際はView作るだろ。
実用できないような架空のsql書いてもしょうがない。

675 :NAME IS NULL:2009/02/01(日) 20:02:22 ID:???
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
ちょっとスレミス
失礼

678 :NAME IS NULL:2009/02/02(月) 00:02:20 ID:???
> トヨタに あまぼーさんと うへへさんが乗ってたらどうすればいいのでしょうか?

何でトヨタがメーカーじゃなくてクライアントなのかよくわからんけど、

client_list から person_id なくして、代わりに

relation_table
person_id | client_id
  1      1
  2      2
  3      3
  4      4
  5      5
  6      6
  4      1

ってしとけばいいだけかと。

679 :NAME IS NULL:2009/02/02(月) 00:05:24 ID:???
きゃべつが人の名前ってのもすごい

680 :NAME IS NULL:2009/02/02(月) 00:54:00 ID:???
みんなありがとう

>>670
そうだね。今現在からみて、今年と今月なら、確かにそれでokですね。
ちなみにcase文を選択した理由がもしあったら教えてもらってもいいかな?

>>671-673
んーViewは結局、存在する月すべてで再計算することになるので遅くなるんじゃないかなと思って。
なら、ストアドかテーブル値関数を使うことになると思うんだけど、結局、
その中身(クエリ)が重要になると思うので、クエリをどう書くかという質問と同じになるので・・

>>673
>パフォーマンス優先するなら集計表つくってトリガで更新しろっていう俺の意見はまったく無視ですか
one fact in one placeの原則がありながら、その原則を排除してパフォーマンス重視のために
集計表を作る方法論は一応理解しているつもりなんだけど、
クエリの書き方としての方法論や、これはしてはいけないというような一般論があれば知りたかったので。
最初の質問の仕方が悪かったね。

>まあ、その4つで比べるなら実際に実行計画とってみればいいんじゃね
確かに、とにかく何でもいいから書いてみて速いのを選択すればいいというのも一つの方法だね。
他に速いクエリの書き方とかありそう?

681 :NAME IS NULL:2009/02/02(月) 01:07:45 ID:???
>>676
マルチ乙

682 :NAME IS NULL:2009/02/02(月) 02:16:27 ID:???
>>655
>あなたが考えたSQLを書いてみせて。
>それより速いと思うものを書くからさ。
速いSQLまだー(・∀・ )っ/凵 ⌒☆チン


683 :NAME IS NULL:2009/02/02(月) 03:31:42 ID:???
>>681

>>677

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の文章から「今現在からみて、今年と今月」以外の
どういう解釈があるのか逆に教えて欲しい。

686 :NAME IS NULL:2009/02/02(月) 11:57:20 ID:???
指定した日付から見て今月、今年じゃなかったんだ?
今現在からだけでいいならパラメータもいらないように思う

687 :NAME IS NULL:2009/02/02(月) 12:03:26 ID:m1gVv77i
load data infile で読み込む時に
エスケープ処理も同時にやってくれるんですかね

688 :NAME IS NULL:2009/02/03(火) 09:10:28 ID:???
>>685
ごちゃごちゃうるせえよ

689 :NAME IS NULL:2009/02/03(火) 23:23:43 ID:???
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なんですが・・



690 :NAME IS NULL:2009/02/03(火) 23:33:09 ID:???
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

とか

691 :NAME IS NULL:2009/02/03(火) 23:43:21 ID:???
>>689
OracleならDECODE関数で、
inu以外の変数をすべてNULLにしてしまえる。

692 :NAME IS NULL:2009/02/04(水) 00:04:39 ID:???
Nameも?

693 :NAME IS NULL:2009/02/04(水) 00:12:19 ID:???
>>692
あー、ごめん、出来ないね。

694 :NAME IS NULL:2009/02/04(水) 00:33:02 ID:???
>>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が同じレコードをマージすることができません。

非常にわかりづらい日本語と思いますが・・・



695 :NAME IS NULL:2009/02/04(水) 00:56:22 ID:???
もっと簡単に書ける。FULL OUTER JOINで調べてみて下さい。

696 :NAME IS NULL:2009/02/04(水) 01:28:37 ID:???
>>695
テーブルが分かれてればjoinでいけそうなんですが、
同一テーブルでも使えるのでしょうか?


697 :NAME IS NULL:2009/02/04(水) 01:58:37 ID:???
他にもNULLにしたいカラムがたくさんあるなら
(select No from A)
left join
(select * from A where Shubetu = 'inu')
using (No)
みたいな感じでやるといいと思う

698 :NAME IS NULL:2009/02/04(水) 02:02:51 ID:???
あらごめん。
リロードしてなかった。
別の要求が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)
という感じでできないですかね。

他にもいい方法がありそうにも思いつつ。

699 :NAME IS NULL:2009/02/04(水) 02:13:37 ID:???
>>698
どうもありがとうございます。
select結果をAやBやCとしてテーブル名として定義できるわけですね?

ただ、このSqlそのままだと構文エラーが起きます
syntax error at or near "select" at character 51 としか出ないので
さっきJOINを知った自分としては何がいけないのやら・・


700 :NAME IS NULL:2009/02/04(水) 02:15:30 ID:???
>>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);

701 :NAME IS NULL:2009/02/04(水) 02:20:07 ID:???
>>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

703 :NAME IS NULL:2009/02/04(水) 06:40:20 ID:???
そもそもその一行はいらんだろ。
自己結合をもう一度最初から勉強してこい。

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


このようにしたいのですが、どうすればいいですか?

705 :NAME IS NULL:2009/02/04(水) 09:52:51 ID:???
>>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
http://www-math.edu.kagoshima-u.ac.jp/~fractaro/database/
のSQL 練習問題 II、練習問題 III、Northwind 練習問題答えを導いてくれないですか?
正直どうしていいかわかりません。今日の13時までにお願いできれば。解説は省いていいです。

707 :NAME IS NULL:2009/02/04(水) 12:29:28 ID:???
13時から試験なの?
丸暗記で単位とってもあなたのためにならないと思うな

708 :がけっぷち:2009/02/04(水) 12:36:00 ID:YKEasflU
正直そのとうりなんですが、もう切羽詰まってるんです。お願いします。
13時からではないが覚えるにはそのくらいの時間にはできてないと・・・・13時半でも。

709 :NAME IS NULL:2009/02/04(水) 13:18:51 ID:???
鹿児島大学 教育学部 数学科 磯川 研究室

710 :NAME IS NULL:2009/02/04(水) 13:34:50 ID:???
練習問題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は答え教えてくれないですよね。・・・・・・ここまでの協力感謝

712 :NAME IS NULL:2009/02/04(水) 14:28:57 ID:???
問題4はただ答えだけ聞いても理解できないんじゃない?

713 :NAME IS NULL:2009/02/04(水) 14:34:26 ID:???
答えは教えないが解答案の添削ならするよ

714 :NAME IS NULL:2009/02/04(水) 14:57:49 ID:???
>>713
多謝。練習問題IIIについて解答案を作ってみた。

#問題1

(設問1)
主キーはデータインスタンスをただ眺めて見つける物ではなく、
データが表現している対象の構造を鑑みて自ら定義するものだ。
この販売表を使っている部門がどういうビジネスしているか
記述もないのに主キーなんておいそれと決め打ちできるか。

(設問2)
主キーを関係従属性に言い換えて、設問1と以下同様。

#問題3

いや、だからどれが主キーなんだと・・・
コードとか番号って書いてあったら自動的に主キーなのか?
ユニークに振られていると解釈すれって暗黙の了解なのか?

#問題4

問題3と同様。社員番号に関する定義が無い。

#問題5

問題3に対するクレームに加えて、分割した各リレーションの
主キーも答えさせてくれないと、無意味。

#問題6

問題5と同様。

#総じて
もちっと厳密に問題作ってくれない?

715 :NAME IS NULL:2009/02/04(水) 14:58:15 ID:???
誰もa1を選ばなかったら。。

716 :NAME IS NULL:2009/02/04(水) 15:01:16 ID:???
>>714

関係従属性->関数従属性

717 :NAME IS NULL:2009/02/04(水) 15:06:27 ID:???
>>714
おおむねダメだな。

> この販売表を使っている部門がどういうビジネスしているか
それが分かったら主キーが決まるという発想が既にずれている

> いや、だからどれが主キーなんだと・・・
主キーがどれであるかが最重要懸念事項ではない

後続も大抵ずれてるんだろうと思うので、採点するなら大きく×をつける。

718 :NAME IS NULL:2009/02/04(水) 15:18:16 ID:???
>>714はネタだよね?

それはともかく
売上日の列がない販売表ってすごく不思議だな

問1設問1でオ以外の誤答に×をつけるには
相当行間と空気を読む必要がある

719 :NAME IS NULL:2009/02/04(水) 15:19:16 ID:???
> 主キーがどれであるかが最重要懸念事項ではない
アとエの両方が可能だと思うのだが、複数回答可能なのかな。

720 :NAME IS NULL:2009/02/04(水) 16:46:10 ID:???
>>717
まあ、>>714は即席のネタなんですが、正直良くない問題だなと
思ったので。

>> この販売表を使っている部門がどういうビジネスしているか
>それが分かったら主キーが決まるという発想が既にずれている

いや、それすら分からないと主キーは決められないでしょう。
要するに問いにちゃんと答えるには与えられた情報が少なすぎる。

>> いや、だからどれが主キーなんだと・・・
>主キーがどれであるかが最重要懸念事項ではない

重要度はともかく要検討事項です。
ISBNと著者コードがそれぞれ主キーだという制約がないとアとエは
常に実行可能、ウは選択肢の解釈次第だけど条件付き可能です。
あと参照の向きも示されていない。著者テーブル->書籍テーブルの
向きだったらイだって実行可能と解釈出来なくもない。

主に正規化に関する練習問題なのに、回答する上で考慮しなければ
ならない関数従属性が明確に示されていないのは困る。
設問中にも記述が殆どないし、設問中で示されたスキーマの中でも
主キー制約の形でそれが表現されているわけでもないし・・・

・・・空気なのか。やはり空気なのか。
空気が読めなくて落第しそうです。

721 :NAME IS NULL:2009/02/04(水) 17:04:34 ID:???
ISBNは一般常識で主キーにしていいと思う

ま、空気でなかったら講義中に補足があったのかもね
納得いかなかったら教授とっつかまえて問い詰めればいいんじゃない?

722 :NAME IS NULL:2009/02/04(水) 17:22:29 ID:???
>>720
主キーかどうかじゃなくてユニーク制約がついてるかどうかが大事なんじゃないの

723 :NAME IS NULL:2009/02/04(水) 17:52:54 ID:???
主キー制約ではなくユニーク制約にするとNULLも考慮する必要が
出てきて、場合によっては問題が面倒くさくなるので。
出題者側としてはシンプルに答えさせるのであれば主キー制約を
明示しておくのが適切なのでは。

724 :NAME IS NULL:2009/02/04(水) 23:37:24 ID:???
数学科の先生でデータベースは専門じゃないんだろうけど、こりゃひどい。

設問3

ア 「同一のISBNを持つ異なる書籍」が存在するなら、単独の「ISBN番号」は主キーたりえない
イ 書籍テーブルの「著者コード」がNULL可なら可能
ウ ON DELETE CASCADEなら...

そもそも、「リレーションを付ける」って何だw

725 :NAME IS NULL:2009/02/05(木) 00:42:00 ID:???
たとえば、以下の様なデータが有ったとして、

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


726 :NAME IS NULL:2009/02/05(木) 00:49:11 ID:???
SQL> SELECT BASE FROM TABLE_A ;
SQL> SELECT SYS_DIR FROM TABLE_B ;

727 :NAME IS NULL:2009/02/05(木) 01:00:13 ID:???
>>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が必要か・・・
まあ、そんな感じなんですけど。どっちがいいでしょうか。
また、こっちのほうがいいというのがあったらアドバイスください


729 :NAME IS NULL:2009/02/05(木) 14:17:49 ID:???
普通に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 ~~~~~
って感じですかね?

731 :NAME IS NULL:2009/02/05(木) 20:57:35 ID:???
VIEWの利点って何ですか?

732 :NAME IS NULL:2009/02/05(木) 21:33:20 ID:???
テーブル作らなくていい

733 :NAME IS NULL:2009/02/05(木) 21:53:36 ID:???
>>731
好きな列や行だけを表(テーブル)として保持できる。

734 :NAME IS NULL:2009/02/05(木) 21:55:47 ID:???
>>731
こんなもんかな?

利点:
・クエリが(一見)単純になる
・あらかじめパフォーマンスチューニングしたVIEWを定義することで
 あとから書くクエリではパフォーマンスを考慮しなくて良くなる(場合がある)
・行や列ごとにセキュリティかけたい場合に使えたりする

欠点:
・あとからロジックを追うのが面倒(な場合がある)
・あとからパフォーマンスチューニングするのが面倒(な場合がある)

735 :NAME IS NULL:2009/02/05(木) 23:07:48 ID:???
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 号俸


737 :NAME IS NULL:2009/02/05(木) 23:41:21 ID:???
VBのコードも書いてみ。

738 :NAME IS NULL:2009/02/06(金) 00:47:12 ID:???
2つのテーブル結合の例は多いですが
3つのテーブル結合ってのはあまりよろしくないんでしょうか?

739 :NAME IS NULL:2009/02/06(金) 02:18:29 ID:???
なじぇに?

740 :NAME IS NULL:2009/02/06(金) 03:23:17 ID:???
例を挙げるのに2テーブルで事足りただけでいくつ結合しても問題ないよ

741 :NAME IS NULL:2009/02/06(金) 11:38:14 ID:???
>>736
部署, 等級, sum(金額) where 部署 in (グループ化マスターで「等級」になってる部署) group by 部署, 等級
union
部署, 号俸, sum(金額) where 部署 in (グループ化マスターで「号俸」になってる部署) group by 部署, 号俸
ってこと?

742 :NAME IS NULL:2009/02/06(金) 12:03:29 ID:???
DELETE 社員マスター WHERE 金額 > 1000

743 :NAME IS NULL:2009/02/06(金) 22:28:15 ID:???
PDO使うときって、ロックって概念はないの?

744 :NAME IS NULL:2009/02/06(金) 22:49:32 ID:???
あるよ

745 :NAME IS NULL:2009/02/06(金) 23:24:48 ID:???
>>744
トランザクションを発行すると、自動的にロックになるんではないの?
それとも、トランザクションをして、なおかつ、自分でまたロックもするの?

746 :NAME IS NULL:2009/02/07(土) 00:47:45 ID:???
>>740
ありがとうございます。
3つのテーブルをJOIN結合させたいのですが、例を書いていただけませんでしょうか?

747 :NAME IS NULL:2009/02/07(土) 00:48:01 ID:???
ぐぐれよ

748 :NAME IS NULL:2009/02/07(土) 14:34:24 ID:???
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     さんま

この結合お願いします。


749 :NAME IS NULL:2009/02/07(土) 14:41:53 ID:???
>>748
select *
from Dテーブル
   inner join
   Aテーブル
   using (id)
   Cテーブル
   using (u_id)
   inner join
   Bテーブル
   using (f_id)

750 :NAME IS NULL:2009/02/07(土) 15:01:49 ID:???
>>749
ありがとうございます。
けどエラーが出ます。。

751 :NAME IS NULL:2009/02/07(土) 15:03:35 ID:???
>>750
Cテーブルの前にinner joinが抜けている
usingが使えなきゃon

てかエラー内容ぐらい書いたらどうなんだ?

752 :NAME IS NULL:2009/02/07(土) 15:11:29 ID:???
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'

よろしくお願いします

753 :NAME IS NULL:2009/02/07(土) 15:26:38 ID:???
MySQLのバージョンも書いておいた方がよいかも。

754 :NAME IS NULL:2009/02/07(土) 15:33:58 ID:???
JOINだ何だというテーブル結合式にどうしても馴染めなくて
常にFROM句にテーブル名列挙+WHERE句に結合条件列挙
なのですが、この先何か困る事はあるでしょうか。

755 :NAME IS NULL:2009/02/07(土) 15:36:22 ID:???
>>753
お手数お掛けして申し訳ないです
MYSQL 5.1.30

756 :NAME IS NULL:2009/02/07(土) 15:37:48 ID:???
既に読み辛いだろう

757 :NAME IS NULL:2009/02/07(土) 15:47:38 ID:???
そうですか〜

選択リストはカラム参照だけ。
FROM句はテーブル列挙だけ。
WHERE句は条件式列挙だけ。

綺麗に棲み分けて案外読みやすいと思うのですが。

758 :NAME IS NULL:2009/02/07(土) 15:58:07 ID:???
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文って可能でしょうか?
良い方法が思いつかないのでどなたかお教えいただけると幸いです。


760 :NAME IS NULL:2009/02/07(土) 16:02:09 ID:???
age てしまった。
申し訳ない。

761 :NAME IS NULL:2009/02/07(土) 16:21:51 ID:???
>>758
結合も所詮直積+制約なので、制約条件がWHERE句にあったり
FROM句の中にあったり省略されてたりするのが何とも。

SELECT句で射影
FROM句で直積
WHERE句で制約

で良いではないですか。
確かに外部結合ぐらいかなぁ。

762 :NAME IS NULL:2009/02/07(土) 16:39:20 ID:???
>>759
where 購入数/限度個数 * 100 >= 90
ってやったら?

763 :NAME IS NULL:2009/02/07(土) 16:40:54 ID:???
>>761
結合を直積+制約と考えるのは微妙だな
select * from Table1 A, Table2 B where A.ID = B.ID or A.ID is null
で外部結合できるかというとそうでもない

764 :NAME IS NULL:2009/02/07(土) 16:44:57 ID:???
>>762
ありがとう。
where をくっつけるだけでOKでした。


765 :NAME IS NULL:2009/02/07(土) 16:47:26 ID:???
>>763
すみません。内部結合の事ですね>直積+制約。
確かに外部結合はテーブル結合式使わないと書くのも面倒だし
多分遅いです。

766 :NAME IS NULL:2009/02/08(日) 11:39:00 ID:???
・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処理が走るようにするにはどうすればよいのでしょうか?

767 :NAME IS NULL:2009/02/08(日) 11:46:20 ID:???
>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 山田君

769 :NAME IS NULL:2009/02/08(日) 12:25:45 ID:???
Union

770 :NAME IS NULL:2009/02/08(日) 12:30:14 ID:???
>>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 エリア情報;

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

772 :NAME IS NULL:2009/02/08(日) 12:59:41 ID:???
わざわざ二重管理するってのは意味不明だけどね

773 :NAME IS NULL:2009/02/08(日) 13:02:16 ID:???
後半のSELECT文でVIEW作ればいいよな

774 :519:2009/02/08(日) 20:28:12 ID:???
>>769-770
なんという魔法のクエリー
うまくいきました!ありがとうございますm(_ _)m
これwhere句は両方いるんだろうか・・色々試してみるか・・


775 :NAME IS NULL:2009/02/09(月) 22:43:06 ID:???
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

・説明
データテーブルの中に、コードがカンマ区切りで入っています。
データテーブルに入っているコードを値に置き換えて、
カンマ区切りで出力したいのですが、この様なことはできますか?


777 :NAME IS NULL:2009/02/10(火) 10:59:02 ID:???
ストアドプロシージャーでFOR文を使って、
SELECT Value_temp1 || ', ' || Value_temp2
FROM マスタ

とかどうでしょう。

778 :NAME IS NULL:2009/02/10(火) 12:13:45 ID:???
>>776
設計が悪い

779 :NAME IS NULL:2009/02/10(火) 15:05:27 ID:???
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;


781 :NAME IS NULL:2009/02/10(火) 19:51:14 ID:???
>>780
トランザクションの分離レベルをDirty Read(Uncommitted Read)にしてない限りそうなる

782 :NAME IS NULL:2009/02/10(火) 20:56:05 ID:???
銀行系の例題で必ず出るよね、そういう話題。

783 :NAME IS NULL:2009/02/10(火) 22:52:39 ID:???
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文で、データーベースの内部で調べるものなの?

784 :NAME IS NULL:2009/02/10(火) 22:55:15 ID:???
どっちでも。

SQL に関係ないからスレ違いだな。

785 :NAME IS NULL:2009/02/10(火) 23:02:10 ID:???
データーベース内部で
「1より多いか?少ないか?」
を判別するのはどうやるの?

786 :NAME IS NULL:2009/02/10(火) 23:03:29 ID:???
>>783
DB 側でのチェックは必須

1) if B >=1ってチェックをかけて、それで「OK」って出たら、
2) そこではじめてBの口座の数字を1減らす、

1) と 2) の間に B が1万円引き出すこともあるから PHP だけの
チェックだとダメ。

PHP 側でもやるかどうかは組み方次第だけど、個人的には >>784
言うように両方でやるというケースが多いように思う。

# て言うか、その銀行って1万円単位なのか!?

787 :NAME IS NULL:2009/02/10(火) 23:03:55 ID:???
>>521の人だろ

788 :NAME IS NULL:2009/02/10(火) 23:17:15 ID:???
>>786
(1)PHP側でif B >=1ってチェックをかける
(2)「OK」って出る
(3)Bのバカ野郎がタイミング悪く、自分で1万円引き出し口座の残高が0になる
(4)Bの口座から1万円減らす(残高はマイナス1万円)

こういう状況を懸念しているわけですね?
でもそのためにトランザクションというものがあるのではないですか?

つまり、(1)から(4)までの間にトランザクションで
防御しておけば、(3)の割り込みは発生しないですよね?

789 :NAME IS NULL:2009/02/10(火) 23:18:43 ID:???
それと、データーベース側で、
Bの口座の残高が1万円以上あるのかないのか、
調べるのはどうしたらいいですか?

なんかそれらしき命令が見当たらないのですが。
SQLにif文って、あるのですか?

790 :NAME IS NULL:2009/02/10(火) 23:24:21 ID:???
>>786
銀行って言ってもゲームの中の銀行ですけどね。
お金もゲームの中のお金。
SOLD OUTみたいなの。

http://uil.sakura.ne.jp/soldout/index.cgi

791 :NAME IS NULL:2009/02/10(火) 23:28:44 ID:???
ちなみにゲームの中の銀行といえども、
実際の運用は本物の銀行と大差ありません。

現在の銀行はほとんどのお金が
データーベース上の数字として存在しているだけです。

紙幣の受け入れとか硬貨の払い出しとかが
ないだけで、それ以外は基本、全部同じと思っていいでしょう。

792 :NAME IS NULL:2009/02/10(火) 23:33:09 ID:???
更新ロックかけてupdate文にwhereすればいいんでないか

793 :NAME IS NULL:2009/02/10(火) 23:34:42 ID:???
>>792
それだとわかりません。
もっと詳しく

794 :NAME IS NULL:2009/02/10(火) 23:40:41 ID:???
また荒らしか・・・

795 :NAME IS NULL:2009/02/10(火) 23:46:23 ID:???
>792に書いてあることが理解できないなら、そんなシステム捨てましょう。
>786,788での重要なポイントも理解できてないでしょ、あなた。

796 :NAME IS NULL:2009/02/11(水) 01:24:03 ID:???
PHPでsqlite3の
データーベースをロックするには
どうしたらいいんだ?

797 :NAME IS NULL:2009/02/11(水) 01:24:47 ID:???
SQLで、データーが1以上かどうか、って
判別するのって無理じゃないか?

798 :NAME IS NULL:2009/02/11(水) 01:33:10 ID:???
(0)トランザクション開始
(1)SELECTでデーターを取ってくる
(2)1より小さいか、if文で確認
(3)もし1より小さかったら、「残高が足りません」と表示
(4)ロールバック

(5)もし1以上だったら、
(6)マイナス1するUPDATE文を発行
(7)コミット文を発行して確定

↑これでいいんじゃない?

799 :NAME IS NULL:2009/02/11(水) 01:36:45 ID:???
(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にすることによって最適化されるのでしょうか?

801 :NAME IS NULL:2009/02/11(水) 02:30:39 ID:???
>>799
(5)で1以上だったらという前提で処理を進めている中で、1以下だったらどうすんだと言われてもね。

>>800
場合にもよるが、複数列インデックスを作った方がいい。
ex.) CREATE INDEX new_idx ON sampletable (model, name);

802 :NAME IS NULL:2009/02/11(水) 03:09:26 ID:???
素人だけど
WHERE model="45" and name="△△"
なら個別のインデックスでも使用されなかったっけ?

803 :NAME IS NULL:2009/02/11(水) 03:36:07 ID:???
残念ながらどちらか片方だけだね

804 :NAME IS NULL:2009/02/11(水) 03:55:26 ID:???
そうなんだ。インデックス張る順番は関係あるの?

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」 の部分は一般的になんと呼べばいいでしょうか?
カラムとは違いますよね?

806 :NAME IS NULL:2009/02/11(水) 07:03:13 ID:???
>>805
http://dev.mysql.com/doc/refman/5.1/ja/select.html

807 :NAME IS NULL:2009/02/11(水) 07:07:24 ID:???
>>788
トランザクションといっても、RepeatableRead以上である必要がある。念のため。

808 :NAME IS NULL:2009/02/11(水) 12:13:50 ID:???
>>804
張る順番は関係ないよ。
古いDBならWHERE句の書く順番に関係があったが、
今時のならプランナやオプチマイザが摘便に判断する。

809 :NAME IS NULL:2009/02/11(水) 12:26:17 ID:???
>>807
トランザクションにもレベルがあるんだ?

810 :NAME IS NULL:2009/02/11(水) 16:25:42 ID:???
>>808
なるほど
張る順番はLIKE検索の時の関係してくるんだっけか。
それよりwhere句で条件を2つ以上使うとインデックス使われないというのは知らんかった。
どこか詳細なサイトとかある?
大抵のクエリは複数条件だろうから単一インデックスじゃほとんど意味ないのね。

811 :NAME IS NULL:2009/02/11(水) 16:26:58 ID:???
そんなのエンジンの実装次第だろよ・・・

812 :NAME IS NULL:2009/02/11(水) 16:40:37 ID:???
>>811
kwsk

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

となってしまいます.
結合が上手くいっていないような感じなのですが、どうでしょうか?
#テーブル毎に検索してから結果を結合というのはナシの方向でお願いします.

815 :NAME IS NULL:2009/02/11(水) 18:17:29 ID:???
ナゲー

816 :NAME IS NULL:2009/02/11(水) 18:29:52 ID:???
・とりあえず外部結合が必要な要件が見つからない。
 全部INNER JOINに書き換えて要観察。

・CREATE TABLEでデータ突っ込むのにORDER BYは
 無意味だし誤解の元なので止めておけ。
 ORDER BYは後でテーブルから実際にデータを検索
 するときに明示的に指定すること。

817 :NAME IS NULL:2009/02/11(水) 18:44:14 ID:???
ごめんなさい。>>816はかなり外したこと言っていた。
原作無しや属性無しの同人誌もあるわけだよね。

rollback!

818 :813:2009/02/11(水) 21:20:57 ID:fk2Zdes0
自己解決しました。
マスタテーブルとN:Nテーブルの結合時にONで指定するカラムが間違っていました・・・
(例えば同人誌マスタとサークルマスタの結合時に「Catalog.id=Publisher.id」とするべきところを
「Catalog.id=Publisher.cid」としていたことが原因でした。)

819 :NAME IS NULL:2009/02/11(水) 21:46:51 ID:???
もしかして、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] とか書けば可能なものもある。

822 :NAME IS NULL:2009/02/12(木) 01:24:59 ID:???
>>819
作れたとしても、誤解の元だからユニークな名前を付けましょう。

823 :NAME IS NULL:2009/02/12(木) 03:15:53 ID:???
>>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

824 :NAME IS NULL:2009/02/12(木) 13:26:31 ID:???
>>808
・ID
・年度ID
・期間ID
・ユーザID
・値

な感じで、IDにPK、各3IDにINDEXを張ってるんだけど、
where 年度ID = x AND 期間ID = y AND ユーザID = z
と検索するとINDEX使われないの?
実際はその3つで一意に決まるからIDやめて年度と期間とユーザでPKにしたほうがいいのかな?


825 :NAME IS NULL:2009/02/12(木) 15:08:51 ID:???
>>810
LIKEでもインデックスを張る(CREATE INDEX)順番は関係ないと思うがな。

>>824
DBも日々進化しているし、俺が気づいてないだけかもしれんが、

そのWHERE句の中で、一番絞り込み安いIDをINDEX検索して、
他のIDでフィルタを掛ける感じになる。
どのIDでINDEX検索するかは、プランナが判断する。
3IDで一意になるなら、ユニークインデックスを作っていた方がいいと思う。

っていうかさ、SELECT文がどのように実行されるか、クエリープランを出力してみりゃわかるでしょ。
例えばPostgreSQLならEXPLAIN文がそう。

826 :NAME IS NULL:2009/02/12(木) 15:24:09 ID:???
DB2にもそういうコマンドあるよ。

827 :NAME IS NULL:2009/02/12(木) 20:13:58 ID:???
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です。
お願いします。

828 :NAME IS NULL:2009/02/12(木) 20:16:07 ID:???
宿題をやらせるなら、せめて文言をそれらしく変えなよ…

829 :NAME IS NULL:2009/02/12(木) 20:32:03 ID:???
こういう primary key の設定って、うっかり duplicate key になったりしないものなんだろうか。


830 :NAME IS NULL:2009/02/12(木) 21:02:18 ID:???
>>827
ヒント:order byにcase式を使う

831 :NAME IS NULL:2009/02/12(木) 21:37:00 ID:???
case文なんか使う必要ないだろ

832 :NAME IS NULL:2009/02/13(金) 00:22:46 ID:???
boolでソートできるからね

833 :NAME IS NULL:2009/02/13(金) 02:35:55 ID:???
>>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;

834 :NAME IS NULL:2009/02/13(金) 02:59:27 ID:???
>>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

とやると、部門と従業員数は出てくるのですが、そこから先がわかりません。
よろしくお願いします。



837 :NAME IS NULL:2009/02/13(金) 19:46:19 ID:???
not in でいいじゃん。

838 :NAME IS NULL:2009/02/13(金) 19:56:08 ID:???
>>837
え、not in でできますか?

839 :NAME IS NULL:2009/02/13(金) 20:02:12 ID:???
not existsだろ普通

840 :NAME IS NULL:2009/02/13(金) 20:08:09 ID:???
select id
from departmetns
where id not in (select department_id from employees)

841 :NAME IS NULL:2009/02/13(金) 20:53:39 ID:???
サンプルDBレベルじゃ違いが分からんだろうが
実環境で>>840なんかやったらとんでもなく遅い

842 :NAME IS NULL:2009/02/13(金) 20:59:53 ID:???
社員数千人レベルなら余裕だなw

ま、それはそれとして、速いクエリがあるなら教えてやれよ。
俺はわからんから>>840でいいけど。

843 :NAME IS NULL:2009/02/13(金) 21:00:14 ID:???
>>841
そうでもないと思うよ


844 :NAME IS NULL:2009/02/13(金) 21:00:21 ID:???
>>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が対応してないような。



845 :NAME IS NULL:2009/02/13(金) 21:40:31 ID:???
>>836
select id from departments
except
select distinct departments.id from employees

じゃだめかな。

846 :NAME IS NULL:2009/02/13(金) 22:21:49 ID:???
>>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述語と同等のものになっていた。

848 :NAME IS NULL:2009/02/14(土) 01:03:21 ID:???
( ;∀;) イイハナシダナー

849 :NAME IS NULL:2009/02/14(土) 17:57:25 ID:???
ttp://blog.hobbystock.jp/report/images/tp0108/014.jpg
お美しい・・・

850 :NAME IS NULL:2009/02/14(土) 19:55:36 ID:hb0oePnz
PostgreSQL
質問テンプレ】
・DBMS名とバージョン PostgreSQLだと思います。。。
・テーブルデータ長いのでhttp://rg550.hp.infoseek.co.jp/cgi-bin/joyful/img/595.txtでお願いします
勝手ながらどうしても今日中に終わらせたいのですがお力をかしてもらえないでしょうか?
よろしくお願いします。

851 :NAME IS NULL:2009/02/14(土) 20:49:17 ID:???
>>850
宿題を手伝うのはどうかと思うが一応自分でも考えてるようなので

2は1のSQLのselect句に
case count(評価値) when 5 then '合格' else '不可' end
を追加

3は1のSQLに
having count(評価値) = 5
を追加

852 :NAME IS NULL:2009/02/14(土) 20:56:45 ID:???
せっかく学校でDBを体系的に学べる機会をもったいねぇ

853 :NAME IS NULL:2009/02/14(土) 21:02:07 ID:???
>>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は皆様のを参考にもう少し考えて理解したいと思います。
ありがとうございます<(_ _)>

857 :NAME IS NULL:2009/02/14(土) 21:32:13 ID:???
>>851
課題テーブルが提出状況のboolean値を持っているので、可不可の判定
もこれを使うのが適当じゃないのかな。
相関サブクエリーで提出状況がtrueの数を数え上げるのが良いと思う。

858 :853:2009/02/14(土) 21:38:03 ID:???
>>855
スマソ、提出状況と評価値を混同してた。

>>856
学生名を出力しないのはどうかとおもうぞ。

859 :850:2009/02/14(土) 21:42:22 ID:???
課題のテーブルなども自分で考えて作ったので必要ない属性や
間違っているところもあるかもしれません;

860 :NAME IS NULL:2009/02/14(土) 21:43:41 ID:???
こんどvistaのノートパソコンを買うつもりなんですが、
Common SQL Environment はvistaに対応されてないので使うことができないかもしれません。

使えなかったときのためにこれに代わるソフトウェアを教えてください。

861 :853:2009/02/14(土) 21:46:12 ID:???
>>857
俺も最初そう思った。でも、>>851の言うように提出状況は他のカラムから判断できるのよね。
課題が増えたりすると面倒だけどさ。>>859で課題テーブルは850が作ったって言ってるし。

862 :NAME IS NULL:2009/02/14(土) 21:46:31 ID:???
どうみてもスレ違いだな・・・

863 :NAME IS NULL:2009/02/14(土) 21:55:13 ID:???
>>861
う〜ん、問題に
「各課題のデータは学籍番号と提出の有無、および評価値を持つ」
と書いてあるので、提出状況カラムの存在はマストだと思った。

あと未提出の課題の得点をNULLにするのは運用として有りだけど、
それだと「未提出課題の得点はマイナス一万点!」なんてのたまう
お茶目な教官のリクエストに応えられない。

864 :NAME IS NULL:2009/02/14(土) 22:11:20 ID:???
本当はこれぐらいに分けた方が良いのだけど。

学生マスタ (学籍番号, 学生氏名) PK: 学籍番号
課題マスタ (課題番号, 課題名) PK: 課題番号
配点マスタ (優良可, 得点) PK: 優良可
課題状況 (課題番号, 学籍番号, 提出状況, 優良可)
PK: 課題番号, 学籍番号 FK: 課題番号, 学籍番号, 優良可

865 :NAME IS NULL:2009/02/14(土) 23:05:54 ID:???
配点マスタって何?

866 :NAME IS NULL:2009/02/14(土) 23:25:54 ID:???
質問いいですか?
Hyou1(Pk,...)
Hyou2(Fk,...)において、
FkはPkと同じドメインじゃないと、
Fkが外部キーだと言える条件の一つを満たさないんですよね?

867 :NAME IS NULL:2009/02/15(日) 00:35:23 ID:???
>>860
黒猫 SQL Studio はどう?

868 :NAME IS NULL:2009/02/15(日) 00:39:08 ID:???
>>860
「CSE Vista」でググれ

869 :NAME IS NULL:2009/02/15(日) 04:46:20 ID:???
質問

SQL文というのは、基本的に、
必ずテーブル名を指定して使うものなの?

つまり、テーブル名の指定無しに
使うというのは、無理なの?

870 :NAME IS NULL:2009/02/15(日) 05:15:28 ID:???
そんなことない

871 :NAME IS NULL:2009/02/15(日) 08:49:28 ID:???
>>865
> 配点マスタって何?

何でかは知らんけど、元々のデータは得点 (1, 3, 5) なのに >>864 は優良可で
保持するように勝手に変更してるので、わざわざ優良可から得点を求めるための
テーブルが必要になってみたい。

簡単な問題をわざわざ複雑にして、得意がるタイプの人なんじゃないかな。

872 :NAME IS NULL:2009/02/15(日) 08:55:08 ID:???
>>869
RDBMSのパラメーター変更にもSQLを使うことがあるので、
その言い方は必ずしも正しくない。

あなたは「CREATE DATABASE」をテーブル名が指定されていると思いますか?

873 :NAME IS NULL:2009/02/15(日) 09:07:10 ID:???
select 1; だって、from table_name がないけど、立派なselect 文でしょ。

874 :NAME IS NULL:2009/02/15(日) 09:13:18 ID:???
CREATE DATABASEがSQLかっていうと少なくとも標準SQLではない
>>873も標準SQLではない

それはさておき、>>869は質問の意図がよくわからんが
「どのテーブルでもいいから条件にマッチするデータを全部もってこい」
みたいなことを言っているなら、無理

875 :NAME IS NULL:2009/02/15(日) 09:16:36 ID:???
>>>873も標準SQLではない

そうなのか、それはすまなかった。撤回する。

876 :NAME IS NULL:2009/02/15(日) 11:53:49 ID:???
>>846
oracleの無料セミナーだと*にするとライブラリだかディクショナリを読みに行くから定数にしたほうが速いらしいよ。
他のDBMSは知らんけどまあ納得して*は対話実行のときしか使ってない。count(*)もcount(1)にしてる。

877 :NAME IS NULL:2009/02/15(日) 12:12:37 ID:???
>>876
それいつ頃のセミナー?
昔は確かにSELECT 1 とかcount(PKカラム)なんかも言われてたけど、
今でもそうなの?

878 :NAME IS NULL:2009/02/15(日) 17:43:28 ID:???
>>877
いや最近はオプティマイザに任せるほうが速い。

879 :NAME IS NULL:2009/02/15(日) 19:35:52 ID:???
意味的には変わってくるな

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は変わらないから、そんな事したことないけどね。

881 :NAME IS NULL:2009/02/15(日) 22:21:15 ID:???
・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も結果として必要ですね
御免なさい

883 :NAME IS NULL:2009/02/15(日) 22:22:35 ID:???
ちょっと前に似たようなのあるだろ・・・
少しは過去ログ参照しろよ

884 :881:2009/02/15(日) 22:29:49 ID:???
申し訳ありませんでした、有難うございます

885 :NAME IS NULL:2009/02/16(月) 01:05:15 ID:???
>>881
oracleの差集合は「MINUS」で取得できる。


886 :NAME IS NULL:2009/02/16(月) 02:04:19 ID:???
フィールドとカラムってどう違うの?

887 :NAME IS NULL:2009/02/16(月) 02:50:24 ID:???
用語の組み合わせが違う。

数学的にはリレーションは「ドメインの直積の有限部分集合」と考えるけど、
この時はリレーション(関係)・タプル(組)・アトリビュート(属性)という用語の
組み合わせを用いるのが一般的。

で、このリレーションを具体的に表現する方法としてはグラフやクロス表
(cross tabulation)もあるけれども、もっとも一般的なのは行・列の表形式。
この時はテーブル(表)・ロウ(row, 行)・カラム(列)という組み合わせになる。

さらにリレーションをデータの出し入れをするストレージとして捉えるときに
ファイル・レコード・フィールドといった用語を用いる事もある。

実際の用法としてはごっちゃになっているけれども、少なくともリレーション
から始まる三つ組みとテーブルから始まる三つ組みは混ぜない方が良い
と思う。

888 :NAME IS NULL:2009/02/16(月) 11:06:14 ID:???
質問です

・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分以上かかってしまいます。
より高速に実現できそうな方法はありますでしょうか?

宜しくお願いします。

889 :NAME IS NULL:2009/02/16(月) 11:42:51 ID:???
sumなんだけど、
これってカラム名しか入れられないの?

sum(1,2,3)
とかってしたら、そんなカラム名おかしいよ、って
エラーになった。

890 :NAME IS NULL:2009/02/16(月) 11:43:24 ID:???
>>887
わかったありがと

891 :NAME IS NULL:2009/02/16(月) 17:22:35 ID:???
>>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

892 :NAME IS NULL:2009/02/16(月) 18:27:07 ID:???
>>887
ちょーさんこうになった。
886じゃないけどさんくす。

893 :NAME IS NULL:2009/02/16(月) 18:47:30 ID:???
>>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でした。

今後は質問する前にまずインデックスをつけます・・・

895 :NAME IS NULL:2009/02/16(月) 19:57:38 ID:???
MySQLで既存のインデックスを変更するには、いったん削除してから作成するしか方法はないでしょうか。
SQL一発で変更する方法があれば教えてください。

896 :NAME IS NULL:2009/02/16(月) 20:19:18 ID:???
「変更」というか、MYISAM なら myisamchk -rq というので作り直せるが…

897 :NAME IS NULL:2009/02/16(月) 22:56:21 ID:???
ALTER 無いの?

898 :NAME IS NULL:2009/02/16(月) 23:31:45 ID:???
DISTINCTって遅いイメージがあったんだがな。

899 :NAME IS NULL:2009/02/17(火) 00:43:06 ID:???
GROUP BYが速くなる理由もあまりない。

900 :NAME IS NULL:2009/02/17(火) 03:24:23 ID:???
一応10万entryで10tag/entryの合計100万レコードのダミーデータ
作って試してみたら断然DISTINCTの方が速い。

DISTINCT: 0.0007s
GROUP BY: 0.03s

このクエリの場合はLIMIT 5が効いている。
これがないとDISTINCTも0.03秒かかる。

901 :NAME IS NULL:2009/02/17(火) 06:46:57 ID:???
LIMITの功績じゃねえか

902 :NAME IS NULL:2009/02/17(火) 09:32:57 ID:???
どういうSQLだ?

903 :NAME IS NULL:2009/02/17(火) 15:27:21 ID:???
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
で重複するデータは抜き出せますが、その先がわからないので
アドバイスをいただけたらと思います。


904 :NAME IS NULL:2009/02/17(火) 15:48:06 ID:???
>>902
>>891のクエリ。
重複排除にDISTINCTとGROUP BYを使った比較です。

905 :NAME IS NULL:2009/02/17(火) 17:04:46 ID:BoDPs+dN
MySQL5の文字コードで質問です。
eucjpmsとujisは何が違うのでしょうか?
どちらを使った方がいいのでしょうか?
ちょっとググっても分らなかったので、分かる方、教えて下さい。

906 :NAME IS NULL:2009/02/17(火) 17:18:27 ID:???
>>903
何処を見て重複していると判断するのか、
どういう基準で残す行を決めているのかワカランがな。

とりあえず、nameとtitleが同じなら重複。
idはユニークで、値の小さい方を残す。
と言うのなら、

DELETE FROM table1 AS T1 WHERE id != (SELECT min(id) FROM table WHERE name=T1.name AND title=T1.title);

907 :NAME IS NULL:2009/02/17(火) 18:27:05 ID:???
何を持って重複なのかがイマイチ不明。
消しちゃいけない行を消しそうな予感。

908 :NAME IS NULL:2009/02/18(水) 09:41:21 ID:???
なんで>>906を言い換えただけの内容で書こうと思ったの?

909 :NAME IS NULL:2009/02/18(水) 10:07:22 ID:???
なんで直前のレスを言い換えただけの内容で書こうと思ったの?

910 :NAME IS NULL:2009/02/18(水) 20:02:21 ID:05nLCNr6
SQLであるひとつのテーブルのデータをすべて抽出して、
ORDERBYで並び替えてから同じテーブルに登録しなおすにはどうしたらいいですか?

911 :NAME IS NULL:2009/02/18(水) 20:23:04 ID:???
>>910
RDBの概念にレコードの順番という概念はない。
特定の実装ならあるかもしれんから、環境をちゃんと書け。

912 :NAME IS NULL:2009/02/18(水) 20:24:11 ID:???
>>903
>906のやり方でできるんだけど、
相関クエリーは考え方に慣れが必要だからわかりにくいかも

重複してる行を消すということは、それぞれ1行だけのこして全部消すってことだから、
DELETE FROM table1 WHERE id not in (SELECT min(id) FROM table1 group by name, title )
でいけると思う。重複とのこす基準は>906と同じな
not in 使うと遅いとか言う話があったりして、これを改良すると>906になる


913 :NAME IS NULL:2009/02/18(水) 21:09:09 ID:???
>>910
何のためにそれをしたいの?

Oracleの索引構成表とかDB2のクラスター化表とかなら
ある意味はじめから順序どおり格納されるとも言えるけど、
そういうことをしたいんでもないだろうしなあ・・・

914 :NAME IS NULL:2009/02/18(水) 21:10:33 ID:???
>>910
いったんテンポラリのテーブルに出力して、元を削除して、再度 INSERT

915 :906:2009/02/18(水) 22:14:42 ID:???
俺、やっちまったなーw
先だってから、「今の(NOT) INは遅くない」って書いてたのに、ついつい慣れから相関クエリを書いてしまう。

name,titleにインデックスがない場合、確実に>>906は遅い。
name,titleにインデックスを張っていても、>>912のサブクエリが一度だけしか実行されない
様になっているDBなら>>912の方が速い場合がある。

で、重複行を消したいという質問が偶にあるけど、本来重複行が出来ないようにすべきで、
せいぜい、設計や仕様変更に伴う時に一度使う程度なんだったら、どちらでもいいっちゃいいよな。

916 :NAME IS NULL:2009/02/19(木) 00:06:25 ID:???
うおお、COUNT(1)が理解されて無いなww

selectされたレコードすべてに数値の定数1を返す。すなわちどのカラムがヌルだろうが選択されたレコード件数になるんだよ。
カラム番号じゃないよ。

917 :NAME IS NULL:2009/02/19(木) 14:10:38 ID:???
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カラムの中にカンマ等でタグ付けしたらいいかなと思っていますが、
もっと効率が良い方法あったりしますか?


919 :NAME IS NULL:2009/02/23(月) 12:28:42 ID:???
別にテーブル追加で、
id tag
------
1  2
1  3
2  1
2  2
3  2

とかでいいじゃない。

920 :NAME IS NULL:2009/02/23(月) 12:31:19 ID:???
カンマで切った tag は、どうやって検索するつもりですか ?

映画名の id name のテーブルはそのままにしといて
id movie-id tag-id
1 1 2
2 1 3
3 2 1
4 2 2
5 3 2

などとする方が楽ではないかと思いますが…



921 :NAME IS NULL:2009/02/23(月) 12:31:50 ID:???
かぶった。すまぬ。

922 :NAME IS NULL:2009/02/23(月) 14:21:29 ID:???
>>918
それはテーブル設計の問題で、SQLの問題じゃないからな
まあ、普通にやるなら>>920のやり方だろうけど

923 :918:2009/02/23(月) 14:24:06 ID:m+mY0xtA
なるほど!そうですよね・・
ブログのコメントなんかはそうやって管理してるのに、
なんで思いつかなかったんだろ・・
これ、複数タグで検索する時は タグテーブルをJOIN して tag=1 and tag=2 and tag=3 ...
みたいに何個もand使う感じでいいんでしょうか?

924 :NAME IS NULL:2009/02/23(月) 21:08:20 ID:???
sybaseはこちらでいいのでしょうか。

CGIで、パラメータ取り込んでDB updateするプログラム書いてるのですが(PERL-DBI)
SQL文をストアド使わないで直書きでやろうとしてます
そのとき、transactionって、使えるのでしょうか。

begin tran
update 〜
if(@@rowcount = 0 or @@error !=0)
rollback tran
else
commit tran

↑のようなSQL文をソース内に書いて実行はできるのでしょうか。
今、SQLサーバに接続できないので、確認が出来なくて
よろしくお願いします。

925 :NAME IS NULL:2009/02/23(月) 21:24:19 ID:???
>>920
それって id って必要なの?

926 :NAME IS NULL:2009/02/23(月) 21:42:44 ID:???
複合PKは嫌い

927 :NAME IS NULL:2009/02/23(月) 21:42:49 ID:???
通し番号が必要かどうかわからなかったら、とりあえずつける。
アプリが出来てから判断してもいいんじゃね。

928 :NAME IS NULL:2009/02/23(月) 21:57:21 ID:???
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)のですが
どのように書けばいいのでしょうか?


930 :NAME IS NULL:2009/02/24(火) 22:30:15 ID:???
where rank = 'bbb' or rank = 'ccc'
でdistinctかければいいのでは?

931 :NAME IS NULL:2009/02/24(火) 22:30:46 ID:???
ごめんorじゃなくてandか

932 :NAME IS NULL:2009/02/24(火) 22:36:03 ID:???
>>929
一応
select name
from TableName
group by name
having count(case rank when 'bbb' then 1 end) > 0
and count(case rank when 'ccc' then 1 end) > 0
でできるけどカッコ良くないよな・・・

商演算の一般的な解は
http://oraclesqlpuzzle.hp.infoseek.co.jp/12-5.html
にあるけど次スレ用にFAQ書く?
にしてもどれを書けばいいやら・・・

933 :NAME IS NULL:2009/02/24(火) 23:47:48 ID:???
>>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'

もし検索したいランクの組がリレーションに入っているので
あれば外部結合を使う。

934 :NAME IS NULL:2009/02/25(水) 01:05:41 ID:???
なにこれ?かっこいい自演をしようと思ってこじれたのかな?

935 :NAME IS NULL:2009/02/25(水) 06:34:22 ID:???
>>933
最後の部分kwsk
少なくともOUTER JOINではないと思うけど

936 :NAME IS NULL:2009/02/25(水) 08:04:52 ID:???
>>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 ランクだけ)

みたいな感じで。

937 :NAME IS NULL:2009/02/25(水) 08:09:57 ID:???
つ GROUP BY NAME

付け忘れました・・・酔っぱらったまま書くととろくな事がないなぁ。

938 :NAME IS NULL:2009/02/25(水) 11:41:53 ID:K3R0lD3x
SQLServerでの自動インクリメントで、決まったフォーマット形式を埋め込むことはできますか?
例えば
 G0001
 G0002
 G0003
 ・
 ・

のようなデータを作りたいのですが

939 :NAME IS NULL:2009/02/25(水) 11:43:58 ID:???
よく考えたら自動インクリメントに文字列フォーマット入れるなんて無理ですね
すいませんでした

940 :NAME IS NULL:2009/02/25(水) 11:44:19 ID:???
朝の8時ですよ?

941 :NAME IS NULL:2009/02/25(水) 15:04:38 ID:???
>>938,939
SQLServerは弄ったことないけど、あるカラムの値をG0001,G0002と増やしたいのなら可能だろう。
そのカラムのデフォルト値を 'G' || to_char(nextval(sequence_name),'FM0000') にすれば桶。
ちなみに || は連結子な。SQLServerは違うかも。

普通で考えれば、取り出すときに'G'を連結する方がいいと思うけど。

942 :NAME IS NULL:2009/02/25(水) 15:51:43 ID:???
>>938
それは、一つのカラムの中に、固定部分と連番部分の二つの項目を入れてることになる
固定部分と連番部分で素直にカラムわけるべき
固定部分はカラム必要ないかも知れんし、合体した形式で扱いたいなら
カラム(または固定文字列)を連結したビューを作れ


943 :NAME IS NULL:2009/02/25(水) 21:33:33 ID:???
>>941
SQL-Server は、シーケンスじゃなくてフィールドの属性として
自動インクリメント指定する方法だから、その方法は取れない。

まあ、Excel じゃないんだからほかの人が言ってるように取り
出し時にフォーマッティングするのがいいと思う。

944 :NAME IS NULL:2009/02/25(水) 21:55:40 ID:???
DB: SQLServer 2005

id | names
---------------------
1 | 佐藤,小林
2 | 小林,鈴木
3 | 鈴木,田中,佐藤

上のテーブルを下のテーブルに変換したいのですが、どのようなSQLを書いたらよいでしょうか。

id | names
---------
1 | 佐藤
1 | 小林
2 | 小林
2 | 鈴木
3 | 鈴木
3 | 田中
3 | 佐藤


PostgreSQL だと regexp_split_to_table で一発でできそうなのですが、
調べた限りでは SQLServer にはなさそうです。


945 :NAME IS NULL:2009/02/25(水) 22:37:10 ID:???
つ SQLCLR


946 :NAME IS NULL:2009/02/26(木) 01:37:30 ID:???
「idが1」で、
なおかつ、
「valueが1より大きい」、
場合のみ、valueを1減じたくて
次のようなSQLを書いたのです。

UPDATE tb1
SET value = value - 1
WHERE id = '1' AND value > '1'

ところが、valueがー3とかの場合にも、
ガンガンvalueが減ってしまいます
(こちらの意図した通りに動くなら、
valueが1より小さいときは動作しない
はずなのに、、、)

どうしてでしょうか?

947 :NAME IS NULL:2009/02/26(木) 02:05:35 ID:???
>>946
は自己解決したのでもういいです。

下のほうに、もう一個SQL文書いてた。

948 :NAME IS NULL:2009/02/26(木) 02:06:31 ID:???
次の質問。

UPDATE tb1
SET value = value - 1
WHERE id = '1'
AND value > '1

このSQL文で、最初の1回は実行されて
valueが減るのですが、
2回目以降は減りません。

なぜでしょうか?
エラーも出ません。

949 :NAME IS NULL:2009/02/26(木) 02:07:16 ID:???
最後のクオーテーション抜けてました

UPDATE tb1
SET value = value - 1
WHERE id = '1'
AND value > '1'

誰か原因教えてください

950 :NAME IS NULL:2009/02/26(木) 02:11:45 ID:???
SELECT value FROM tb1
WHERE id = '1'
AND value > '1'

これで検索されてこないよ
なんで?

951 :NAME IS NULL:2009/02/26(木) 02:15:18 ID:???
自己解決した

SELECT value FROM tb1
WHERE id = '1'
AND value > 1

にしたらできた。

952 :NAME IS NULL:2009/02/26(木) 04:22:32 ID:???
>>946-951
まずおまえは数値と文字列について勉強しれ
つぎに、暗黙の変換についても勉強しとけ


953 :NAME IS NULL:2009/02/26(木) 07:15:18 ID:???
http://pc11.2ch.net/test/read.cgi/php/1234958956/461
http://pc11.2ch.net/test/read.cgi/php/1234958956/464
PHPスレでいつも現れる荒らしさんです。餌を与えないで下さい。

954 :NAME IS NULL:2009/02/26(木) 09:13:54 ID:???
いきなりUPDATEとか、
危険な奴っちゃな〜

955 :NAME IS NULL:2009/02/26(木) 10:47:49 ID:???
自己解決したのでもういいです。

956 :NAME IS NULL:2009/02/26(木) 11:34:53 ID:???
冗談抜きで頼むからもう来ないでください。

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の後にカンマ抜けてました

959 :NAME IS NULL:2009/02/27(金) 08:57:21 ID:???
>>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 ....

960 :NAME IS NULL:2009/02/27(金) 13:07:00 ID:???
>>957
>>1 >質問するときはDBMS名を必ず付記してください。

>>959
>SELECT リストには FROM句で参照しているものしか書けません。
本来は、って話なんだが、これは、標準的なSQLの話なのか?
俺の記憶では、定数とカラムの計算式はSELECTリストにかけたと思うんだ

つか、FROM句じゃなくてGROUP BYで参照してるカラム、じゃないのか?
その場合でも定数と式はかけたと思ったが





961 :NAME IS NULL:2009/02/27(金) 13:17:00 ID:???
記憶で書くなよ…

>>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で参照してない定数はセレクトリストにかけないのが本来の動作なのか?


963 :NAME IS NULL:2009/02/27(金) 17:08:40 ID:???
なんか揉めてますね。第三者ですが一応ちゃんとした本から引用
して書いておきます。

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

964 :NAME IS NULL:2009/02/27(金) 17:48:58 ID:???
引用元も明記しないとか駄目すぎ

965 :NAME IS NULL:2009/02/27(金) 18:27:40 ID:???
ごめん。ど忘れ。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句で参照しているものしか書けません。 が正解だろうと
自分で書いてて、かなり揚げ足取りくさいな

まあ揚げ足取りついでに、
>集約関数の引数となるスカラー式についても同様
引数となる列名についても、の間違いじゃないのか?
そもそも集約関数の引数はスカラー式に限らないと思うんだが







967 :NAME IS NULL:2009/02/27(金) 19:07:36 ID:???
もういいよ
不毛


968 :963:2009/02/27(金) 19:57:21 ID:???
>>966
>SELECT リストの列名には FROM句で参照しているものしか書けません。
>が正解だろうと

そうですよね。
自分も>>959の書き方は少しいい加減で良くないだと思います。あと、

>そもそも集約関数の引数はスカラー式に限らないと思うんだが

これなんですが、正確には集約関数の引数はスカラー式もしくは「*」
(ただしCOUNT限定)で、スカラー式は項もしくは項同士の足し算引き算で、
項は因子のかけ算割り算で、因子はスカラー一次子かスカラー一次子に
正負の符号がついたものでスカラー一次子は列名・定数・集約関数の参照
(ただし集約関数の引数となるスカラー式の場合は除く)・括弧でかこまれた
スカラー式・括弧でかこまれた行サブクエリーということでした。

長いので定義を端折って書きましたが、誤解を招いたようで申し訳ない。

969 :959:2009/02/27(金) 21:02:06 ID:???
おースマン、書き方が悪かった。
元質からの流れと俺の語彙の少なさで、あのような書き方になってしまった。

970 :NAME IS NULL:2009/02/28(土) 00:14:07 ID:???
おまいらDUAL表使って定数返し放題だろw


あれは何もDUALじゃなくて1レコードだけ格納された表つかえば
全くおなじ結果になんだよ

971 :NAME IS NULL:2009/02/28(土) 00:21:39 ID:???
特定の実装と、標準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なら用途ありそうだね

974 :NAME IS NULL:2009/02/28(土) 05:16:51 ID:???
そもそもSelectリストって表現がおかしい。

975 :NAME IS NULL:2009/02/28(土) 10:33:21 ID:???
Selectリストって表現使われてるのは見かけるな。英語のマニュアルとかで。
日本語だと選択リストって感じかな。

976 :NAME IS NULL:2009/02/28(土) 10:52:10 ID:???
BNFでも<select list>って書いてあるし、全く変だと思わないけど

ttp://savage.net.au/SQL/sql-99.bnf.html#query%20specification

<query specification> ::= SELECT [ <set quantifier> ] <select list> <table expression>

<select list> ::= <asterisk> | <select sublist> [ { <comma> <select sublist> }... ]

977 :NAME IS NULL:2009/02/28(土) 14:40:59 ID:???
PostgreSQLの日本語マニュアルでも選択リストだね。

978 :NAME IS NULL:2009/03/02(月) 08:52:03 ID:???
SQLiteのrandom関数、
1−5の値を出したいんだが、
どうしたらいいのかな?

979 :NAME IS NULL:2009/03/02(月) 10:20:26 ID:???
SELECT abs(random()) % 5 + 1;とか?

980 :NAME IS NULL:2009/03/03(火) 01:49:37 ID:???
>>979
サンキューでした。

981 :NAME IS NULL:2009/03/03(火) 01:50:57 ID:???
「ボタンを一回押したら、数値が3−5増える」
というプログラムを作ったんだが、上限を100で固定したい。

いまのままだと、「97」のときに、ボタンを押して、
「5」がランダム生成されると、

97+5=102
になってしまって、100をオーバーしてしまう。

これを、100以上にしないようにしたいのだが、
SQL文で、上限の固定とかできるの?

982 :NAME IS NULL:2009/03/03(火) 01:57:21 ID:???
DBがサポートする仕様によっては出来る事もあるけど、DBの
バージョンも「・・・というプログラム」をどういったSQLで実現した
のかも書いていないのでは恐らく誰もコメント出来ないと思う。

983 :NAME IS NULL:2009/03/03(火) 02:48:14 ID:???
ん、、、少なくとも、SQLの標準機能では
無理そうだというところまでわかりますた。

984 :NAME IS NULL:2009/03/03(火) 03:30:58 ID:???
ちょうど>>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;

986 :NAME IS NULL:2009/03/03(火) 21:13:56 ID:???
sage

987 :NAME IS NULL:2009/03/03(火) 22:51:32 ID:???
>>981
単純にやるなら select LEAST(n + floor(3 * Random()) + 3, 100) from ...
でいいと思うが。

LEAST() ないなら、case でがんばれ。

988 :NAME IS NULL:2009/03/04(水) 06:17:22 ID:???
>>984,985,987

ん、、、みんなありがとう
自分の知識が足りなくて
書いてあることが理解できないよ

989 :NAME IS NULL:2009/03/04(水) 17:55:11 ID:???
>>SQL文で、上限の固定とかできるの
テーブルの項目に制約をつけることによって上限の固定はできるだろう
もしくは、トリガでチェックするって方法もある


990 :NAME IS NULL:2009/03/05(木) 01:50:13 ID:???
自分がイメージしたのは、

MAX(100)

みたいな、シンプルな命令がもしあれば
使いたいな、ってことだったんです。

991 :NAME IS NULL:2009/03/05(木) 02:29:12 ID:???
>>990
いやだからさ、>>981だと情報が少なすぎて何をどうやりたいのか
さっぱりなんだわ。

>「ボタンを一回押したら、数値が3−5増える」 というプログラム

をどういうSQLで実現したのかSQL文の抜粋程度は書かないと、
それをどう変更すれば望みの「100で固定」を実現出来るか答え
ようがない。

あと「標準SQL」でもこの機能は実現出来るけど、残念ながら全て
のDBMSが「標準SQL」で定義されている機能を全部持っている
わけではない。DBMSによっては持っていない機能もある。
だからDBMSの名前とバージョンを書かないと答えようがない。

なのでまずは>>1のテンプレと>>4,5の質問を参考にして必要十分
な情報を書くこと。
あるいはエスパーをご所望ならそう明記を。

992 :NAME IS NULL:2009/03/05(木) 09:44:46 ID:???
SQLと言うよりもプログラム側でランダム値を生成すればいいだけのような気がする。

993 :NAME IS NULL:2009/03/05(木) 20:52:20 ID:???
sage

994 :NAME IS NULL:2009/03/05(木) 20:56:11 ID:???
次スレ

SQL質疑応答スレ 8問目
http://pc11.2ch.net/test/read.cgi/db/1236253554/

995 :NAME IS NULL:2009/03/05(木) 21:10:14 ID:???
エスパーすると、これはSQLと関係なくて、
>「ボタンを一回押したら、数値が3−5増える」
で得た値と 100 を比較して小さい方を返す、
という関数を作るなり、
組み込み関数を使うなりすればいいと思うよ。

996 :NAME IS NULL:2009/03/05(木) 21:49:24 ID:???
SQLfでやることじゃねーわなw

997 :NAME IS NULL:2009/03/05(木) 21:50:09 ID:???
997なら最高のオナニーができる

998 :NAME IS NULL:2009/03/06(金) 01:04:56 ID:???
もう終わりでいいな。

999 :NAME IS NULL:2009/03/06(金) 01:07:16 ID:???
うめ。

1000 :NAME IS NULL:2009/03/06(金) 01:08:50 ID:???
うめ。

1001 :1001:Over 1000 Thread
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。

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

read.cgi ver 05.02.02 2014/06/23 Mango Mangüé ★
FOX ★ DSO(Dynamic Shared Object)