SQL質疑応答スレ 9問目 at DB
[2ch|▼Menu]
1:NAME IS NULL
09/09/09 19:31:36
このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。

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

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

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

前スレ:
SQL質疑応答スレ 8問目
スレリンク(db板)

2:NAME IS NULL
09/09/09 19:32:51
SQL言語リファレンス一覧
Oracle Database
URLリンク(otndnld.oracle.co.jp)
Microsoft SQL Server
URLリンク(msdn.microsoft.com)
IBM DB2 Database
URLリンク(publib.boulder.ibm.com) (目次から参照情報→SQL)
PostgreSQL
URLリンク(www.postgresql.jp)
MySQL
URLリンク(dev.mysql.com)


参考リンク
URLリンク(sql.main.jp)
URLリンク(www.atmarkit.co.jp)
URLリンク(oraclesqlpuzzle.hp.infoseek.co.jp)
URLリンク(www.techscore.com)

3:NAME IS NULL
09/09/09 19:33:55
過去スレ
SQL質疑応答スレ 8問目
スレリンク(db板)
SQL質疑応答スレ 7問目
スレリンク(db板)
SQL質疑応答スレ 6問目
スレリンク(db板)
SQL質疑応答スレ 5問目
スレリンク(db板)
【帰ってきた】SQL質疑応答スレ 4問目
スレリンク(db板)
【帰ってきた】SQL質疑応答スレ 3問目
スレリンク(db板)
【帰ってきた】SQL質疑応答スレ 2問目
スレリンク(db板)
【帰ってきた】SQL質疑応答スレ
スレリンク(db板)
SQL質疑応答スレ Part 2
スレリンク(db板)
SQL質疑応答スレ
スレリンク(db板)

4:NAME IS NULL
09/09/09 19:35:02
よくある質問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
09/09/09 19:36:09
よくある質問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
09/09/09 19:37:35
よくある質問3

(問)
ID HOGE
01 A
01 B
01 C
02 A
03 B

HOGEをAもBもCも持っている、ID:01だけ取り出すにはどうすればよかですか

(答1)
SELECT id
FROM TableName
WHERE hoge in ('A','B','C')
GROUP BY id
HAVING count(DISTINCT hoge) = 3
;

(答2)
select *
from TableName T1
where not exists (select *
         from (values 'A', 'B', 'C') T2 (HOGE)
         where not exists (select *
                  from TableName T3
                  where T1.ID = T3.ID
                  and T2.HOGE = T3.HOGE
                  )
         )
;
※valuesの部分(Table Value Constructor)はDBMSによって文法がかなり違うので注意

7:1
09/09/09 19:40:02
なんか落ちてたんで立てた
後悔はしていない

8:NAME IS NULL
09/09/09 20:00:55
>>1


9:NAME IS NULL
09/09/10 06:37:53
おつ

10:NAME IS NULL
09/09/10 20:13:02
SQL の SELECT で取得する個数を指定することはできますか?
例えば、ソートした結果の100番目から150番目を個取得するなどです。

11:10
09/09/10 20:14:00
「個数を指定する」というよりも、「範囲を指定する」の方が言葉として適切でした _o_

12:NAME IS NULL
09/09/10 20:17:00
>>11
どっちもできるよ


13:10
09/09/10 20:24:15
>>12
■件数指定 LIMIT

・先頭から 3 件問い合わせるには、次のようにする。
access の top と同じことができる。
(TOP 10 取得、表示行制限、レコード数限定、件数指定、表示件数)
(1 レコード取得、1 件取得)

select * from testm
order by key1
limit 0, 3
;

みたいな感じでしょうか?

「access の top と同じことができる。」の意味が解らないのですが。。

14:NAME IS NULL
09/09/10 20:29:43
count(1)とcount(*)の違いを教えていただけないでしょうか?

15:NAME IS NULL
09/09/10 21:21:19 91yFw6iE
お願いします。
テーブル1(t1)には
[ID][受け渡し区分][客着日]フィールドがあります。
主キー 数値 日付型です

テーブル2(t2)には
[ID][データ内容][受け渡し日]フィールドがあります。
主キー テキスト 日付型です。

主キーで結合し、[データ内容][受け渡し日][客着日]の選択クエリを作ろうとしています。

[受け渡し日]の日付に[受け渡し区分]に入った数値を加算した日付を、
[客着日]に入るようなイメージなのですが、
どうもうまく作れません。

分かりにくいかもしれませんが、どうぞよろしくお願いします。。


16:NAME IS NULL
09/09/10 21:46:29
>>14
その違いは、使ってるデータベスのマニュアルに書いてあるはずだから、
マニュアル読んでくるといいよ

17:NAME IS NULL
09/09/10 21:52:43
>>15
よう分からんが、こうか?

select
t2.データ内容, t2.受け渡し日, t1.客着日
from テーブル1 t1
join テーブル2 t2 on t1.id = t2.id
where
t1.客着日 = t1.受け渡し区分 + t2.受け渡し日


あと、使ってるDBとバージョンは提示した方がいいぞ

18:NAME IS NULL
09/09/10 22:15:32 91yFw6iE
>>17
すいません。
access2000とかいう化石みたいなもの使ってます。
大まかにご提示いただいたようなテーブルを作成したのですが、

select t2.データ内容, t2.受け渡し日, t1.客着日
from t1,t2
join t2 on t1.id = t2.id
where t1.客着日 = t2.受け渡し区分 + t2.受け渡し日

where指定のあたりが間違ってるとのことなのです・・。

19:NAME IS NULL
09/09/10 22:16:37
>>16
わかりませんでした、ごめんなさい

20:NAME IS NULL
09/09/10 22:19:12
日付演算の方法がわからんというオチだったりしてなw

21:NAME IS NULL
09/09/10 22:54:35
>>19

Oracle
URLリンク(otndnld.oracle.co.jp)

MySQL
URLリンク(dev.mysql.com)

PostgreSQL
URLリンク(www.postgresql.jp)

firebird
URLリンク(firebird.skr.jp)

SQL Server
URLリンク(msdn.microsoft.com)

DB2
URLリンク(publib.boulder.ibm.com)

好きなの嫁
言ってることは、どのドキュメントも同じだから


22:NAME IS NULL
09/09/10 23:05:29
>>21
親切にありがとうございました
結論として、まったく変わらないということですね
勉強になりました

23:NAME IS NULL
09/09/10 23:24:41
だめだこりゃ・・・

24:NAME IS NULL
09/09/10 23:42:45
>>22の来世に幸あれ

25:NAME IS NULL
09/09/11 06:12:59
おまえら自信なさげに不親切な回答してるけど
count(1)とcount(*)の結果は同じだぜ?

26:NAME IS NULL
09/09/13 14:43:18 BgFEKAE5
Oracle10gでスキーマ内で更新されたレコードを抽出することはできますでしょうか?
判別としては各テーブルにUPDDATE項目があります。
DBA_TAB_COLUMNSあたりを使用して抽出できないでしょうか?

27:NAME IS NULL
09/09/13 16:06:40 olkIEqmS
お願いします。
access2003です。

あるテーブルに日付フィールドがあり、
そのフィールドの日付が土日であれば、
翌営業日(月)の日付を返してくれるクエリを作成したいと思っています。

どうぞよろしくお願いします。
とゆうか、sql単体では出来ないのでしょうか

28:NAME IS NULL
09/09/13 18:49:28
SELECT Switch(Weekday(日付)=1, Dateadd("d", 1, 日付), Weekday(日付)=7, Dateadd("d", 2, 日付)) AS 営業日
FROM あるテーブル AS T1
WHERE T1.日付 = (SELECT Max(T2.日付) FROM あるテーブル AS T2);

最新日が土日なら翌月曜日に
でも確認してないから全然自信ないわ…
vba使ったほうが絶対良いよ

29:NAME IS NULL
09/09/13 20:16:58
>>26
LogMinerを使うか、FlashBack Queryでもどうにかできるかも
まあトリガーをあらかじめ仕掛けておくのが常道だけど

30:NAME IS NULL
09/09/13 20:28:08 olkIEqmS
ありがとうございます。

UPDATE T1 SET [土日後]=[加算前]+2 WHERE WEEKDAY(加算前)=1;

これで、T1テーブルの、
加算前フィールドの日付が日曜の場合、
+土日後フィールドに2日を加算した値を入れるようには出来ました。

ここから、スウィッチを文に含めると構文エラーと怒られるんですが、
何かケアレスしてそうな所ございませんか・・・

vbaは読みづらい書きづらいで、sqlで済ませたいんです。。

31:NAME IS NULL
09/09/13 20:51:49 mrtjO9XU
>>29
既存のシステムの保守にあたり、テストを行いたいのですが、
機能を処理してメインとなるテーブルはわかるのですが、その他にもないか
判別したいのです。
トリガーとなるとすべてのテーブルに仕掛けておかないといけないですよね
それしか方法はないですか・・・

32:NAME IS NULL
09/09/13 21:01:45
>>31
じゃあやっぱLogMinerで掘るしかないんじゃね?

33:NAME IS NULL
09/09/13 21:04:26
>>30
無理して1SQLでやらなくても、土曜の場合+2するUPDATE文と
日曜の場合+1するUPDATE文2回実行すればいいんじゃないかね

余計なお世話かもしれないが
お前のとこの営業日は、祝祭日も年末年始も考慮しないのか

34:NAME IS NULL
09/09/13 21:45:34
>>30
UPDATE文だったのか…Accessだと確か更新クエリでサブクエリ使えなかったような
構文にも自信ないからこっちに行った方がいいかも

Access総合相談所 其の22
スレリンク(bsoft板)

35:NAME IS NULL
09/09/14 14:44:11
注意: 他のSQLデータベース管理システムでの作業に親しんだユーザは、count集約関数がテーブル全体に適用される場合の性能に失望するかも知れません。
SELECT count(*) FROM sometable;のような問い合わせはテーブル全体を逐次スキャンを用いてPostgreSQLにより実行されます。

うわ、今まさに失望した。

36:NAME IS NULL
09/09/14 14:46:41
ちなみにpostgresqlのdistinct速くなったらしいね、というのはもう古い情報だろうか

37:NAME IS NULL
09/09/15 19:01:50 nAU+9E+9
複数のテーブルから同条件で抽出したレコードのカウントを取得したいのですが、
スマートな方法はありませんか?
テーブルをUNION ALLで連結し、
countした結果をさらに合計する方法を考えたんですが、
他にいい方法はありますか?
例)
select count as (cnt) from ta union all select count as (cnt) from tb
これの結果をさらに合計↑

38:NAME IS NULL
09/09/15 19:15:01
UNION ALLしてからcountすればいいじゃない

39:37
09/09/15 22:23:28 nAU+9E+9
>>38
すみません、よかったら具体例書いていただけませんか?

40:NAME IS NULL
09/09/15 22:31:25
select count(*) from (select * from ta union all select * from tb) where 条件
ということだったんじゃないの?

41:37
09/09/15 23:53:26 nAU+9E+9
サブクエリーですね。
試してみます。ありがとうございました!

42:NAME IS NULL
09/09/17 14:32:22
今PHPを学習していて、SQLite使ってますが、やはりMySQLの方がいいのでしょうか?
ユーザ管理機能などの点でSQLiteは駄目だとか読みました
しかし何か、SQLiteの方がPHP本体では推奨しているとか、MySQLを禁止しているところもあるとか聞いたりしたものでどうなのかなぁ、と
それでも学習するという意味でも、実用的という意味でもMySQLの方がいいのかなぁと思い始めてきたのですが、どういう違いがあるのでしょうか?

43:NAME IS NULL
09/09/17 14:51:03
コンパクトで、別途サービスなりデーモンなりを設定しなくていいのがSQLiteの優位性かなあと

44:37
09/09/17 16:47:58 k//XEl+s
37ですが、残念なことにMySQLではサブクエリーが使用できませんでした。
37のはなんとか他の方法でいけたのですが、もう一つ質問があります。
複数のテーブルから同条件で抽出した結果セットの並び替えを行いたいのですが、
サブクエリーを使用せず並び替える方法はありませんか?

select * from ta union all select * from tb order by 条件
とするとテーブルtbのみ並び替えが行われると思うのですが、
taとtbテーブルを合わせた結果セットの並び替えを行いたいのです。
どうすればいいのでしょう?

45:NAME IS NULL
09/09/17 17:15:04
>select * from ta union all select * from tb order by 条件
>とするとテーブルtbのみ並び替えが行われると思うのですが、
思うだけではなく、実行してみれば?
実行環境がないのかな?

46:37
09/09/17 17:18:33 k//XEl+s
すみません、whereが各select個々に記述しないとだめだったので、
orderも個々じゃないと駄目なのかなと。
確かに推測ではなく確認を取るべきですね。
動作させて出直してきます。

47:NAME IS NULL
09/09/17 19:27:07
>>44
> MySQLではサブクエリーが使用できませんでした
半端な情報を流すのはやめた方がいいです。
同じような言い方をするならば、MySQLはサブクエリをサポートしています。

48:NAME IS NULL
09/09/17 20:00:27
× MySQLはサブクエリをサポートしています
○ MySQLはバージョン4.1からサブクエリをサポートしています

49:NAME IS NULL
09/09/17 20:25:33
両方にorder byかけたっけ?

と思いSQL Server2008で試したけど無理だった。
unionの外でかけるしかないね

50:NAME IS NULL
09/09/17 20:29:32
order byの評価順は一番最後
unionよりも後

51:NAME IS NULL
09/09/18 15:36:31
複数店舗の定休日を管理するテーブル設計はどうしたらいいでしょうか。

定休日は「毎週土日、第三木曜日、祝日、毎月15日のみ」などいろいろあります。

また、どの店が定休日かを抽出する必要があります。
( 来週の金曜日が定休日でなく、かつ予約がない店など )

一番先に思いついたのは例えば「毎週土曜日」というデータを持ち、そこから今月であれば 9/5, 9/12, 9/19, 9/26 という日付データを持とうかと考えましたが、来月や年末を見ることを考えると、データ量が膨大になります(^^;。

お知恵を貸してください!

52:NAME IS NULL
09/09/18 17:07:13
テーブル設計はすれ違いな気もするが

日付、店舗ごとに休みの日もてばいいんじゃね
1店舗最大366件/年だぜ。それで膨大ってことはないだろ

53:NAME IS NULL
09/09/18 17:27:07
で、バッチでレコード作ればいいよねきっと。

54:51
09/09/18 17:43:05
>>52-53
すれ違い気味にもかかわらず、ありがとうございます。
# どこがいいかと探してみて「何故データベース設計は軽視されるのか」があったのですが、
# ここもちょっと違う感じです。相応しい板に誘導していただければ移動します><

確かに言われてみれば、366×年数×店舗の件数なので、そんなに膨大ではないですね。

下記のように持ち方でいいのでしょうか。

ShopID|Holiday
------+-------
1|2009/1/1
1|2009/1/3
2|2009/9/18
2|2009/9/19
3|2000/1/1

この場合、2009/1/1 が休みじゃない ShopID の抽出 ( 2 と 3 ) の SQL はどのようになるでしょうか。


55:NAME IS NULL
09/09/18 17:58:54
select * from ショップマスタ where not exists (
select * from 休日マスタ where 休日マスタ.ShopID = ショップマスタ.ShopID and Holiday = '2009/1/1');

こんな感じで取れない?

56:51
09/09/18 18:07:45
>>55
ありがとうございます!ばっちりです。

先の話ですが、ショップマスタが 1000 件、
休日マスタが 10 万件の場合、
ShopID と Holyday へのインデックス適用以外に
パフォーマンスで考えることはなんでしょうか。
SQL もこのままでいけるものでしょうか。

57:NAME IS NULL
09/09/18 18:28:38
速度はある程度出ると思うけど、一応実測してみてね

58:NAME IS NULL
09/09/18 18:33:41
>>57
そうですね。ありがとうございます。

0.3s くらい出ているので問題なさそうです。


59:NAME IS NULL
09/09/18 19:00:35
オプティマイザとかによるんだが、(Holiday,ShopID)で主キーにするなら
select * from ショップマスタ where ShopID not in
(select ShopID from 休日マスタ where Holiday = '2009/1/1')
のが速い気がする


60:NAME IS NULL
09/09/18 20:29:55
>>59
ああ、やっぱりいろいろあるのですね。
ありがとうございます。
PostgreSQL 8.3 を考えています。
データ件数を 100 万件など増やして試してみます。

61:NAME IS NULL
09/09/19 15:47:13
inとexistsでの速度計測したらはってほしいな。

62:NAME IS NULL
09/09/20 08:41:22 OTmXdOaQ
このスレの存在をしらずに、別のスレで同じ書き込みをしました。
すみません。

質問は、、、

Mampを使って、php、mysqlとつないで簡単な掲示板を作ったのですが、
文字化けだらけです。utf-8に設定してるのですが、、
どこが問題なのでしょうか。
この問題を解決された方、アドバイスをよろしくお願いします。

63:NAME IS NULL
09/09/20 10:47:07
>どこが問題なのでしょうか。
macじゃね?

64:NAME IS NULL
09/09/20 23:22:18
>>61
ちなみにSQL Server2008だとどっちも全く同じ実行計画だった

65:NAME IS NULL
09/09/21 03:59:08
データ量は?

66:NAME IS NULL
09/09/23 00:06:44
CREATE TABLE test (username VARCHAR(50),password VARCHAR(32))
というので、usernameにPRIMARY KEYを設定したいのですが、
CREATE TABLE test (username VARCHAR(50),password VARCHAR(32) PRIMARY KEY(username))
のように設定すればいいのでしょうか?
主キーの設定の仕方が分からないもので教えていただけたらと思います

67:NAME IS NULL
09/09/23 01:22:34
>>66
使ってるDB書いてくれないと答えられないよ!!!!


68:66
09/09/23 13:43:47 1c6MbXvq
すみませんでした
リレーショナルデータベースで、抽象化レイヤはSQLiteです
PEAR::Authを利用前にユーザ情報テーブルを定義しようと思ったのです


69:NAME IS NULL
09/09/23 18:57:27
CREATE TABLE test (username VARCHAR(50),password VARCHAR(32),PRIMARY KEY(username))

でいけるんじゃない

70:NAME IS NULL
09/09/24 01:17:28
SQL Server 2005+Management Studioを使用しています。

1列目 2列目 3列目
 0    2
 3    2
 0    4
 1    5

1,2列目を使って計算し、3列目に結果を格納したビューを作りたいと考えています。
・1列目が0以外の時は1,2列目を使って計算して結果を3列目に格納し、
・1列目が0の時は計算しない(3列目はNULL値を格納)。
のような場合を考えているのですが、どのような方法があるでしょうか?
ご教授よろしくお願いします。

71:NAME IS NULL
09/09/24 01:27:33
CASE でできるだろ。

72:NAME IS NULL
09/09/24 02:00:53
select
a.1列目,
a.2列目,
case when a.1列目<>0 then null
else a.1列目+a..列目 end as 3列目
table a

73:70
09/09/24 02:21:50
>71,72
さっそくやってみたらできました!本当にありがとうございます!!

74:NAME IS NULL
09/09/24 13:15:44 Z8PuTcTT
MYSQL5使用してます。

テーブル
id code date
1 abc 2009-09-01 00:00:00
2 def ...
3 abc ...
4 abc ...

・欲しい結果
1日範囲で個別コードごとの総カウント数(COUNT)を取得し返したい。

・説明
アクセス集計していますが、コードがバラバラのため
個別にどれだけ該当コードでアクセスされたのか集計したいのです。
SQL文2回なら出来ますが、出来れば1度にやりたいのです。

よろしくお願いします。

75:51
09/09/24 13:49:14
>>61
計測してみました。
PostgreSQL 8.3.7 ( Xeon 1.86GHz x 2、 メモリ 2G ) の環境で
shop 10 万件、holiday 1000 万件で試しました。

shop.shop_id, holiday.shop_id, holiday.holiday に INDEX 張ってます。

5 回くらい explain analyze した結果。

■ IN
select count(shop.shop_id) from shop where shop_id not in (
select shop.shop_id from holiday,shop where shop.shop_id=holiday.shop_id and holiday.holiday = '2009/1/1');
→270ms

■ exsits
select count(s.*) from shop s where not exists (
select s.* from holiday where s.shop_id = holiday.shop_id and holiday.holiday = '2009/1/1');
→cost が IN の 900 倍あって計測中止


76:NAME IS NULL
09/09/24 15:10:15
select s.*

select *
でもおなじかの

77:51
09/09/24 15:27:56
>>76
同じでしたのう。
何か根本的に間違えているのかな。

78:NAME IS NULL
09/09/24 21:43:03
>>77
なんでnot inのサブクエリーを改悪する

つかそれでもnot inが900倍も速いのかw
existsのサブクエリのs.*を普通に*とかにしてもホントに遅いままか?
holiday.*とかholiday.shop_idとか1とかにしても遅いままか?


79:NAME IS NULL
09/09/24 22:24:43
最近のPostgreSQLでは (NOT) IN は速いよ。
でも900倍は変。
holiday.shop_id や holiday.holidayにインデックス貼ってみたらマシになるかも。

80:NAME IS NULL
09/09/24 22:28:18
holiday(shop_id,holiday)という複合INDEXがなければnot existsはそんなに
パフォーマンスが出ないというのは想像がつくが、この例ではholiday.shop_idの
holiday.holidayのどっちのINDEXが使われたのかねぇ。
それと、'2009/01/01'を休日に持つshopは10万件のうち何割だったんだろう?

普通に考えて、前者のnot inはshopとholidayのfull scanを1回ずつ、後者の
not existsはshopのfull scanを1回*nested loop joinだから、両方のテーブルが
メモリに収まらないくらい十分大きく、nested loop joinがindex scanできる
条件でならば通常後者のnot existsの方が速いはずだけど。

どっちにしても、せっかくexplainしても実行計画見ないんじゃ何もわからないね。

81:NAME IS NULL
09/09/24 22:41:13
>>80
テーブルの構成や行数にもよるが、サブクエリでユニークインデクスで検索する場合でも
EXISTS (インデックススキャンをメインテーブル行数回)
より
IN (両テーブルを各1回フルスキャン)
の方が速い場合もある。(つか、あった)

82:NAME IS NULL
09/09/24 23:01:00
どっちか一方が常に有利なんてことはないんだから、それは別に不思議じゃないと思うが。

83:NAME IS NULL
09/09/24 23:20:57
>>80
おれはPostgreSQL詳しくないので、特有な癖とかあったらわからんが
もともとnot inは、
>(Holiday,ShopID)で主キーにするなら
って前提だぜ。つまり(Holiday,ShopID)で複合インデックスがあれば
holidayテーブルのフルスキャン必要なくなるはずだ

84:81
09/09/24 23:31:01
すまん、ちょっと脊髄反射した...orz

85:NAME IS NULL
09/09/24 23:45:40
>>83
たしかに、holidayが十分選択性が高ければそこでフルスキャンはかかんないね。
その場合shop_idとの複合にする意味はあんまないと思うけど。

86:NAME IS NULL
09/09/25 00:31:30
>>85
カバードインデックスってPostgreSQLじゃ有効じゃないのか?


87:NAME IS NULL
09/09/25 04:37:07
not in と not existsだと調査するまでもなく後者の方が速いと思いこんでいた。
勉強が足りないなぁ俺。。。

88:51
09/09/25 10:31:33
みなさん、いろいろとアドバイスありがとうございます。

>>78
遅いっすね。

>>80
複合 INDEX を張ったら 1/30 になりました!
それでも IN に比べると 30 倍遅いです。

「'2009/01/01'を休日に持つshopは10万件」中 15% です。

explain 結果は分けてポストします。


89:NAME IS NULL
09/09/25 10:32:25
■ 複合 INDEX 前の exists

# explain select count(*) from shop s where not exists (
select 1 from holiday where s.shop_id = holiday.shop_id and holiday.holiday = '2009/1/1');
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Aggregate (cost=28065024.77..28065024.78 rows=1 width=0)
-> Seq Scan on shop s (cost=0.00..28064899.76 rows=50003 width=0)
Filter: (NOT (subplan))
SubPlan
-> Bitmap Heap Scan on holiday (cost=276.60..280.62 rows=1 width=0)
Recheck Cond: (($0 = shop_id) AND (holiday = '2009-01-01'::date))
-> BitmapAnd (cost=276.60..276.60 rows=1 width=0)
-> Bitmap Index Scan on index_holiday_shop_id (cost=0.00..5.88 rows=71 width=0)
Index Cond: ($0 = shop_id)
-> Bitmap Index Scan on index_holiday_holiday (cost=0.00..270.47 rows=14550 width=0)
Index Cond: (holiday = '2009-01-01'::date)


90:NAME IS NULL
09/09/25 10:33:08
■ 複数 INDEX 後の exists

( vacuum full analyze してます )

# explain select count(*) from shop s where not exists (
select 1 from holiday where s.shop_id = holiday.shop_id and holiday.holiday = '2009/1/1');
QUERY PLAN
-----------------------------------------------------------------------------------------------------------
Aggregate (cost=938409.27..938409.28 rows=1 width=0)
-> Seq Scan on shop s (cost=0.00..938284.26 rows=50003 width=0)
Filter: (NOT (subplan))
SubPlan
-> Index Scan using index_holiday_shop_id_holiday on holiday (cost=0.00..9.37 rows=1 width=0)
Index Cond: (($0 = shop_id) AND (holiday = '2009-01-01'::date))

91:NAME IS NULL
09/09/25 10:34:18
■ in

# explain select count(shop.shop_id) from shop where shop_id not in (
select shop.shop_id from holiday,shop where shop.shop_id=holiday.shop_id and holiday.holiday = '2009/1/1');
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Aggregate (cost=36525.88..36525.89 rows=1 width=4)
-> Seq Scan on shop (cost=34610.79..36400.87 rows=50003 width=4)
Filter: (NOT (hashed subplan))
SubPlan
-> Hash Join (cost=3459.70..34574.27 rows=14609 width=4)
Hash Cond: (holiday.shop_id = public.shop.shop_id)
-> Bitmap Heap Scan on holiday (cost=278.57..30593.96 rows=14609 width=4)
Recheck Cond: (holiday = '2009-01-01'::date)
-> Bitmap Index Scan on index_holiday_holiday (cost=0.00..274.91 rows=14609 width=0)
Index Cond: (holiday = '2009-01-01'::date)
-> Hash (cost=1540.06..1540.06 rows=100006 width=4)
-> Seq Scan on shop (cost=0.00..1540.06 rows=100006 width=4)


92:51
09/09/25 10:38:00
5 回くらい実行した explain analyze 結果。
in → 268ms
exists → 780ms

INDEX は下記。
・shop(shop_id)
・holiday(holiday)
・holiday(shop_id)
・holiday(shop_id, holiday)

こんな感じです。複合 INDEX をすっかり忘れていました。
やはり in がずっと成績がいいですね。


93:NAME IS NULL
09/09/25 10:55:28
>>92
だから、なんでnot inのサブクエリにshopテーブルが必要なんだ?
わざわざ改悪して速度調査ってなんなの?馬鹿なの?本気で馬鹿なの?
なんでおそらく最速になるであろう方法をためさないの?

ちゃんとnot inのサブクエリ直してholiday(holiday,shop_id) に
インデックはった上で実行した結果がみたいぞ

94:62
09/09/26 07:00:08 JyUvDari
>>62
62ですが、解決しました。phpmyadminで確認したら、sjisで設定してありました。
utf-8に設定しなおして、文字化け、なくなりました。

初めての掲示板、ちっぽけな事ですが、私にとっては、ビッグニュースです。
mysqlとphp、これから猛勉強して、はまります。

95:NAME IS NULL
09/09/28 21:05:35
MySQL 5.1

週間日付テーブルがあります
week_tbl
w_sdate 週初日付
w_edate 週末日付

で、ある日付を元にそれが属している週のデータを知りたい。

例えばその日付が '2009-09-28'だとすると、

select w_sdate,w_edate from week_tbl
where w_sdate < '2009-09-28' and
'2009-09-28' < w_edate;

で良いのですが、この日付の部分を他のsqlで持って来よう
とする場合、どのように書けばいいのでしょうか?





96:NAME IS NULL
09/09/28 21:57:27
>>95
こういうこと?
select w_sdate, w_edate
from week_tbl, (select ほげほげ from ふがふが)
where w_sdate < ほげほげ
and ほげほげ < w_edate;

しかし週の初めと終わりを取りたいだけなら
select ほげほげ - interval dayofweek(ほげほげ) - 1 day,
    ほげほげ + interval 7 - dayofweek(ほげほげ) day
from (select ほげほげ from ふがふが)
みたいな感じでいいような。

97:95
09/09/28 22:26:06
>>96
すんません、教えてください(アセ
日付は
select max(in_date) from data_dailytbl
where code = 9999;
で出すmax(in_date)を元にしたいんですが、そのsqlにはどうあてはめれば
よろしいのでしょうか?


98:NAME IS NULL
09/09/29 00:11:39
これじゃいかんか?

select a.w_sdate,a.w_edate from week_tbl a,
(
select max(in_date) as maxdate from data_dailytbl
where code = 9999;
) as b
where a.w_sdate < b.maxdate and
b.maxdate < a.w_edate;


99:NAME IS NULL
09/09/29 06:47:26
>>98
9999;の";"を取り除いて動作しました。
ありがとうございました m(_ _)m

100:NAME IS NULL
09/10/01 08:33:30
失礼します
独習SQLのP67に書いてあるのですが、「WK_仕入先」テーブルに「仕入先テーブルの行を挿入する(テーブルのデータを別のテーブルにコピーする)」とあるのですが、
@CREATE TABLE WK_仕入先 (仕入先コード NUMBER(5), 仕入先名 CHAR(20) )

ACREATE TABLE WK_仕入れ先 AS SELECT * FROM 仕入先 WHERE 1 = 2
が同じとあります
それで分からない事があるのですがAの最後の部分、【WHERE 1 = 2】の部分の 1 = 2とは何を意味しているのでしょうか?
仕入価格 = 12000とかならば分かるのですが、1 = 2 というのは抽象的過ぎて何をやっているのかが分かりません
すみませんがご回答いただければと思います

101:NAME IS NULL
09/10/01 09:45:29
抽象的な訳じゃなくて、面食らっただけじゃないのかな
1と2は同じではないので、抽出結果は常に0件になる

ただ、WK_仕入れ先を作るために必要なカラム情報は取れる

102:NAME IS NULL
09/10/01 16:07:29
>>101
はい、面食らいました
未だに意味は分かっていないのですが、コレは特に意味の無い表記なのでしょうか?
ただ@の仕入先コードや仕入先名のようなカラム情報を得たいが為だけに記入されているのでしょうか?
この1や2が何を意味するのかも見当もつきません・・・

103:NAME IS NULL
09/10/01 16:46:36
1は数字の1、2は数字の2 そのままの意味
1と2を比べれば等しくないのでその条件は不成立となる
かならず不成立となる条件として書いてあるだけ


104:NAME IS NULL
09/10/01 17:21:45
>>103
説明有難うございました

105:NAME IS NULL
09/10/02 14:44:20 aRTkE45u
OracleとAccess(JetやSQL Server)はどちらがいいのでしょうか?
自分、まだ全然良く分かっていない初心者なのですが、最初からずっと使うであろう方を学んで使い続けたいと思っているのですが
本屋でパッと見たところSQLServerの本が多かったように思えますが、Oracleの方が有名な気がします
どのような違いがあって、どちらがいいのか教えていただけたらと思います

106:NAME IS NULL
09/10/02 15:00:56
>>105
どちらも体験版というか、ExpressEditionはある。ただ、SQLServerの方が判り易い(と俺は思う)
どちらを選ぶにしろ、解説本を読んで自分のPCで試してみたら?

OracleはOS毎にあるけど、SQLServerは当然のことながらWindows用しかない。
けど、今のレベルではそんなの関係ないだろ?

どちらで勉強しても基本的な所をしっかり押さえれば、大丈夫だと思うけどね。


107:NAME IS NULL
09/10/02 21:33:49
ほげ台帳
--------
ほげ名 テキスト
担当1コード 数値
担当2コード 数値
担当3コード 数値

担当者テーブル
----------
コード オートナンバー
氏名 テキスト

これを
----------
ほげ名
担当1氏名(ほげ台帳.担当1コード=担当者テーブル.コードになる担当者テーブル.氏名)
担当2氏名(ほげ台帳.担当2コード=担当者テーブル.コードになる担当者テーブル.氏名)
担当3氏名(ほげ台帳.担当3コード=担当者テーブル.コードになる担当者テーブル.氏名)

という形にするにはどうすれば良いでしょうか?
環境はAccessです。

108:NAME IS NULL
09/10/02 22:20:56
>>107
select T1.ほげ名,
    T2.氏名 as 担当1氏名,
    T3.氏名 as 担当2氏名,
    T4.氏名 as 担当3氏名
from ほげ台帳 T1
   inner join
   担当者テーブル T2
   on T1.担当1コード = T2.コード
   inner join
   担当者テーブル T3
   on T1.担当2コード = T3.コード
   inner join
   担当者テーブル T4
   on T1.担当3コード = T4.コード

Accessでどう書くかは知らない

109:NAME IS NULL
09/10/02 22:31:54 RteXPf/F
>>105
インストール後、使えるようになるまではSQL Server の方が少し楽な気がする

OracleXEは分かってる人が使うものって感じかなぁ>個人的な意見
Webのマニュアル(英語版)位しかないよ>出た時ね
今本はあった気がするけど、内容は見たことがないので
#保守契約ないと、パッチ手に入れられないから、業務には使いづらいし
#SQLServerは、一応SPはでるからね

最初は「現場で使えるSQL 第2版」が個人的にお勧め(両方対応してるし)
#10g、2005対応だけどね

Accessは悪くはないけど、最初に触るものとしては、薦めたくないな・・
最初にSQLをちゃんと使うことを覚えて欲しいと思うから

110:NAME IS NULL
09/10/02 22:49:08
.NET やるなら SQL Server で。

111:NAME IS NULL
09/10/03 01:12:59
SQL Serverはあまり使ったこと無いけど、ホスト言語も含めた開発環境で変な癖がつかないか?
MSにどっぷりはまるのなら別にいいけど、ここに書かれる質問で、SQL側とホスト言語側の
切り分けが出来ていない物がたまに見受けられる。
ま、問題の切り分けが出来ない人はMS絡みに限ったことじゃないし、SQL Serverも含め
MSに対して他意はない。

112:NAME IS NULL
09/10/03 01:46:14
.NETとMSSQLが相性いいのは間違いないだろ。
ORMapperにLINQtoSQL使ってみなさいよ。

113:NAME IS NULL
09/10/03 03:07:05
切り分けができてないだけなのか、がんばればSQLで解決できるのかもしれないと思っているのか
その判断が俺にはできないわ。

114:NAME IS NULL
09/10/03 07:49:05 jYp+tLjS
>>111
>ホスト言語も含めた開発環境で変な癖がつかないか?
あまり無いと思うよ>普段はSQL鯖使い
Linuxから、アクセスするときはFreeTDS使うけど、後はあまり無いんじゃね?
Oracleと比較しても、そう変わらん気がする
#pl/sqlと比べてストアドがかなり弱い気がするけど
パフォチュー関係の情報があまりでてきてないくらいかな



115:111
09/10/03 09:52:16
相性がいいから癖がついちゃうとか。
SQLの中に割り当てるホスト言語の変数を埋め込んだままとか、
ホスト言語の一文そのままここに晒されても、とかって思うときがあった。
俺の偏見かな。

一応俺も.NET(C#)使うけど、LINQはまだだし、.NET+DBって機会がろくにないな。
やりたいんだけど、誰か仕事クレw

116:NAME IS NULL
09/10/03 18:04:22
>>108
Accessではこんな感じで出来ました、ありがとうございます
見かけのフィールド名(担当1〜3氏名)については、プロパティで設定したためSQLにはありません

select ほげ台帳.ほげ名, T1.氏名, T2.氏名, T3.氏名
from ((ほげ台帳
inner join 担当者テーブル as T1 on ほげ台帳.担当1コード = T1.コード)
inner join 担当者テーブル as T2 on ほげ台帳.担当2コード = T2.コード)
inner join 担当者テーブル as T3 on ほげ台帳.担当3コード = T3.コード;

117:NAME IS NULL
09/10/03 20:47:59
116の追記ですが、最終的にはLEFT JOINになりました。
第二、第三担当がNULLの場合に対応するためです。

118:NAME IS NULL
09/10/03 21:41:20
            ___
           ,r'     `ヽ、
          ,i"        ゙;
          !.(●)   (●),!
          ゝ_      _,r''
         /  ;;;;;;  ・・ ;;;;) <それは報告しなくてもいいです。
         /          (_
        |    f\ トェェェイノ     ̄`丶.
        |    |  ヽ__ノー─-- 、_  )
.        |  |            /  /
         | |          ,'  /
        /  ノ           |   ,'
      /   /             |  /
     _ノ /              ,ノ 〈
    (  〈              ヽ.__ \
     ヽ._>              \__)

119:NAME IS NULL
09/10/04 01:55:14
mysql 5.1.37

(問)
[groupテーブル]
group_id   | group_name
---------+-----------
g1      | グループ1
g2      | グループ2
g3      | グループ3

[belongテーブル]
group_id  | user_id   | status
---------+---------+------
g1      | u1     | 1
g2      | u2     | 0
g2      | u3     | 1
g2      | u4     | 1

このようなテーブルから、下記のように
group_name | user_count
-----------+-----------
グループ1  | 1
グループ2  | 2
グループ3  | 0
各グループ毎の「belong.status = 1」の所属ユーザ数を取得したいです。

以下のようなsql文を考えてみましたが、
SELECT group.group_name as group_name, count(belong.user_id) as user_count
FROM group left join belong on group.group_id = belong.group_id
WHERE belong.status = '1'
GROUP BY belong.group_id

group_name | user_count
----------+-----------
グループ1 | 1
グループ2 | 2

と、グループ3に対してデータを取得することができませんでした...orz...
※外部結合している為、「belong.status = '1'」の部分で…
なにか良い方法はないでしょうか?

120:NAME IS NULL
09/10/04 01:57:26
グループ化した結果を、group テーブルに LEFT JOIN。

121:119
09/10/04 02:05:58
>> 120
レスありがとうございます。
アドバイスして頂いた内容ですが、「サブクエリを使って…」と
解釈しましたが、問題ないでしょうか?
できれば、サブクエリを使わない方法で取得したいのです。

122:119
09/10/04 02:39:28
>>120
アドバイスして頂いたことを元に、
SELECT
 group.group_id,
 group.group_name,
 IFNULL(count_table.user_count, 0) as user_count
FROM
 group left join
  (SELECT group_id, count(*) as user_count FROM belong WHERE status='1' GROUP BY belong.group_id) as count_table
 on group.group_id = count_table.group_id
と、sqlを発行することで、取得することができました。

やはり、サブクエリをつかってしか取得することはできないのでしょうか?
『サブクエリを使用すると、レスポンスが悪くなる』
と、聞いたことがあり、なるべくなら、使用したくありません。
※今回の場合、上記sqlを発行すると、都合、2回、sqlが発行されることになると思います。

123:NAME IS NULL
09/10/04 03:57:37
SELECT group.group_name as group_name, count(belong.user_id) as user_count
FROM group left join belong on group.group_id = belong.group_id
GROUP BY belong.group_id, belong.status
HAVING belong.status = '1'

124:NAME IS NULL
09/10/04 04:14:30
サブクエリなしのSQL(笑)

125:NAME IS NULL
09/10/04 05:14:07
SELECT group.group_name as group_name, sum(case when belong.status is null then 0 else 1 end) as user_count
FROM group left join belong on group.group_id = belong.group_id
GROUP BY belong.group_id, belong.status
HAVING belong.status = '1' or belong.status is null

グループ3を0人と出すならこうかな。

126:NAME IS NULL
09/10/04 07:02:54
>>123,125
アドバイスして頂き、ありがとうございます。
アドバイスして頂いた中にあった「case句」を使うことで取得することができました。

SELECT
 group.group_id as group_id,
 group.group_name as group_name,
 CASE WHEN belong.status IS NULL THEN 0 ELSE COUNT(belong.user_id) END user_count
FROM
 group left join belong on group.group_id = belong.group_id
WHERE
 belong.status = '1' OR belong.status IS NULL
GROUP BY
 group.group_id

>>123,125
少し気になったのですが、アドバイスして頂いたsql文で
>GROUP BY belong.group_id, belong.status
と、「belong.group_id」にて、GROUP BYされていますが、これは、「group.group_id」の
間違いではないでしょうか?

127:119
09/10/04 08:21:47
>>126のsqlでもダメでした。
【ダメな理由】
belongテーブルに「belong.status」が'0'のレコードのみ存在する場合、
対応するgroupテーブル中のレコードが表示されない。

[groupテーブル]
group_id   | group_name
---------+-----------
g1      | グループ1
g2      | グループ2
g3      | グループ3

[belongテーブル]
group_id  | user_id   | status
---------+---------+------
g1      | u1     | 0
g2      | u2     | 0
g2      | u3     | 1
g2      | u4     | 1

[取得したい結果]
group_name | user_count
----------+-----------
グループ1 | 0
グループ2 | 2

[取得される結果]
group_name | user_count
----------+-----------
グループ2 | 2

もう少し、考えて見ます。m(_ _)m

128:NAME IS NULL
09/10/04 11:03:48
テーブルAにdatetime型のカラムがあり、select結果として

date_split_by_year
--------------┤
y/m/d h:m:s 1  |
y/m/d h:m:s 2  |
y/m/d h:m:s 3  |
y/m/d h:m:s 4  |
y/m/d h:m:s 5  |
y/m/d h:m:s 6  |
y/m/d h:m:s 7  |
   :       |
   :       |
y/m/d h:m:s N  |

y/m/d h:m:s 1 = テーブルAの最小年月日(Minで取得?)
y/m/d h:m:s 2〜N-1 = y/m/d h:m:s 1 に 1年ずつ加算していった年月日
y/m/d h:m:s N = 現在日時

という風に取得結果を取りたいのですが、どうすれば良いでしょうか?
おそらく問題は、y/m/d h:m:s 1とy/m/d h:m:s Nの値が常に変動するので
Nの数が決まっていないということです。
先生方よろしくお願いしますm(_ _)m

129:NAME IS NULL
09/10/04 11:05:02
DBはSQL Server 2005 SP2 です

130:NAME IS NULL
09/10/04 11:14:57
もう少し具体的に。row_number() 使えばいいだけの話にも見える。

131:NAME IS NULL
09/10/04 11:21:25
テーブルに有る訳でもないレコードを取ってくるとか
自分ならわざわざSQLでやらないなぁ

132:NAME IS NULL
09/10/04 11:40:17
ありがとうございます。
具体的にご説明しますと、

@[テーブルA]
code_id      | updt_time
------------+--------------------
code1      | 2003/01/01 00:00:00
code2      | 2004/07/01 12:30:00
code3      | 2005/07/01 22:00:00

現在日時 2009/10/04 11:20 にクエリ実行
[結果]
date_split_by_year
--------------------┤
2003/01/01 00:00:00  |
2004/01/01 00:00:00  |
2005/01/01 00:00:00  |
2006/01/01 00:00:00  |
2007/01/01 00:00:00  |
2008/01/01 00:00:00  |
2009/01/01 00:00:00  |
2009/10/04 11:20:00  |
---------------------

A6年後テーブルAに削除がかかっていたとして
[テーブルA]
code_id      | updt_time
------------+--------------------
code2      | 2004/07/01 12:30:00
code3      | 2005/07/01 22:00:00

6年後 現在日時 2015/10/04 11:20 に再度クエリ実行
[結果]
date_split_by_year
--------------------┤
2004/07/01 12:30:00  |
2005/07/01 12:30:00  |
2006/07/01 12:30:00  |
2007/07/01 12:30:00  |
2008/07/01 12:30:00  |
2009/07/01 12:30:00  |
2010/07/01 12:30:00  |
2011/07/01 12:30:00  |
2012/07/01 12:30:00  |
2013/07/01 12:30:00  |
2014/07/01 12:30:00  |
2015/07/01 12:30:00  |
2015/10/04 11:20:00  |
---------------------

といった取得結果にしたいです。

>>131
素直にテーブルAから最小日時をとって、コードで(開発言語はVB6.0です)
1年ずつ足して配列に格納とするほうが自然でしょうか。
意図としてはクエリ一発でできればやってしまおうー!と思ったしだいです。
ですが不自然なコードは今後のメンテナンスのためにも書くことは避けたいので、
そのやりかたは変だとあれば、この案はあきらめたいと思います。

133:NAME IS NULL
09/10/04 11:42:56
俺ならストアドにして終わり、だな。

134:NAME IS NULL
09/10/04 16:10:50
ストアドかアプリかな

135:NAME IS NULL
09/10/04 18:29:15
DBに存在しない値をSQLで生成するという考え方がおかしい
どうしてもクエリ1発でやりたかったらストアド書け


136:NAME IS NULL
09/10/04 23:05:08
SELECT A.風, A.林, B.火, B.山
FROM 南斗 A, 北斗 B
WHERE A.風 = B.風
AND A.風 IN ( SELECT C.風 FROM 北斗 C WHERE 山 >= 10000 )

すみません、このテーブル結合が分かりません
何故、「北斗(テーブル) B」があるのに、INの後に「北斗(テーブル) C」という記述があるのでしょうか?
同じ北斗テーブルなのにBというのとCと言う風に分けられていて、このテーブルBとテーブルCの違いは何なのでしょうか?



137:NAME IS NULL
09/10/04 23:14:14
書いた奴に聞けよ。

138:136
09/10/04 23:36:01
やはり書いた人間の意図によって分けられているだけなのですか・・・

では、すみませんがこの点を教えて下さい
上記のように北斗テーブルをBに設定しているのに、また別にCに設定すると言うことは出来るのでしょうか?


139:NAME IS NULL
09/10/04 23:37:03
できるよ。

140:NAME IS NULL
09/10/04 23:45:55
使い道はもちろんあるんだよ。
社員が給与振込口座を複数持つことが出来て、
銀行マスタをいくつも結合する場合、とか。


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

4761日前に更新/307 KB
担当:undef