【帰ってきた】SQL質疑応答スレ 4問目

このエントリーをはてなブックマークに追加
1NAME IS NULL
2NAME IS NULL:2007/04/14(土) 21:28:32 ID:???
で、全スレ>989宛。
995辺りので989〜992の機能は満たしとらんか?
もしくは、意図が掴みかねる993のカキコ内容が要求仕様上重要なん?
3989:2007/04/14(土) 22:05:01 ID:vEBJlPWj
>>2
ああ、そうですね、それは無視してください。

4989:2007/04/15(日) 10:59:08 ID:???
>>995
とりあえず、これで試してみます。
ありがとうございました。
5NAME IS NULL:2007/04/15(日) 13:04:44 ID:mKPpVVQg
質問一件お願いします。

以下のような単純なテーブルがあり、
valueの大きい上位3件のレコードを取得したいです。

【テーブルhoge】
name | value
a | 10
b | 30
c | 40
d | 5
e | 2
(以下大量のレコード)

【得たい結果】
c | 40
b | 30
a | 10

現在limitを用いて
select * from hoge order by value desc limit 0, 3;
としているのですが、速度が悲惨に遅いです。

何かいい方法はないでしょうか?
6NAME IS NULL:2007/04/15(日) 19:39:54 ID:8Gbsm4yF
mysqlについて質問です。
トランザクション可能なテーブルを利用した場合
通常のテーブルパフォーマンスとの差はどれくらいになるのでしょうか?
7NAME IS NULL:2007/04/15(日) 20:10:18 ID:afmYW8Mb
MySQL5.0での質問です。

testテーブルに、datetimeとtest_txtというフィールドがあります。
PHPにて、「INSERT test SET datetime='2005/10/10'」を実行すると、
MySQLエラーで「Field 'test_txt' doesn't have a default value」
と返ってきます。
「test_txt」は何も入れないで追加したいのですが、
何か設定の変更などが必要なのでしょうか?
それともいちいち「text=''」のように入れないといけないのでしょうか?
87:2007/04/15(日) 20:14:46 ID:afmYW8Mb
my.iniの
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
をコメントアウトすることで解決しました。
ですが、これは何を意味しているのでしょうか?
9NAME IS NULL:2007/04/15(日) 21:10:59 ID:???
>>7
エラーの内容をきちんと書いて質問するのはよい傾向。

あとはそのエラーをまず、よく読んで見ること。

> Field 'test_txt' doesn't have a default value
⇒ 分野'テスト_txt'には、デフォルト値がありません。

これでもわからないなら、まずデータベースについてもう少し
勉強することを薦める。
10NAME IS NULL:2007/04/15(日) 21:46:28 ID:???
MySQLって専用スレないんだな
11NAME IS NULL:2007/04/15(日) 23:06:14 ID:???
12NAME IS NULL:2007/04/16(月) 16:20:00 ID:???
col1 col2      col3
 1  2007/04/16 9
 1  2007/04/15 8
 1  2007/04/14 7
 2  2007/04/14 6
 2  2007/04/16 5
 2  2007/04/15 4
 3  2007/04/15 3
 3  2007/01/14 2
 3  2007/04/16 1

主キー(col1,col2)

上のようなテーブルから、col1毎にcol2が一番大きいcol3を得たいのですがSQL書けずに困っています
よろしくお願いします。
13412:2007/04/16(月) 16:20:57 ID:???
書き忘れですが、MySQL4,0xなので副問い合わせが出来ません・・・
14NAME IS NULL:2007/04/16(月) 17:10:32 ID:???
あげさせてもらいます
15NAME IS NULL:2007/04/16(月) 20:21:59 ID:???
SELECT COL3
FROM TABLE
LIMIT 0,1
GROUP BY COL1, COL3
ORDER BY COL2 DESC
16NAME IS NULL:2007/04/16(月) 22:57:56 ID:???
質問です。次のような表が二つあります。

表1
コード    コード名   種類名
 1      果物      区分コード
2       野菜      区分コード
10       あり      割引コード
20       なし      割引コード

 
表2
名前      区分コード  割引コード
りんご      1       10
トマト        2        20
きゅうり       2       10
ぶどう       1       20


これを

名前     区分コード  種別   割引 割引有無
りんご     1       果物    10    あり
トマト      2       野菜     20    なし
きゅうり       2     野菜    10    あり
ぶどう      1       果物   20    なし

のような表にしたいのです。
UNIONを用いて式を書きたいのですがうまくいきません。
何か良い方法がないでしょうか?


17NAME IS NULL:2007/04/16(月) 23:04:04 ID:???
訂正します

名前     区分コード  種別   割引コード 割引有無
りんご     1       果物      10    あり
トマト      2         野菜     20    なし
きゅうり      2        野菜    10    あり
ぶどう      1         果物   20    なし

18NAME IS NULL:2007/04/16(月) 23:34:22 ID:???
>>16
表1を二つに分ける。
既にその糞設計が所与のものならViewを使って別の表に見せかける。
19NAME IS NULL:2007/04/17(火) 00:18:52 ID:???
>>16

select 名前,表2.区分コード,区分.コード名 as 種別,表2.割引コード,割引.コード名 as 割引有無
from 表2,
(select コード,コード名
from 表1
where 種類名='区分コード') as 区分,
(select コード,コード名
from 表1
where 種類名='割引コード') as 割引
where 表2.区分コード=区分.区分コード
and 表2.割引コード=割引.割引コード
2016:2007/04/17(火) 21:52:34 ID:???
>>19

ありがとうございました!
おかげで助かりました。
21NAME IS NULL:2007/04/18(水) 15:33:04 ID:doDz5ry0
日付、キー、の二つのフィールドがあるテーブルがあります。
キーごとに、過去の日付のレコード件数を取得したいのですが
どのようなSQLを書けばいいでしょうか。

日付      キー
2007/01/01   1
2007/01/01   2
2007/01/02   1
2007/01/03   1



日付      キー    カウント
2007/01/01   1     0
2007/01/01   2     0
2007/01/02   1     1
2007/01/03   1     2
22NAME IS NULL:2007/04/18(水) 16:10:51 ID:???
そのカウントはどこから出てきたんだ。
23NAME IS NULL:2007/04/18(水) 17:50:43 ID:doDz5ry0
>>22
>キーごとに、過去の日付のレコード件数を取得したいのですが
これです。
4行目のカウント「2」は、キーが1で、
日付が2007/01/03未満のデータの件数(1行目と2行目)を数えています。
24NAME IS NULL:2007/04/18(水) 18:15:36 ID:???
SQL Server 2005で質問です。

以下のような「TableA」「TableB」があって
[TableA]
col1 col2 col3
------------------------
01  AAAA 1
02  AAAA 1
03  BBBB 2
04  CCCC 3
05  DDDD 4

[TableB]
col1 col2
-------------
AAAA 1
BBBB 2
CCCC 3
DDDD 4

TableAにだけ存在する行を取得するとき
以下のSQLで取得できますが

select col2 from TableA
except
select col1 from TableB

[結果]
col1 col2
-------------
AAAA 1

この内容からではTableAのcol1が01なのか02なのかが分かりません。
このような場合には差集合は使えませんか。
また差集合を使わない場合、他に良い方法はありますか。
25NAME IS NULL:2007/04/18(水) 18:38:19 ID:???
24です。
SQLが間違ってました。

select col2,col3 from TableA
except
select col1,col2 from TableB

です。
よろしくお願いします。
26NAME IS NULL:2007/04/18(水) 21:53:21 ID:???
>>24
01を持って来たいのか02を持って来たいのかはオマエが決めなきゃならん。
27NAME IS NULL:2007/04/18(水) 22:29:57 ID:???
文字
a
a
a
b
c
c


文字 個数
a 3
b 1
c 2

とするsql文を教えてください
28NAME IS NULL:2007/04/18(水) 22:33:58 ID:???
count
group by
29NAME IS NULL:2007/04/18(水) 22:44:30 ID:???
ぐぐったらでてきました
どうもです>>28
30NAME IS NULL:2007/04/18(水) 23:08:59 ID:???
>>24
スカラ副問合せが出来るDBMSなら

SELECT A.日付,A.キー
,(SELECT COUNT(*) FROM TBL B
 WHERE B.キー = A.キー
 AND B.日付 < A.日付
) カウント
FROM TBL A
ORDER BY A.日付,A.キー
31NAME IS NULL:2007/04/18(水) 23:11:44 ID:???
上は、>>24ではなく、>>21でした。
32NAME IS NULL:2007/04/19(木) 07:07:17 ID:???
>>24
select col1,col2,col3
from TableA a
where not exists(
select *
from TableB b
where a.col2=b.col1 and a.col3=b.col2
)
3321:2007/04/19(木) 12:48:54 ID:???
>>30
動きました!!ありがとうございます。
34NAME IS NULL:2007/04/19(木) 16:25:37 ID:???
>>33
01  AAAA 1 
02  AAAA 1 
のどっちか一件残すとなると>>.32だと両方消えるのでまずいのだが、
それでよかったのか?
35NAME IS NULL:2007/04/19(木) 18:00:13 ID:???
ファンクションとプロシージャはどう使い分けるのですか?
違いがない様な気がして聞きました。
36NAME IS NULL:2007/04/19(木) 18:08:27 ID:???
>>35
一般的にファンクションは更新が出来ない。
標準化は進んでないから例外はあると思うけどね。
37NAME IS NULL:2007/04/19(木) 20:21:08 ID:iuRHnTpA
>>26
すいません。01、02はどちらが取れても構いません。

>>32
>>34さんも指摘してくれているように
それだと01、02が両方消えるんですよね。

やっぱり、ストアドか何かでコントロールブレイクするしかないですかね。
38NAME IS NULL:2007/04/19(木) 21:36:49 ID:???
t1 t2 t3 の3つのテーブルを結合したaとbをそれぞれ作って
select したいんですがうまくいきません

イメージ的にはこんな感じです

select a.name, b.name
+from t1
|  join t2 a
|    on t1.id = a.id_1
|  join t3
|    on a.id_1 = t3.id
+
|  join t2 b
|    on t1.id = b.id_2
|  join t3
+    on b.id_2 = t3.id
where t1.id = 1

よろしくお願いします
3938:2007/04/19(木) 22:27:27 ID:???
血を吐きそうになりながらも自己解決できました〜……
いやーSQLは奥が深い!

よかったら
オススメのSQL(mysql)の参考書・テクニック本とか教えてください
40NAME IS NULL:2007/04/20(金) 00:12:08 ID:???
>>39
俺も知りたかったので教えてください
4138:2007/04/20(金) 16:02:06 ID:???
select b.name, d.name
+from t1
| join t2 a
| on t1.id = a.id_1
| join t3 b
| on a.id_1 = b.id
+
| join t2 c
| on t1.id = c.id_2
| join t3 d
+ on c.id_2 = d.id
where t1.id = 1

t1.id = a.id_1 = b.id -> b.name
t1.id = c.id_2 = d.id -> d.name

みたいな感じ?
実際のSQLのほうは結果がだぶったりするんだけど
DISTINCTで無理やり消した みたいな……

まぁなんとか動けば 理解はあとからついてくるし
42NAME IS NULL:2007/04/20(金) 21:10:41 ID:???
なるほど、難しい・・・
どうもです>>38
43NAME IS NULL:2007/04/20(金) 21:59:36 ID:???
[TableA]
date      col  
------------------------
2007/04/20  10
2007/04/19  20
2007/04/18  30
2007/04/17  40
2007/04/16  50
2007/04/15  60
2007/04/14  70

[TableB]
date      col 移動平均 
------------------------
2007/04/20  10  30
2007/04/19  20  40
2007/04/18  30  50
2007/04/17  40  55
2007/04/16  50  60
2007/04/15  60  65
2007/04/14  70  70

TableAからTableBを作成するSQLを教えてください
dateが自身を含めて4日前までのcolの平均を求めたいです
44NAME IS NULL:2007/04/20(金) 23:48:07 ID:???
>>43
SELECT c.data,c.col,SUM(c.col2)/COUNT(*) FROM
(SELECT * FROM (SELECT * FROM tablea)a CROSS JOIN (SELECT data AS data2,col AS col2 FROM tablea)b ORDER BY a.data DESC,b.data2 DESC)c
WHERE c.data >= c.data2 AND c.data2 > c.data - 5
GROUP BY c.data,c.col ORDER BY c.data DESC

dataとcolでキーなの?なんか違和感が・・・。
45NAME IS NULL:2007/04/21(土) 00:13:27 ID:???
sqlの問題を自宅のパソコンで勉強したいのですが、
初心者でも分かりやすく勉強できるサイトや無料ソフトは
ないでしょうか?あれば教えてください。よろしくおねがいします。
46NAME IS NULL:2007/04/21(土) 00:55:38 ID:???
>>43

SELECT a.date,a.col
,(SELECT AVG(b.col) FROM TableA b
 WHERE b.date BETWEEN a.date - 4 AND a.date
) 移動平均
FROM TableA a
ORDER BY a.date DESC

もしくは

SELECT a.date,a.col,AVG(b.col) 移動平均
FROM TableA a,TableA b
WHERE b.date BETWEEN a.date - 4 AND a.date
GROUP BY a.date,a.col
ORDER BY a.date DESC
47NAME IS NULL:2007/04/21(土) 01:07:01 ID:???
>>24
select col1,col2,col3
from TableA
where (col2,col3)in(
select col2,col3
from TableA
minus
select col1,col2
from TableB
)
48NAME IS NULL:2007/04/21(土) 01:18:42 ID:???
>>43
select a1.date,a1.col,sum(a2.col)/count(*)
from TableA a1,TableB a2
group by a1.date,a1.col
having a2.date between a1.date-3 and a1.date
49NAME IS NULL:2007/04/21(土) 12:36:56 ID:???
学校でSQLの勉強してて自宅でも学習したいけどSQL Serverっていくらぐらいなの?
50NAME IS NULL:2007/04/21(土) 14:16:02 ID:???
ただ、のやつもあるだろ。
51NAME IS NULL:2007/04/21(土) 15:23:46 ID:???
>>49
Microsoft SQL Server 2005 Developer Edition 日本語版
税抜  6,800円

SQL Server 2005 Enterprise Edition 180日間 限定評価版
http://www.microsoft.com/japan/sql/downloads/trial-software.mspx
無料
5243:2007/04/21(土) 15:24:26 ID:???
>>44 >>46 >>48

素晴らしいです。皆さんのおかげで無事動きました

>>44
主キーはdateだけですが何か変ですか
53NAME IS NULL:2007/04/21(土) 22:35:33 ID:???
>>51
サンクスです
半年も無料で使えるんだ、だったらフリーにすればいいのにね
とりあえず、今のところは無料のソフト入れて勉強したいと思います
サンクスです
54NAME IS NULL:2007/04/22(日) 00:12:30 ID:???
まともに運用する時のライセンス代が馬鹿高いから試用期間も長いんだろ
55NAME IS NULL:2007/04/22(日) 00:39:18 ID:???
一方ORACLEは無料で期間無制限
56NAME IS NULL:2007/04/22(日) 03:37:57 ID:p/CIzjLQ
質問させてください
=の逆は!=ですがlikeの逆は何でしょうか?
!likeだとエラーになりました…
57NAME IS NULL:2007/04/22(日) 04:11:06 ID:???
not like
58NAME IS NULL:2007/04/22(日) 08:47:03 ID:???
データベースのSQLの勉強初めて疑問があるけど、なんでACCSEとか入力するだけのソフト使わないの?
わざわざ、言語で生成するメリットって自由性?自分の思ったような形にできること?
まだ、初期段階で高度なことはしてないから気づかないだけかもしれないけど
59NAME IS NULL:2007/04/22(日) 11:17:50 ID:???
日本語でおk
60NAME IS NULL:2007/04/22(日) 13:50:40 ID:???
最初からツールを使うのと、基礎が分かった上で便利なツールを使うのとでは全く違うっしょ。
それに、何らかのプログラムからSQLを叩く時にAccessなんかは使えないし。
61NAME IS NULL:2007/04/22(日) 13:56:32 ID:???
>>58の言うACCESSとは、SQL*Plusやmysqlコマンドなんかも含むと予想
んで、「わざわざ、言語で生成する」とは、>>60でいう「何らかのプログラムからSQLを叩く」と予想

という意味でレスすると、SQL"だけ"勉強するのに「わざわざ、言語で生成する」メリットは特に無い
6260:2007/04/22(日) 14:25:42 ID:???
>61
自分は、SQL文の手打ち(コピペでもいいけどさ)のことだと認識した。
63NAME IS NULL:2007/04/22(日) 22:14:47 ID:???
>>58
1.データベースの内容をある視点からみたいなー、と思う。
2.必要なSQLが頭に湧く。
3.「頭の中身を吐き出せるプラグが欲しい」と思いながら
 ぺしぺしとテキストエディタへそのSQLを吐き出す。
4.カットアンドペーストでSQL*PlusやらCSEに貼り付けて実行。

・・・大概こんなもんで用が片付くから、わざわざテーブル間の関連付けが
どうとかACCESS使って定義するまでもないからでないかい?
そらユーザーの人に便利につかってもらう為、フォームやらなんやらもいると
なってくると話は違うけども。
64NAME IS NULL:2007/04/22(日) 23:10:25 ID:???
> わざわざテーブル間の関連付けがどうとかACCESS使って定義するまでもないからでないかい?

意味わからん。

テーブル間の関連付けがどっかに定義されてるとでも思い込んでるのか?

それても、制約条件のことを勘違いしているのか?
655:2007/04/23(月) 00:24:30 ID:vffmtpA6
>>5です。

どなたか教えていただけないでしょうか。
ググルにもググリようがありませんし、過去ログはdat落ちして見れません。

お願いします。
66NAME IS NULL:2007/04/23(月) 02:57:07 ID:???
>>65
ソート済みのテーブルを別に作って定期的に更新すりゃいんじゃね?
ってSQL初学者が言ってますよ。
67NAME IS NULL:2007/04/23(月) 04:11:40 ID:???
>>65
valueに非ユニークな索引をつける。
68NAME IS NULL:2007/04/23(月) 07:57:05 ID:???
>>5
DBも書かないような奴はスルーされて当然

とあえて釣られてみる
695:2007/04/23(月) 08:26:36 ID:vffmtpA6
>>5です。
みなさんありがとうございます。

>>68
すみません、すっかり抜けていましたmysqlの4.12です。

>>66
テーブルを作ってみました。
驚くほど早くなりました!

>>67
インデックスを作ってみました。
こちらも驚くほど早くなりました!

取り急ぎ問題解決しましたが、
なんというか、SQL一発で解決できる問題ではなかったのでしょうか?
みなさんはどんな対処が一般的なのでしょうか。
70NAME IS NULL:2007/04/23(月) 08:50:27 ID:???
>>69
つか、パフォーマンスチューニングのためには
何をしなきゃならんのか、もうちょっと勉強汁
71NAME IS NULL:2007/04/23(月) 09:31:02 ID:???
>>58
自動でハナクソをほじる機械があれば一見便利そうに思うが
実際は自分の指でほじった方がずっといい。
それと同じ感覚。
72NAME IS NULL:2007/04/23(月) 18:44:22 ID:???
>>64
いや、単に普段使うSQLが複数テーブルが絡む物ばかりなもんで、
テーブル1つだけの問い合わせについては失念しとった。
深読みさせてすまん。
73NAME IS NULL:2007/04/23(月) 21:12:24 ID:???
>>72
余計意味わからん。

> 単に普段使うSQLが複数テーブルが絡む物ばかりなもんで、

そんな奴が >>64 に書いてることを理解できないわけないと思うが...。
74NAME IS NULL:2007/04/23(月) 23:18:50 ID:???
mysqlでランキングカラムを作るにはどうしたらいいですか?
75NAME IS NULL:2007/04/23(月) 23:52:08 ID:???
>>73
すまん、そう返されると、そもそもの突っ込み意図が読み取れんとしか
言えん。

元々>>63では「テーブルのJOIN」位の意味合いでテーブル間の関連付けと
書いたんだ。要は複数テーブル使った問い合わせをACCESSで作るにしても、
テーブルやらクエリーやらの画面上の箱(正式名称忘れた)同士の列を線で
結んでやって、その結合一本一本にINNERやらLEFTやらの定義を付与するよな?。

その一連の作業を、ちまちまちまちまマウス操作でやるのは面倒なんじゃっ、
という事を言いたかっただけなんだ...。頭に完成形のSQLがある時は特に。
76NAME IS NULL:2007/04/24(火) 00:10:42 ID:???
>>58
Access使うし便利だよ
でもJavaで作ったソフトが売れないと儲からないの
77NAME IS NULL:2007/04/24(火) 00:12:40 ID:???
エディタでコピペとかするぐらいなら Access で SQL を直接入力すればいいだけだろ。

> 頭に完成形のSQLがある時は特に。
78NAME IS NULL:2007/04/24(火) 00:20:54 ID:???
アクセスで使えるSQLなんてMySQLより制限されてるんだよ
79NAME IS NULL:2007/04/24(火) 00:44:53 ID:???
>>77
直接SQL入力していいんなら、そもそもAccess使う意味薄くね?。
SQL内の予約語とか強調表示してくれんし。

というかこれまでの話は、大元>>58

「データベースのSQLの勉強初めて疑問があるけど、なんでACCSEとか入力するだけのソフト使わないの?」

「ツール生成によらないSQLのベタ書きがなんでいるの?」(俺解釈)

の質問に対しての「こんな理由(=うちには後者の方が楽)があるぞ」
レスだしな。
80NAME IS NULL:2007/04/24(火) 03:15:16 ID:???
> データベースのSQLの勉強初めて疑問があるけど、なんでACCSEとか入力するだけのソフト使わないの?

Accessの勉強ってならわかるが、SQLの勉強にはなっていないような気がする
81NAME IS NULL:2007/04/24(火) 09:24:30 ID:???
>>74
自己結合
82NAME IS NULL:2007/04/24(火) 09:35:44 ID:???
>>78
Accessつ〜か、JETの方が
MySQLより柔軟なSQL書けるだろ。
83NAME IS NULL:2007/04/24(火) 21:55:43 ID:???
バージョンによるだろ。

つーか、最新版ならどっちでもあまり不自由しないだろ。
84NAME IS NULL:2007/04/29(日) 15:20:39 ID:GU/EYy4+

はじめまして。

降順で重複非表示をさせたいのですがうまくいきません。




テーブル test1

ID pref

1 北海道
2 青森
3 福島
4 北海道
5 秋田
6 岩手
7 北海道
8 青森
9 秋田
10 福島


期待する表示は

福島
秋田
青森
北海道
岩手

なんですが。

SELECT distinct pref from test1 order by id desc;
のように
distinctとorder by を使ってみたのですが駄目でした。


SQLで一発で抽出する表記するのは無理があるんでしょうか?


85NAME IS NULL:2007/04/29(日) 16:01:23 ID:???
distinctだとそれぞれの県名にどのIDが対応するのか分からないんじゃないの

prefでGROUP BYしてMIN(ID)で降順にするとか
86NAME IS NULL:2007/04/29(日) 18:04:23 ID:???
max(id)だろ
87NAME IS NULL:2007/04/30(月) 00:17:58 ID:LY2aGMZK
処理系の明記必須はテンプレに含むべきだと感じる今日この頃。

>>84
■汎用
SELECT *
FROM
(
SELECT pref, id
FROM test1
INTERSECT
SELECT pref, MAX(id)
FROM test1
GROUP BY pref
)
AS test2
ORDER BY id DESC

■postgresql限定
SELECT DISTINCT ON (id) id,pref
FROM test1
ORDER BY id DESC

でいけるはず。汎用の方は実行速度が微妙かもだ。
88NAME IS NULL:2007/04/30(月) 00:24:24 ID:???
あ゛、postgresql限定がまずい...。
SELECT *
FROM
(
SELECT DISTINCT ON (pref) pref,id
FROM test1
ORDER BY pref,id DESC
)
AS test2
ORDER BY id DESC
89NAME IS NULL:2007/04/30(月) 00:30:26 ID:???
つーか汎用も
SELECT *
FROM
(
SELECT pref, MAX(id) AS id
FROM test1
GROUP BY pref
)
AS test2
ORDER BY id DESC
こんなんでいいよなぁ。ごたごた書いてスマン。
90NAME IS NULL:2007/04/30(月) 01:11:05 ID:???
出題に回答するスレでもないんでしょ?
いきなり答えまで書いちゃうよりも適当にヒントやるぐらいのがいいんでないの
91NAME IS NULL:2007/04/30(月) 01:32:30 ID:???
スタンスもルールも個々人が好きなようにで良いだろ
92NAME IS NULL:2007/04/30(月) 03:58:25 ID:HNTwEPb8
これを読み解けと言われたのですが、助けてもらえないでしょうか。

SELECT ITEM_ID, A.ITEM_NAME, A.MAIN_CATEGORY, A.SUB_CATEGORY, A.QUANTITY, A.POINT, A.RANKER
FROM
( SELECT ITEM_ID, A.ITEM_NAME, A.MAIN_CATEGORY, A.SUB_CATEGORY, A.QUANTITY,
A.POINT, RANK()OVER(ORDER BY POINT ASC) AS RANKER
FROM
( SELECT A.ITEM_ID, A.ITEM_NAME, A.MAIN_CATEGORY,
A.SUB_CATEGORY, A.QUANTITY, A.POINT
FROM
( SELECT B.ITEM_ID, B.ITEM_NAME, B.MAIN_CATEGORY, B.SUB_CATEGORY,
A.QUANTITY, C.URIAGE,
TRUNC((SELECT A.QUANTITY / DECODE(C.URIAGE,0,-1,C.URIAGE) FROM DUAL),2) AS POINT
FROM ( SELECT
ITEM_ID, SUM(QUANTITY) AS QUANTITY
FROM ZAIKO_TABLE
GROUP BY ITEM_ID
) A,
STORE_ITEM_MASTER B,
( SELECT A.ITEM_ID AS ITEM_ID, DECODE(B.URIAGE,NULL,0,B.URIAGE) AS URIAGE
FROM
STORE_ITEM_MASTER A
LEFT OUTER JOIN
( SELECT COM_CODE, SUM(SALES_NUM) AS URIAGE
FROM ORDER_TABLE
WHERE SALES_DATE >= (select add_months(sysdate, -1) from dual) AND
SALES_DATE <= SYSDATE
GROUP BY COM_CODE
ORDER BY URIAGE DESC
) B ON A.ITEM_ID = B.COM_CODE
ORDER BY ITEM_ID
) C WHERE B.ITEM_ID = A.ITEM_ID and A.ITEM_ID = C.ITEM_ID
ORDER BY ITEM_ID
) A WHERE A.POINT > 0
) A
) A
WHERE RANKER <= 3
93NAME IS NULL:2007/04/30(月) 04:33:45 ID:???
>>89
select pref
from test1
group by pref
order by max(id) desc
/
94NAME IS NULL:2007/04/30(月) 05:06:53 ID:???
>>92
>これを読み解けと言われたのですが、助けてもらえないでしょうか。
具体的に何を求めているのかが、見えてこないのですが、
SQL自体は、各テーブル名、カラム名を普通に解釈すると、
在庫数に対する売上げ個数の比率が多い上位3商品の情報を
求めるSQLかと思います。
95NAME IS NULL:2007/04/30(月) 05:14:10 ID:???
>>92
とりあえず無駄なorder byがたくさんあるのは読み解いた。
意味があるのはrank() overの部分だけ。
サブクエリを全部Viewにしてみてひとつずつ何やってるか考えてみろ。
9684です。:2007/04/30(月) 13:29:07 ID:J6a1E/oV

みなさん、ありがとうでがんす。
とても勉強になりました。

来週、職場に戻りましたら、早速試したいと思います。
97NAME IS NULL:2007/05/01(火) 12:25:11 ID:E0G15yAt
データベースの検索に関して、

A列とB列の値を加算して、その上で、少なくともA列の値が1以上である、
というような条件の下、最大の値をとるような行を求める場合には、
どのようなSQLを発行すればよろしいでしょうか?

よろしくお願いします。
98NAME IS NULL:2007/05/01(火) 12:29:41 ID:DXF7CsXb
>>97
何が最大?
A + BがMAXってことかいな?

だとしたら
SELECT MAX(A + B) FROM TABLE1 WHERE A >= 1;
でいいんじゃね?
99NAME IS NULL:2007/05/01(火) 12:33:27 ID:???
>>97
なあ、少しは自分で考えたのか?
100NAME IS NULL:2007/05/01(火) 12:35:24 ID:???
>>98

返信ありがとうございます。

イメージとしては、

SELECT * FROM TABLE1 WHERE 先頭出現頻度 > 0 AND MAX(先頭出現頻度 + 隣接度)

といった感じで、

name p1 p2
hoge 1 2
hoke 2 4

といったデータがあったとき、 p1 と p2 を加算して最大のもので、
そのうち、少なくとも p1 が 1 以上である行の name を取得したいと考えています。


101NAME IS NULL:2007/05/01(火) 13:40:28 ID:???
>>100
前提が既におかしい希ガス。

少なくとも p1 が 1 以上と言っておきながら
WHERE句に「先頭出現頻度 > 0」ってのはおかしいだろ。

WHERE句の額面通りに受け取るなら
「p1 が 0よりおおきい」で無いといけない。
条件の文言が正しいなら
「先頭出現頻度 >= 1」が正しい。

それはともかく、
例えば、SELECT TOP nが使えるなら、
SELECT TOP 1 
  a.NAME,
  MAX(a.P1 + a.P2) as MAXVAL
FROM
  TBL a
WHERE a.P1 >= 1
GROUP BY a.NAME
ORDER BY MAXVAL DESC;

なんてのでも取得可能だと思われ。
102NAME IS NULL:2007/05/01(火) 20:38:12 ID:E0G15yAt
>>101

教えていただいたコードを参考に、以下のように SQL を発行しました。
(WordRanking と 俺 は二つの異なるテーブルです)

SELECT TOP 1 WordRanking.AAA, MAX(WordRanking.BBB+俺.CCC) AS MAXVAL
FROM WordRanking INNER JOIN 俺 ON WordRanking.AAA=俺.AAA
WHERE WordRanking.BBB>=1
GROUP BY WordRanking.AAA
ORDER BY MAXVAL DESC;

上記のコードは OleDbCommand によって実行しているのですが、どうにもエラーが発生します。
Access 上では正しく実行されているように感じられるのですが、どこか誤っている箇所がありますでしょうか?
103NAME IS NULL:2007/05/01(火) 20:51:51 ID:???
だからさぁ、エラーがでるって言うなら、そのエラーメッセージぐらい書けや、このカス・厨房
104NAME IS NULL:2007/05/01(火) 20:57:59 ID:E0G15yAt
>>103

申し訳ありません。
エラーメッセージはデータベースを扱う環境に依存するものであると考えたため、
SQL の構文の正当性の確認には必要が無いと思い、添えておりませんでした。

エラーメッセージ(例外)は以下の通りです。

「1つ以上の必要なパラメータの値が設定されていません。」
(Visual Studio.NET2003, Access2003)
105NAME IS NULL:2007/05/01(火) 21:53:34 ID:???
>>104
SQLの構文としてはこれでいいかどうかを確認したい、ってことかい?
Accessで実行したら結果が返ってくるんだから問題はないんだろうな。
エラーメッセージでぐぐるなり、ADO.NETのスレとかで聞くなりしてみては。

で、SQLで個人的に気になることを言わしてもらうと
最大値をとる行が複数ある場合を考慮しなくてもいいのか、ってのと
あと、そのSQLってわざわざGROUP BYする必要あるのか?
こんなんでいいと思うが。

SELECT TOP 1 WITH TIES WordRanking.AAA, (WordRanking.BBB+俺.CCC) AS A
FROM WordRanking INNER JOIN 俺 ON WordRanking.AAA=俺.AAA
WHERE WordRanking.BBB>=1
ORDER BY A DESC;
106NAME IS NULL:2007/05/01(火) 22:52:23 ID:???
>>104
俺の薄っぺらい知識で推測するに
>ORDER BY MAXVAL DESC;
を↓に変えろってことじゃないだろうか
ORDER BY MAX(WordRanking.BBB+俺.CCC) DESC;
107NAME IS NULL:2007/05/02(水) 10:02:48 ID:???
そいつぁ薄すぎる
108NAME IS NULL:2007/05/02(水) 10:55:19 ID:???
>>106
あ、昨日の晩の俺がいる。
便乗質問なんだが、例えばSQLイメージで
SELECT 血液型,count(*) AS 人数
FROM 日本人
GROUP BY 血液型
ORDER BY 人数
という構文(ORDER句に集約値につけた名前を直使用)は
大概のDBへの問い合わせに使えるのだろうか?
(>>104とは関係なく一般的な話として)
いや確かpostgresqlでは駄目だったんだこの構文。
109NAME IS NULL:2007/05/02(水) 11:00:40 ID:???
>>108
バージョンいくつ?
110NAME IS NULL:2007/05/02(水) 12:06:42 ID:???
>>109
確か7.2.1?(最後の桁が自信無い)
以前そういったことがあったんで、とりあえずGROUPとORDERを
 SELECT * FROM(集約式)AS 結果 ORDER BY 人数
こんな風に分離して逃げた覚えがあるんだ。
111NAME IS NULL:2007/05/02(水) 12:12:42 ID:???
7.xは今動作環境ないなあ
8.1.4ではとりあえず、それ使えてます
112NAME IS NULL:2007/05/02(水) 13:03:51 ID:???
>>112
お、8.1.4ではいけると。なら俺の知識が古いだけか...。
113NAME IS NULL:2007/05/02(水) 15:14:18 ID:???
7.4でもいける。
7.2でも使えてたような気がするんだがなぁ。
114NAME IS NULL:2007/05/02(水) 15:57:33 ID:???
7.2以降とそれより前は大きく違うからな、7.1以前ならありうる気がしないでもない
115NAME IS NULL:2007/05/02(水) 16:15:11 ID:M2WxE7YV
>>105
>>106

返信、どうもありがとうございます。

>>105 によって示されたコードに
>>106 が示した箇所を修正したところ、見事に動作しました。

とても助かりました。
どうもありがとうございました。
116NAME IS NULL:2007/05/02(水) 18:03:09 ID:???
>>108
7.1.2があったから試してみたけど、いけたよ。
order by 2
も試したけど、これもちゃんとソートされた。
117NAME IS NULL:2007/05/02(水) 19:07:26 ID:???
>>111 >>113 >>116
なら俺の記憶はなんか別の件をねじまげてしまったんだな。嘘言ってスマン。
連休明けに7.2.1(多分)の開発環境で自分でも試してみるよ。
118NAME IS NULL:2007/05/02(水) 19:15:59 ID:???
今日の日付 2007-05-02

SELECT end, start
FROM hyou
WHERE date >= now()
ORDER BY date;

end      start
2007-05-02 0
2007-05-02 0
2007-05-02 0
2007-05-03 0
2007-05-04 2007-04-29 ←
2007-05-07 0
2007-05-08 2007-05-03

これを下のように表示したいのですが、
どうSQLを組めばいいんでしょうか・・?

end      start
2007-05-02 0
2007-05-02 0
2007-05-02 0
2007-05-04 2007-04-29 ←
2007-05-03 0
2007-05-07 0
2007-05-08 2007-05-03

「start」の日付から「end」の日付の間に、今日の日付が含まれていれば
「end列に今日の日付の含まれる行」の次の行に該当するものを表示しようとしています。
119NAME IS NULL:2007/05/02(水) 20:15:12 ID:???
すみません、自己解決しました。

IF( end >= now( )
AND start <= now( )
AND start <> '0000-00-00', DATE_FORMAT( now( ) , '%Y-%m-%d' ) , date ) AS bit
ORDER BY bit
120NAME IS NULL:2007/05/02(水) 20:22:18 ID:???
失礼・・・「"end列に今日の日付の含まれる行"の次の行に該当するものを表示」が出来ないorz
121NAME IS NULL:2007/05/02(水) 20:28:54 ID:???
>>120
order by bit,end,start
ってすればいいんじゃにか?
122NAME IS NULL:2007/05/02(水) 21:06:56 ID:???
>>121
なるほど。。ORDER BYで複数指定した際の考え方がいまいち分かっていませんでしたorz
その構文で期待通りの表が得られました。ありがとうございます。
123NAME IS NULL:2007/05/08(火) 00:52:25 ID:YXJfMvSq
sqlについての質問です。

Aテーブル
no | date
a | 2007/10/11
b | 2006/2/3
c | 2006/4/2

Bテーブル
no | date | value
a | 2004/10/3 | 24
b | 2005/2/1 | 30
c | 2008/10/11 | 13

のようなテーブルがある時、AとBのテーブルをleftjoinでnoをキーにして結合、
そして、AとBの同じnoでもdateの値が大きい方を取得、最後にその値でソートをかけたいのですが、
どのようなsqlを発行すればいいでしょうか?

欲しい結果
no | date | value
c | 2008/10/11 | 13
a | 2007/10/11 | 24
b | 2006/2/3 | 30




124NAME IS NULL:2007/05/08(火) 02:59:26 ID:???
>>123
SELECT no,CASE WHEN A.date>B.date THEN A.date ELSE B.date END AS date,B.value
FROM A LEFT JOIN B USING(no) ORDER BY date;
125NAME IS NULL:2007/05/08(火) 13:54:02 ID:???
すんまそん。。

正規化して外部キーが沢山あるテーブルAにinsertする場合、
各情報をそれぞれの各テーブルにinsertしていき、そのidをテーブルAに外部キーとして
記録する、とゆー以外に

なにか特殊なステートメントとかで、テーブルAに対するSQL一発で、全部済んじゃう
なんていう虫のいい方法ってあるのでそうか。。

よろしくおながいします。m(_ _)m
126NAME IS NULL:2007/05/08(火) 14:59:14 ID:???
ストアド
127125:2007/05/08(火) 16:05:56 ID:???
>>126

>ある表 (テーブル) の内容を編集して別の表に格納する大量データの更新処理などを
>データベースエンジン内部で処理プログラムを実行し、入出力 (I/O) のほとんどを
>データベース内部で完結することにより、クライアント側とのデータ通信による
>オーバヘッドを削減することでバッチ処理性能を向上させる「ストアドプロシージャ」が考え出された。
ttp://ja.wikipedia.org/wiki/SQL

定型処理を登録しておくっていう感じでしょうか。これなら出来そうですね。
でも、、、、SQLiteを使う予定なので、非対応でした。。orz

一応やりようはあるってことが分かってスッキリしますた。
どうもありがとーでしたー。
128NAME IS NULL:2007/05/08(火) 17:12:12 ID:???
状況がよくわからないんだけど、トリガじゃだめなの?
129NAME IS NULL:2007/05/08(火) 17:14:35 ID:???
トリガでストアドを実行することになるだろうね
130NAME IS NULL:2007/05/08(火) 17:19:05 ID:???
ってSQLiteの話か。
DELETEやUPDATEのカスケードはできるだろうけど、INSERTはどうなる?
131123:2007/05/08(火) 18:53:56 ID:???
>>124
できました。
ありがとうございますた。
132NAME IS NULL:2007/05/10(木) 08:44:19 ID:???
TIMESTAMP型の質問ですが、TIMESTAMP型に対して演算を行うと、表示するとき時間が表示されなくなってしまいます。
何故このように表示されるのか、解説をお願い致します。

SELECT
   SYSTIMESTAMP AS A
    SYSTIMESTAMP - 1/1440 AS B
FROM
   DUAL;


以下、実行結果

A
--------------
2007/05/10 08:33:05.385

B
--------------
2007/05/10
133NAME IS NULL:2007/05/10(木) 09:39:19 ID:???
>>132
DUALを使ってるからOracleのtimestamp型かな?
計算結果がDATE型に化けてる感じだね。
TO_CHARで時分秒まで書式指定してみては。
134NAME IS NULL:2007/05/10(木) 09:42:20 ID:???
>>133
ありがとうございます。
試してみます。
135NAME IS NULL:2007/05/10(木) 09:53:41 ID:???
>>134
その問い合わせでVIEWを作ってみると
AはTIMESTAMP型になるが、BはDATE型になる。
>>133の回答が正しいと思われ。
136133:2007/05/10(木) 12:42:06 ID:???
>>133
>>135
試してみました。
DATA型になっているようです。
TIMESTAMP型のまま計算はできないのでしょうか?

SELECT
  to_char(SYSTIMESTAMP - 1/1440,'yyyy-mm-dd hh24:mi:ss:ff'),
FROM
  DUAL;

行2でエラーが発生しました。:
ORA-01821: date format not recognized
137NAME IS NULL:2007/05/10(木) 13:01:34 ID:???
>>136
DATE型に対してミリ秒まで書式指定してるからでないの?

SELECT
 SYSTIMESTAMP AS A,
 TO_CHAR(SYSTIMESTAMP - 1/1440,'YYYY/MM/DD HH24:MI:SS') AS B
FROM DUAL;
ならエラーでないし。

どうしてもTIMESTAMP型にしたいなら
SELECT
 SYSTIMESTAMP AS A,
 TO_TIMESTAMP_TZ(TO_CHAR(SYSTIMESTAMP - 1/1440,'YYYY/MM/DD HH24:MI:SS'),'YYYY/MM/DD HH24:MI:SS') AS B
FROM DUAL;
みたいにしなきゃならんと思われ。
138133:2007/05/10(木) 13:34:58 ID:???
>>137
たぶんそれです。
ありがとうございます。
早速試してみます。
139NAME IS NULL:2007/05/10(木) 14:51:42 ID:???
ワキガ…それは、科学技術が発達した現代において、未だ解決手段を
      見出せない不治の病…

ワキガ…それは、人と人を分かつ人種差別の根源。ワキガこそが
     人々を争わせ、血と涙を流させる…

ワキガ…それは、夢ある若者を絶望させ、悪心を植えつける悪の源泉

ワキガ…それは、悪徳業者の儲け口。悪をのさばらせる恰好のエデン

ワキガは全てを破壊し、再生を妨害する。ワキガがある限り、この世は平和にならない。
こんにちまで、私達人間はワキガに対する対抗手段を持ち得なかった。
だが、2007年の五月。ついにワキガを撲滅するための手段が見つかった!
その名は「軽石療法」
軽石でワキを擦ることで、ワキガは消滅するのだ!なんと単純な治療法だろうか。
しかし疑ってはいけない。相対性理論も画期的だがシンプルだったではないか。
そう、画期的なものはシンプルなのだ。シンプルでなければいけないのだ。
つまり軽石療法こそが、ワキガを消滅させるための唯一の方法なのだ。

軽石療法について詳しく知りたければいますぐここへ行くことをお勧めする。
※わきが※ワキ擦り治療法※腋臭※
http://life8.2ch.net/test/read.cgi/diet/1172992888/

君の人生に明るい光がさすことを約束しよう。さあ来たれ悩める民たちよ。
140nobodyさん:2007/05/10(木) 17:36:02 ID:7Nf664PD
欠番を埋めるSQLを作成しています。
テーブル名 TEST_TB

C_ID C_NAME
C00001 A
C00002 B
C00004 D
C00005 E
C00006 F

C00003を取得するSQLが書けません。
ご教授よろしくお願いいたします。
141NAME IS NULL:2007/05/10(木) 17:56:47 ID:???
>>140
C_IDの桁数は6桁固定で後ろ5桁が数字でOK?

しかし1桁目が文字でゼロ詰めされてるから、
文字列操作がめんどくさいなwww

select MIN(to_number(SUBSTR(C_ID,2)) + 1) AS TARGET from TEST_TB
WHERE (to_number(SUBSTR(C_ID,2)) + 1) NOT IN (select to_number(SUBSTR(C_ID,2)) from TEST_TB)

Oracleならこれで3が戻るはずから、
戻り値をC00003にするようガンガレwww
142NAME IS NULL:2007/05/10(木) 21:28:29 ID:???
Webサービス(PHP)で使うユーザとグループをSQLで管理しようと考えています。
ユーザが複数のグループに所属できるようにしたいのですが、
ユーザとグループそれぞれのテーブルの良い関連づけの仕方が思いつきません。

・ユーザのテーブルに所属グループを記す配列を付ける
・グループのテーブルに所属メンバーを記す配列を付ける
初めは以上の2通りのやり方を考えたのですが、SQLには配列が無いことに気付きました。

配列を実現するために、ユーザ(あるいはグループ)ごとに配列の代わりになるテーブルを作成するか、
カンマ区切りの数値を文字列として保存して配列のように使うか、
今はその二つの方法だけが思いつき、どちらが最適か悩んでいます。

SQLでの一般的な実現方法がありましたら、ご教授願います。
143NAME IS NULL:2007/05/10(木) 22:47:08 ID:???
>>142
ユーザー表、グループ表、ユーザー・グループ対照表
144nobodyさん:2007/05/11(金) 10:19:09 ID:5xTIeHlP
>>141
ありがとうございました。
ただ、mysqlだったのでto_numberは使えませんでした。
145NAME IS NULL:2007/05/11(金) 10:23:05 ID:???
>>144
だったら最初からRDBMS名を挙げとけwww

MySQL4.1のリファレンス見ると
CASTかCONVERTが存在するから、それ使え。
146NAME IS NULL:2007/05/11(金) 10:23:43 ID:???
>>144
あと、SUBSTRは、SUBSTRINGな。
147NAME IS NULL:2007/05/11(金) 15:27:23 ID:???
お舞ら一般的な考え方を教えてください。
あるテーブルにUINTのフィールドがあったとします。
それはテーブルでユニークではなく、同じ値を複数のレコードがもちえるとします。

ここである操作に対して新しいレコードを作製しそのフィールドにそれまで使われてない値をいれたいんですが、この使われてない値を高速に持ってくる方法ってあるんでしょうか?

インクリメントしていってもいいんですが、レコードが削除されて使われなくなった値とか出てきます。その値も無駄にすることなく使いたいのです。
ひとつ考えたのはインクリメントしていって上限までいったら歯抜けをつめなおして関連テーブルの値を更新するものです。
もしも使われてない値を高速に持ってくることができるならそうした処理をする必要がないので、何か手段があれば教えてくださいエロイ人(´・ω・`)
148NAME IS NULL:2007/05/11(金) 15:42:13 ID:???
>>147
UNSIGNED INTなら、
http://www.yel.m-net.ne.jp/~oss/Tips/ADO/Tips_11003.htm
をまんまパクればいいと思うが?

SELECT MIN(UINTの列名+1) AS 欠番 FROM テーブル
   WHERE UINTの列名+1 NOT IN (SELECT UINTの列名 FROM テーブル)

で取れるんじゃね?
149NAME IS NULL:2007/05/11(金) 18:14:51 ID:???
さんくすです。パフォーマンス見て検討してみます。
150NAME IS NULL:2007/05/11(金) 19:49:42 ID:???
UINTって約43億?
設計上INSERTとDELETEが非常に多く繰り返されてしまうのかもしれないけど、
それでも実レコードが数百万とか数千万にまで膨れ上がると、
>>148では遅くなるだろうな。(ハードも含めたシステムによるけど)

DBによるが、NOT IN より NOT EXISTSで相関クエリにした方が速そう。
でも結局、1度はテーブル全て読み込むことになってしまう。

ULONGを使うと事実上インクリメントしても一巡することはありえねぇーってなら
その方が速いんじゃね。
151NAME IS NULL:2007/05/11(金) 23:54:19 ID:m7WrnMvu
DESC って何の略?ORDER BYで使うDESC。
152NAME IS NULL:2007/05/12(土) 00:34:43 ID:o1KON6CY
descend
153NAME IS NULL:2007/05/12(土) 01:15:06 ID:???
>>142
俺もあるシステム作ったときに同じようなことで迷った

結局、「ユーザーとグループの対照テーブル」に
「ユーザー列」+「所属するグループのキー」をカンマ区切りの文字列で格納して
JSPで分割しながら判定するようにしたけど、遅いし、無数に増えるグループだといつかカラムの容量超えるしで
結局所属できるグループ数と全体の最大グループ量に制限設けるしかなかったんだよな

よくありそうな話だし、DB設計者なら何かもっとよいDB設計がでてくるのかもね
154NAME IS NULL:2007/05/12(土) 02:20:53 ID:???
「ユーザーとグループの対照テーブル」に
ユーザーID, グループIDを追加していくだけじゃダメなんですか?
155NAME IS NULL:2007/05/12(土) 09:21:13 ID:???
>>153
俺も、最初 DB 使い始めの頃は同じような考え方してたよ。

一般的な正解は >>143, >>154 の言う通りで

[ユーザ表]
id
名前
...

[グループ表]
id
名前
...

[ユーザ・グループ対照表]
ユーザid
グループid

のようにして、ユーザをグループに所属させる時は [ユーザ・グループ対照表] に
ユーザid と グループid の対を挿入していく。

ある名前のユーザが所属するグループ名一覧が欲しい時は、

SELECT "ユーザ表"."名前", "グループ表"."名前"
FROM "ユーザ・グループ対照表", "グループ表", "ユーザ表"
WHERE ( "ユーザ・グループ対照表"."グループid" = "グループ表"."id"
AND "ユーザ・グループ対照表"."ユーザid" = "ユーザ表"."id" )
AND ( ( "ユーザ表"."名前" = 'いいいい' ) )

のようにする。(OpenOffice.org の Base の例)

三つものテーブルにアクセスしないといけないし、[ユーザ・グループ対照表] は
結構行数も大きくなるので、なんか非効率な感じがするけど、インデックスとか
ちゃんと設定しておけば大丈夫。

凄くよくある話だし、データベースの基本だから「データベース 正規化」とかで
ぐぐって色々見てみるといい。わかってみるとそんなに難しい概念じゃないよ。
156NAME IS NULL:2007/05/12(土) 15:52:24 ID:???
なるほど、そういうことか
何か意味もなく「ユーザ・グループ対照表」のユーザーIDもしくはグループIDを一意にしないとって考えにとらわれてた

DB周りはあまり触らないのだけど、スッキリしたし勉強になったよ。ありがとう
157NAME IS NULL:2007/05/13(日) 11:18:16 ID:CvhZCYzt
質問です。
データベースをとある条件で検索した多量の結果のうち、
項目の範囲を指定して、その範囲内だけのデータを取得するにはどうすれば良いのでしょうか?
例を挙げると、検索系のシステムで、最初の20件・・次の20件・・最後の20件、というアレです。

よくありそうな処理ですが、これの解説をされているサイト等、私には見つけることが出来ませんでした。
くだらない質問かもしれませんが、ご存知の方いらっしゃいましたらご教授くださいませ。
158NAME IS NULL:2007/05/13(日) 11:20:40 ID:???
MySQL ならLimit SQLServerだったらTOP(だったか?) etc
159NAME IS NULL:2007/05/13(日) 11:21:18 ID:???
>>157
limit offset構文が使えるなら、それで。
使えないなら別の方法でwww

多分にRDBMSの方言が出てくるから、
手前の使ってるDB名晒せ。
160NAME IS NULL:2007/05/13(日) 11:42:43 ID:rmiwhMVe
Oracleで重いUPDATEをいくつか書いたスクリプトを流そうと考えています。

UPDATE tbl1 set a=1;
UPDATE tbl1 set b=2;

Object Browserかsql/plusで流す予定ですが、途中経過を出力させたいのです。
例) "UPDATE tbl1が終了しました"
どのようなSQLを書けば宜しいでしょうか?教えて下さい。
161NAME IS NULL:2007/05/13(日) 11:54:01 ID:???
dbms_output使っても経過情報を
リアルタイムには出力できなかったと思うので、
SQLを実行するスクリプト側で1本目のSQL終了時に
標準出力にECHOさせるようにするしかない。

162NAME IS NULL:2007/05/13(日) 11:54:21 ID:???
スクリプトの中に外部プロシージャー呼び出せばいいのでは。
163NAME IS NULL:2007/05/13(日) 11:58:16 ID:???
>>158-159
標準のSQLではなく、データベースサーバによる拡張的に存在していたのですね!
使用しているのはMySQLなので、Limitを使ってみたいと思います。
これは非常に為になりました。どうもありがとうございました!
164160:2007/05/13(日) 11:59:43 ID:rmiwhMVe
更新情報をリアルタイム出力する必要はないです。
1個目のSQLが終わって2個目のSQLが開始されたことだけわかればOK。
ずっと放置して固まっていたというのが怖い。

>>161>>162
それを調べるのにキーワードとなる単語はありますか?
もう少し詳しく教えて頂けると助かります。
165NAME IS NULL:2007/05/13(日) 12:04:25 ID:???
>>164
「Oracle EXTPROC」
とか
「Oracle 外部プロシージャ」
とかだろうなwww

標準出力にECHOするだけの外部プロシージャなら、
CでもJavaでも簡単に書けるし。


>>162
外部プロシージャでECHOさせる発送はなかったわ、俺。
166160:2007/05/13(日) 14:06:49 ID:rmiwhMVe
何とかなりそうです。ありがとう。
167162:2007/05/13(日) 18:35:24 ID:???
>>165
ちなみにDB2/400とかだと経過情報をリアルタイムに見れるな。

普通(?)のDB2UDBがソレっぽい事できなくて驚いたので、
ちょろっと悩んだ時期があった。

最近は前もって「5分くらいかかるから気にスンナ」ってメッセージ最初に
出すようにしたけどな。w
168NAME IS NULL:2007/05/14(月) 15:46:02 ID:o9PHUJbI
次のように社員番号と枝番で一意であるが、枝番がNullを許容する場合、
社員番号と枝番で一意であることをどのように示すのでしょうか?
主キーはなしで、社員番号と枝番を複合して、
ユニーク制約(ユニークインデックス)とすべきでしょうか?

社員番号  枝番
123  1
123  2
123  Null
169NAME IS NULL:2007/05/14(月) 15:49:37 ID:???
>>168
枝番にNULLが来るなら
UNIQUE制約しかないと思うよ。
170NAME IS NULL:2007/05/14(月) 16:04:54 ID:???
枝番0を新設するほうが簡単な気がする
171NAME IS NULL:2007/05/14(月) 22:02:25 ID:???
俺もそう思う。
172NAME IS NULL:2007/05/14(月) 22:29:41 ID:???
>>168
ふつう、nullにuniqueは効かないから(123,null)が複数エントリできてしまうよ。
MS-SQLServerは違うみたいだけど。
173NAME IS NULL:2007/05/15(火) 13:07:51 ID:???
a_tb (
date,
b_id
)

b_tb (
id,
url
)

とゆー二つのテーブルから、b_id同士をつなげて、重複しない最新の5件のurlを表示したいのです。そこで...

select DISTINCT date(a_tb.date), b_tb.url FROM a_tb, b_tb
WHERE a_tb.b_id = b_tb.id ORDER BY a_tb.date DESC LIMIT 5;

としたのですが、重複排除の集約方向が、dateの古いレコードの方に集約されてしまって、こまっています。。

つまり、a_tbに

2007-5-15 13:05:00, 5
2007-5-15 10:05:00, 5

とあると、下のレコードに集約されてしまって、上のレコードがあることが、
最新の5件の中に含まれないのです。。orz

お知恵を拝借したいです。。よろしくおながいします。
174NAME IS NULL:2007/05/15(火) 14:59:41 ID:???
>>173
>date(a_tb.date)
どのDBMSを使っているか知らないが、
date() というのが時分秒を切り捨てる関数なんじゃないのかい?
175NAME IS NULL:2007/05/15(火) 15:48:09 ID:???
>>174
>どのDBMSを使っているか知らないが、
スマソ。SQLite 3でつ。

>date()�というのが時分秒を切り捨てる関数なんじゃないのかい?
yes。日付だけになるので、同じ日の同じURLの重複を排除すると言う感じになっておりますです。
そうしないと分秒が影響して、DISTINCTする意味が無くなってしまう気がするので。。

もしかして、、、ORDER BYで時間含めてソートしていても、
DISTINCTで日付だけでソートされた時に、ORDER BYのソートは全く関係なくなってしまうのでしょうか?
そんな気がしてきました。。

とすると、最新の5件に重複するURLが含まれないようにするには、SQLだけでは難しいのかな。。むー

もうちょと考えてきます。どうもありがとうございましたー。
176NAME IS NULL:2007/05/15(火) 17:19:09 ID:???
SELECT DATE(a_tb.date), b_tb.url FROM a_tb, b_tb
WHERE a_tb.b_id = b_tb.id GROUP BY DATE(a_tb.date)
ORDER BY 1 DESC

こんなんじゃだめか?実行すらしていないが。
これじゃダメならサブクエリ使うといい
177176:2007/05/15(火) 17:19:50 ID:???
ごめ、忘れてくれ
178147:2007/05/15(火) 18:09:58 ID:???
たびたびすいません。
またIDのつけ方で悩んでるのですが、次のような方法はありですか?
UINTなどをIDとする。
IDはオートもしくは手動でインクリメントさせる。
IDが上限まできたら、すでに削除されたレコードがあるとして0から連番になるように更新する。その際関連するテーブルのID値も更新する。
つめた後のIDの最大値+1を次のIDのシードとする。



・・・こんな処理が必要なのか?だんだん疑問になってきた。皆さんID値ってどうされてるんでしょう?
179NAME IS NULL:2007/05/15(火) 20:07:24 ID:???
>>178
普通にシーケンスつかって取得してるけどwww
180NAME IS NULL:2007/05/15(火) 23:46:12 ID:???
>>178
> IDが上限まできたら

普通は、来ないようにする。

どの DBMS 使ってるのか知らんけど、最近の奴なら ID を 64bit にできるから、
よほど特殊なデータでない限りラップしたりしない。
181NAME IS NULL:2007/05/16(水) 07:08:42 ID:???
>>178
32bitのIDを使い切る場合は、
1秒に10 IDずつ新規IDを発行すれば1日864000 IDで13年半ほどもつ。
64bit使い切ろうと思ったら、
1日4294967295(32bit相当分) IDを消費するために1秒49710 ID程度の新規発行が必要で
これでも11734883年ほどもつ。

まあなんだ頑張れ・・
182NAME IS NULL:2007/05/16(水) 16:40:18 ID:shmAdjsQ
tbl_area
*************
area_id
-------------


tbl_shop_area
*************
area_id(FK)
shop_id(FK)
-------------

tbl_shop
*************
shop_id
-------------

という主キーを持つ三つのテーブルがあってもうすでにある程度DATAが入ってます。
shopテーブルが持つエリアの数は1つなので、tbl_shopにarea_idカラムを作って
tbl_shop_areaから対応するshop_idを持つarea_idを、そのカラムに流し込みたいのですがどうすればよいのでしょうか?

ALTER TABLE tbl_shop ADD COLUMN area_id INTEGER;
ALTER TABLE tbl_shop ADD FOREIGN KEY(area_id) REFERENCES tbl_area (area_id) ON UPDATE CASCADE ON DELETE SET NULL;
とカラムは作ったのですが、流し込むところで躓いてます。

UPDATE tbl_shop SET tbl_shop.area_id = tbl_shop_area.area_id WHERE tbl_shop.shop_id = (SELECT tbl_shop_area.shop_id FROM tbl_shop_are);
とやってみたのですが
ERROR: missing FROM-clause entry for table "tbl_shop_area"
といわれたので
UPDATE tbl_shop SET tbl_shop.area_id = tbl_shop_area.area_id FROM tbl_shop_area WHERE tbl_shop.shop_id = (SELECT tbl_shop_area.shop_id FROM tbl_shop_are);
とかしてみましたけど根本的にちがうっぽくてうまくいきません。

複数行のUPDATEはできないのでしょうか?
なんかスクリプト使わないと無理なのかな?

SQLでいける書き方あったらお願いいたします。
183182:2007/05/16(水) 16:41:32 ID:???
ちなみにpostgreSQL8.1.8です
184182:2007/05/16(水) 16:59:25 ID:???
UPDATE t_shop SET area_no = (SELECT area_no FROM t_rel_shop_area WHERE t_shop.shop_no = t_rel_shop_area.shop_no);
でできました。(微妙にカラム名違うけど気にしないでください)

お騒がせしました。
185NAME IS NULL:2007/05/17(木) 10:48:10 ID:EjOsYkVC
おせわになってます
timestampが保存されているカラムから現在までの時間を取得したいのですが
age(add_date)
を使うと、例えば
3 mons 24 days 10:00:01.22559
という型で帰ってきてしまって、PHPなどで使うときに
"3 mons 24 days 10:00:01.22559"というテキストになって
計算に使うのが面倒なのですが、
秒数や何日、見たいな形で取得することはできないのでしょうか?

お願いいたします。
186185:2007/05/17(木) 10:50:07 ID:EjOsYkVC
DBの種類書くの忘れました
postgresqlです。
187NAME IS NULL:2007/05/17(木) 12:14:51 ID:???
varcharの長さを短くしておくメリットって( ´Д`)なにか?あるんでしょうか?
なければすべてvarchar(Max)とかしておけばいいのかと思ったのですが
188NAME IS NULL:2007/05/17(木) 12:35:23 ID:???
>>185
extract(epoch from age(d))
とかでどうかなあ。
この辺よく変わるからバージョンによるかも。
189NAME IS NULL:2007/05/17(木) 15:26:41 ID:???
>>187
その長さ以上の文字列が入っちゃだめなときとか。。
190NAME IS NULL:2007/05/17(木) 15:48:36 ID:???
>>189 そういう制限ないときはMaxでいいとですか?
191NAME IS NULL:2007/05/17(木) 17:44:34 ID:???
>>190
DBMSによるかのう。
無制限の可変長文字列はラージオブジェクト扱いだったりでいろいろ制限があるものが多い。
varchar(max)とか言ってるからMSSQL2005かな?
旧バージョンのtext型と違い制限は少なくなってるけどまだ何かあったはず。
192NAME IS NULL:2007/05/17(木) 17:49:13 ID:???
>>191 
いわれてるとおりMSSQL2005です。
なるほど。あえて8000文字までとMaxで分けてるからには実装で違いありそうですね。
通常のvarcharのサイズの長短でも影響あるのか調べて見ます。
193NAME IS NULL:2007/05/17(木) 19:37:37 ID:wTPpdrT0
oracleで日本語の半角、全角を区別しないで検索する方法ってありますか?
194NAME IS NULL:2007/05/17(木) 20:27:31 ID:???
>>187
ストアドプロシージャやユーザ定義関数内でvarchar(max)な変数が
使えなかった気がする。

なので、そういうので値いじろうとすると面倒になる。
195NAME IS NULL:2007/05/19(土) 21:45:20 ID:???
【女性客拉致・強姦】 被害女性「男が4人ほどいた」と証言…ステーキ店「ペッパーランチ」店長・店員の他に共犯者か★35
http://news22.2ch.net/test/read.cgi/newsplus/1179576460/

ペッパーランチという大手ステーキ屋の店長達が、食事中の女性客を店内で拉致・レイプした。
店の制服・名札を着けたまま犯行に及んでいることから、レイプ後に被害者を殺す予定だった可能性が高い。
ところが報道はほとんどされず、インサイダー取引の可能性大。
同社の隠蔽工作、google対策等怪しいが、一週間経っても新情報無し。

31スレ消化 = 3万1000カキコ
関連スレレス数おおよそ 1万
ロムが これの5倍にあたる15万人?
約20万人のネラーが興味を示してます。

2chからの現段階での波及効果
○アマゾンにて一瀬邦夫社長の著者本の評に罵詈雑言
○ミクシーなどでペッパーランチアルバイトがまさかの暴言。これに対して総攻撃
○wikiのペッパーランチが書き換え合戦によりほぼ機能停止
○ペッパーフードサービスHPがポートを意図的に閉鎖
○携帯チェーンメール展開中
○ペッパーランチはてなダイアリーにて「女性客が一人で食べに行くと、逆に店員に食べられてしまうという」記載
○Yahoo グルメ、株式掲示板にてペッパーランチ炎上
○監禁場所の特定(2chスクープ)
○ペッパーフードサービスHPに掲載された謝罪文の誤字脱字に「バカじゃねーのwww」と指摘レス相次ぐ
これら繰り返される訂正レスにペッパーフードサービスは反応。合計七回もの謝罪文を訂正
(執行部は2chを見てるのは間違いないと確信)
○ファミリーマートがペッパーフードサービスとの共同商品に大して「事件の重大性」を理由に
共同開発中止を通達
○有志のブロガーさん達が、報道を抑制しているマスコミに代わって自分のブログでこの事件をエントリー開始

ペッパーランチからの攻撃
○2ch内での工作員を送り込む(煽動失敗、2chによって完全制圧される)
196NAME IS NULL:2007/05/20(日) 00:37:47 ID:???
logテーブルがあって
 user_id(int)
 run_time(timestamp)
これを
 ・5/19 20時 2回 ・5/19 21時 0回
 ・5/19 22時 1回 ・5/19 23時 4回
みたいな感じで 1ページに1ヶ月分表示しているんですが
発行クエリが 31日×24時間=744回 発生するんで非常に重いんです……

なにか1回だけのSQLで744行返ってくる書き方あれば教えてください
DBはmysqlです


現在使っている方法
select count(*) from log
where uid=ユーザid and date_format(run_time, '%Y-%m-%d-%H)'=?
?は for $i (1..31){for $j(0..23){年-月-$i-$j}}

197NAME IS NULL:2007/05/20(日) 02:10:08 ID:???
select date_format(run_time, '%Y-%m-%d-%H'),count(*) from log
where uid=ユーザid
group by date_format(run_time, '%Y-%m-%d-%H')
198NAME IS NULL:2007/05/20(日) 09:12:26 ID:???
>>197
こういう SQL 見てて select のところの date_format() と group by
のところの date_format() に同じ内容を書かないといけないのが、なんか嫌。

select date_format(run_time, '%Y-%m-%d-%H') as DateHour, ...
group by DateHour

のようにすればよさげなんだけど、なんか駄目な理由でもあるんだろうか?

date_format(run_time, '%Y-%m-%d-%H') ぐらいならまだ許容範囲だけど、
case を使ったような長い式を書く時に特にそう思う。
199NAME IS NULL:2007/05/20(日) 10:50:36 ID:???
>>198
GROUP BY や WHERE は SELECTリストを見てるんじゃなくて、
FROM句を見てるから。つーか、SELECTのところよりGROUP BY句の方が先に処理されてる。
逆にORDER BYはSELECTリストに無いとエラーになる。こちらはカーソルだからね。

とは言うものの、今のPostgreSQLのGROUP BYはORDER BYと同じように扱えたりする。
エイリアスで指定可能はもちろんのこと、
SELECT date_format(run_time, '%Y-%m-%d-%H'),count(*) FROM log
WHERE uid=ユーザid GROUP BY 1;
んでも桶。まぁ、パーサが融通利かせれば如何様にでもなるんだろうけど。
200196:2007/05/21(月) 00:05:37 ID:???
>197
ありがとうございます
countが0だと返らないのはなんかアレなんですが
まぁプログラム側で処理すればいいですね

>198
ただでさえ分かりにくいから できるだけ簡潔に書きたいですね

>199
ホリデープログラマーは気にする必要なさそうですね

ありがとうございました。またよろしくです
201NAME IS NULL:2007/05/21(月) 06:01:43 ID:HJQ5A+AS
mysqlを勉強していますが、わからないことがありましたので、質問させていただきます

Tbl_player

id name posi
1 三浦 FW
2 柳沢 FW
3 中村 MF
5 中田 MF
7 小野 MF

こういったテーブルがあったとして、
最後のレコードのnameを抽出したい場合、Where句にはどのような抽出条件を書いたらいいのでしょうか。

SELECT name
FROM Tbl_player
WHERE ??
202NAME IS NULL:2007/05/21(月) 07:11:12 ID:???
>>201
何をもって「最後のレコード」とするのが不明だが、idが一番大きい物を選ぶなら、
WHERE id = (SELECT max(id) FROM Tbl_player);
サブクエリが使えないMySQLだったら、idで降順に並べ替えて1行目。
203NAME IS NULL:2007/05/21(月) 21:07:36 ID:???
select name from Tbl_player order by id desc limit 1
204NAME IS NULL:2007/05/23(水) 16:23:31 ID:???
MySQL 4.1 以降ならサブクエリ可。
205NAME IS NULL:2007/05/23(水) 16:25:44 ID:???
だからサブクエリが使えないMySQLだったらって書いてるんだろ
使えるMySQLもあるからわざわざ書き足してる
206NAME IS NULL:2007/05/23(水) 22:39:25 ID:???
>>202, >>204
> サブクエリが使えないMySQLだったら

「全ての MySQL はサブクエリが使えない」と解釈することも可能。

特に >>202 だけ読むと、サブクエリを使う例の後に書いてるので、
多くの人は「全ての MySQL はサブクエリが使えない (と >>202
思っている)」と解釈すると思う。

「サブクエリの使えないバージョン (の MySQL) なら」と書けば
意図がより明確になる。

そもそも、>>202 でわざわざサブクエリ使う意味がないし。
207202:2007/05/23(水) 23:16:06 ID:???
最初に断っとくが、>>205は俺じゃないからな。

>>206
確かに「バージョン」と書けばよかったが、>>201はMySQLを勉強...と断っているので、
「全てのMySQLはサブクエリが使えない」とはとらんだろう。少なくとも元質の人は。

個(最大値)を選択するのに、ベンダーに依存するLIMITクエリは、このスレ的に面白くないじゃん。
208NAME IS NULL:2007/05/23(水) 23:30:25 ID:???
そもそもMySQLでサブクエリ使えるようになったって誰でも知ってることだろ……
209NAME IS NULL:2007/05/24(木) 11:15:02 ID:???
うちの仕事先は3.23さ……orz
210NAME IS NULL:2007/05/24(木) 20:51:30 ID:???
仕事で使ってるDBなんて、そう頻繁にバージョンアップするもんでもないけどな
211NAME IS NULL:2007/05/24(木) 22:57:09 ID:???
>>210
運用してるDBはそうだな。
開発用ならあっちこっちにいろんなバージョンのDBが
あることの方が多いだろwww
212NAME IS NULL:2007/05/26(土) 10:24:17 ID:4biNP+cn
select
  a, b, c
from 
  tbl
where
  b = "hoge" and
  c = (select max(c) from tbl where b = "hoge")

c が大きいレコードが新しいレコードだとします。
bが"hoge"の中で一番新しいレコードを取得するのに、こういうsqlを考えたのですが、こういう書き方って普通でしょうか?
213NAME IS NULL:2007/05/26(土) 11:39:50 ID:???
having c=max(c)
214NAME IS NULL:2007/05/26(土) 21:06:17 ID:???
冠詞(The, A)を読み飛ばしてソートするSQL文をご教授くださいm(__)m

データ
The piano
A doll
the song
songs

実行結果
A doll
The piano
the song
songs
215NAME IS NULL:2007/05/26(土) 21:08:49 ID:???
冠詞(The, A)を読み飛ばしてソートするSQL文をご教授くださいm(__)m

table 'rooms'

column 'object'

songs
The piano
A doll
the song

実行結果
A doll
The piano
the song
songs
216NAME IS NULL:2007/05/26(土) 21:33:43 ID:???
Replace みたいな関数があれば、それで消してからソート、で OK
217NAME IS NULL:2007/05/26(土) 22:35:58 ID:???
>>207
> ベンダーに依存するLIMITクエリは、

> >>201はMySQLを勉強...と断っているので、

もしかして馬鹿?
218NAME IS NULL:2007/05/26(土) 22:40:48 ID:???
終わった話題を蒸し返すバカ
219NAME IS NULL:2007/05/26(土) 23:38:42 ID:???
あっ、悪い。

蒸し返されると困る人がまだいたんですね。
220NAME IS NULL:2007/05/26(土) 23:58:31 ID:???
その二つは別問題だろうが、
行間を端折らずに全て説明しなきゃわかんないのかね。
ひょっとして生粋の日本人かな。
221NAME IS NULL:2007/05/27(日) 01:22:12 ID:???
MySQLスレに行かずにわざわざここで聞いてるくらいだから
222NAME IS NULL:2007/05/27(日) 04:14:25 ID:???
MySQLスレは初心者が質問できる雰囲気では無いからなあ。
223NAME IS NULL:2007/05/27(日) 09:38:17 ID:???
>>220
> 行間を端折らずに全て説明しなきゃわかんないのかね。

へ〜、ちゃんと説明できるんだ。

じゃあ説明してみてよ。
224NAME IS NULL:2007/05/27(日) 10:34:52 ID:???
なんかうるさいのがいるな。
ここは汎用のSQLの質疑応答がメインだから、
特定の処理系にこだわることはないし、方言に気を使う場所だ。
質問者がたまたま環境を指定したからって、それでしか使えない方法を
教えなくちゃいけないなんてことはない。
225NAME IS NULL:2007/05/27(日) 10:52:01 ID:???
粘着しているのは一人だけだから放っておけよ。ただのキチガイみたいだし。
226NAME IS NULL:2007/05/27(日) 14:20:26 ID:Hm1mP6ts
シーケンス番号がプライマリにあるテーブルで
Insert時にSQLで1ずつシーケンス番号をカウントアップさせようとしています。

Insertの際にシーケンス番号の部分に
select max(シーケンス番号) +1 のように値を指定しようかと思っていますが
1つのtransaction内で複数回Insertしようとした際に
max(シーケンス番号)が2回目以降Isolationによって
どのように変わるか教えてください。

Identityとか使えればよいのですが
パッチ作業が頻繁に発生し、バルクイン、アウトを行うのですが
これによりシーケンス番号が変更されると聞いているため
Identityを使用できません。
(そもそもIdentityのあるテーブルでバルクイン、アウトをやらないものなのでしょうか?)

シーケンス番号に順序性等は必要ないのですが
バルクイン、アウトを行うためだけに、このようなことをしようとしています。

定石等があれば教えてください。



227NAME IS NULL:2007/05/27(日) 14:39:15 ID:???
そのDBMSには独立したsequenceオブジェクトはないのかい?普通はそれを使う。
228NAME IS NULL:2007/05/27(日) 15:10:09 ID:???
>>224
> 質問者がたまたま環境を指定したからって、それでしか使えない方法を
> 教えなくちゃいけないなんてことはない。

いや、俺もそんなことは問題視してないよ。

ただサブクエリ云々の言い訳として「>>201はMySQLを勉強...と断っているので、」と
言う理由あげときながら、同じレスで「ベンダーに依存するLIMITクエリは」なんて書
く奴はアフォじゃね? って思っただけ。

見事に証明してくれてありがとう。(w
229NAME IS NULL:2007/05/27(日) 16:08:41 ID:Hm1mP6ts
>>227

Identityでもsequenceでも同じことじゃん
230NAME IS NULL:2007/05/27(日) 17:17:42 ID:???
違うだろ
identity列はsequenceが自動採番される列のこと。
231NAME IS NULL:2007/05/27(日) 17:43:59 ID:???
>>226
なんか矛盾してねぇ?

順序性等は必要ないのですが
バルクイン、アウトを行うためだけに、このようなことをしようとしています。
これによりシーケンス番号が変更されると聞いているため
Identityを使用できません

232NAME IS NULL:2007/05/27(日) 18:08:58 ID:Hm1mP6ts
>>231

説明足らずでした
履歴を持つテーブルなのでプライマリーキー的にもうひとつ、かぶらない値が必要なのです。

通常履歴も管理するテーブルの場合、このように採番系のカラムをもつのは一般的ではないのでしょうか?
233NAME IS NULL:2007/05/27(日) 19:29:25 ID:???
>>216
THX!!ありがとうございました。
234NAME IS NULL:2007/05/28(月) 02:17:14 ID:trwQ1/5+
インデックスについて質問
カラムA、カラムBの複合インデックスをもっている時
WHERE カラムA = ○○
で検索した場合、インデックスは使われる?
235NAME IS NULL:2007/05/28(月) 06:47:51 ID:???
>>234
使われない
236NAME IS NULL:2007/05/28(月) 10:04:31 ID:???
>>234
普通は使われるはずだが、心配ならプランを確認。
237NAME IS NULL:2007/05/28(月) 10:36:09 ID:???
>>234
RDBMSのオプティマイザの実装に依存する。

RBOだと使われる可能性は高いと思うし、
SQLにオプティマイザヒントなんかを埋め込むことで、
特定のRDBMSならINDEXを使うようし向けることは出来る。
・・・が、すべてのRDBMSで必ず使われる保証は無いと思う。

CBOだったらいくら適切にINDEXが作成してあっても、
TABLE FULL SCANの方が低コストと判断されたら
全表走査することもある。
238NAME IS NULL:2007/05/28(月) 10:45:46 ID:???
>>232
トランザクションがロールバックしようがコミットしようが、
単純に重複しなけりゃOKって用途であれば、
俺はOracleならシーケンス使う。
他のRDBMSで自動採番系の機能が有ればそっち優先で使う。
239NAME IS NULL:2007/05/28(月) 15:52:21 ID:???
(SQL Server2005)
伝票の情報を保存するような以下のテーブルで
(伝票コード , 得意先コード , 取引区分 , 金額)
取引区分が 1 , 2 , 3 , 4 しか入らない場合
インデックス(Non-Clusterd)をつけるのは無駄なのかな?
select/Insertの比率9:1とします
Insertする時にreal分割が発生すると取引区分=1 のレコード全部にロック(ラッチ)かかる?

1.ないよりマシ
2.選択性が低いので意味なし
3.さらにロック、ラッチの観点から逆効果
240NAME IS NULL:2007/05/28(月) 20:41:18 ID:???
試しにやってみればいいじゃねーか。
不思議な質問だ。
241NAME IS NULL:2007/05/29(火) 17:58:14 ID:???
めんどいじゃん。
242NAME IS NULL:2007/05/29(火) 18:22:52 ID:???
答えるほうもめんどいわw
243NAME IS NULL:2007/05/29(火) 18:27:29 ID:???
三択まで用意してやったんだぜ?サクッと答えられる奴いないの?
244239:2007/05/29(火) 18:38:08 ID:???
お前らどんだけだよ!にわかは氏ね!
245NAME IS NULL:2007/05/29(火) 19:11:39 ID:???
試しにやってみればいいじゃねーか。
不思議な人だ。
246NAME IS NULL:2007/05/29(火) 19:34:01 ID:???
>>239
「データが極端に少ない」 or 「データが大量にある」なら、
カーディナリティ低いINDEXにどれだけ意味がある?

実際は自分が想定するデータ件数で実験して判断しろよwww
247NAME IS NULL:2007/05/29(火) 20:13:50 ID:???
>>226
>Identityとか使えればよいのですが 
>パッチ作業が頻繁に発生し、バルクイン、アウトを行うのですが 
>これによりシーケンス番号が変更されると聞いているため 
>Identityを使用できません。 
sql serverのことだったら
bcp in の時に -E オプションをつければシーケンス番号は変わらないぞよ。
248NAME IS NULL:2007/05/29(火) 23:16:27 ID:???
通常タイムスタンプは同じ値でも幅があるから一意として使えない(1秒間に複数更新があった場合)。
けれど、SQLServerのTIMESTAMPは

行が更新されるたびに更新
される、データベース内で
一意なバイナリ形式の番号。
データを追加または変更
した日時とは関係ありま
せん。
以下はTUMESTAMP の
シノニムです。
ROWVERSION

だそうだ。更新されれば自動的に値が変わる。
自明だけど、反復読み取りのチェックに使える。
249NAME IS NULL:2007/05/29(火) 23:19:57 ID:???
>>226
履歴を作る場合等、データによって同じ数値のカウンタが複数出る時は、行識別のidentifierと更に追加でカウンタ含む複合uniqueキーを使う。
例えば、
取引 id  カウンタ(defalt:0 0は最新データを意)
A  123
注)取引とカウンタで複合unique
という表Aをつくる。ここでは、取引:Aとid:123をinsert済
次に、
取引 id  コンスタント
A      0
注)id:unique,取引とコンスタントで複合unique
と取引名とid:nullとコンスタント:0のみの表Bを作りselect,insert:可 update,delete:拒否とする。
表Aをselectする場合、表Bより取引&idのwhereでコンスタントを探し該当する値がなければid=nullのときのコンスタントを選ぶ。
更新は、表Bに対し取引A,id,コンスタント+1を行う(これが履歴となる)。
仮に、+1処理させないルール無視のクライアント処理がきた場合、複合キーがぶつかってはじかれる(アプリに計算させてもACIDのために制限をかけている)。
idと複合uniqueのコンビネーションで反復読み取りのはざまに更新した場合の判別がやりやすくなる。(全カラム比較の必要なし)

このようにすれば、
>select max(シーケンス番号) +1 のように値を指定しようかと思っていますが
>1つのtransaction内で複数回Insertしようとした際に
>max(シーケンス番号)が2回目以降Isolationによって
>どのように変わるか教えてください。

のMRUの履歴max+1をidentifierとしてカウントアップさせるのではなくACIDを保持したまま安全にアプリに変数として持たせられる。
後、トリガー使う方法もあるけど(考え方としてはやりやすいけど)、選択の余地が無いのでバッチ等処理が重くなる。
この辺、前処理後処理含めてcobolのcallインターフェースは融通効くんだけどねえ、なにせRDBというかSQL・・(ry
250NAME IS NULL:2007/05/29(火) 23:33:50 ID:???
あと履歴のレプリカ作って元表と全カラムjoinしてやれば、
たちまち履歴が更新削除禁止になるなんてこともできるぜ
(連鎖更新、連鎖削除禁止)
251NAME IS NULL:2007/05/30(水) 07:44:06 ID:???
>>248
SQL Server2005ですがTimestamp列で楽観的ロックをやってます
252NAME IS NULL:2007/05/30(水) 19:16:42 ID:PlndNA/w
SQL Server2005を使用しています。
例えば500行ヒットして先頭から50行取得するSELECT文で
SELECT TOP 50 カラムA FROM T WHERE 〜 としていたのですが
このヒット数の500も一緒に取得するにはどうしたらいいのでしょうか。

試しにSELECT TOP 50 COUNT(*) カラムA FROM T WHERE 〜
としてみましたがCOUNTにはやっぱり50が入ってきます。

ただ50行全部にCOUNT値があるのでこういう場合は
切り分けて考えた方がいいのか悩んでいます。


253NAME IS NULL:2007/05/30(水) 20:58:08 ID:???
いつもロムっていましたが質問させてください。

a表
得意先コード 売上区分 売上金額  売上日
1       10    1000    2007/04/15
1       10    500     2007/05/02
2       30    2100    2007/04/28
2       13    2500    2007/05/01
3       14    3100    2007/04/10
3       25    3900    2007/04/18
4       31    4500    2007/05/15

b表
得意先コード 得意先名
1       佐藤
2       青木
3       田中
4       佐々木

c表
得意先コード 限度金額
1       10000
2       5000
3       20000
4       30000

上記3つの表から
a表の得意先コードごとに売上月で分かれた下記の様な集計表を作成したいのですが
途中でつまずいてしまいました。
どのようなSQL文を書いたら良いのか教えていただけないでしょうか。
RDBMSはOracle9.2を使用しています。
よろしくお願いします。

得意先コード 得意先名 合計売上金額 前月売上金額 今月売上金額 限度金額
1       佐藤   1500     1000     500      10000
2       青木   4600     2100     2500     5000
3       田中   7000     7000     0       20000
4       佐々木  4500     0       4500     30000
254NAME IS NULL:2007/05/30(水) 21:00:34 ID:???
>>252
select ごにょごにょ into #temp from table_a where ごにょごにょ (500行分)

select top 50 ごにょごにょ, count = (select count(*) from #temp) from #temp

もしくは .NETなら
select top 50 ごにょ from table_a where ごにょ
select count(*) from table_a where ごにょ
で dataadapter.fill(dataset) とすれば
dataset.table(0) に1つ目, table(1)に2つ目が入る
255NAME IS NULL:2007/05/30(水) 21:07:45 ID:???
>>253
けっこう面倒そうだけど
合計売上額は先々月のデータとかあったら足していいのけ?

まずa表から月別の売上作ってみたら?
256NAME IS NULL:2007/05/30(水) 21:20:47 ID:Mj0ff4uQ
>>255
さっそくありがとうございます。
先月までの累積金額と今月分のを集計したいので足して集計させたいです。

a表から先月までの分と今月分のを作成するのはできると思います。

select 得意先コード, sum(売上金額) as 売上金額
from a表
where 売上日 < '2007/05/01' ←ここを変えて2回処理します
group by 得意先コード;

先月までの分と今月分とb表、c表を結合するには(+)とか使えばいいのでしょうか。
よろしくお願いします。
257NAME IS NULL:2007/05/30(水) 21:45:04 ID:???
>>256
>ここを変えて2回処理します
月別でグループ化して一時表作ったら1回で済むんじゃ?

select 得意先コード, 年月 = cast( replace(売上日,'/','') as int)
,sum(売上金額) as 売上金額
into #temp from a表
where 売上日 < '2007/05/01' 
group by 得意先コード , cast( replace(売上日,'/','') as int)

累積
select 得意先コード , 累積 = sum(売上金額) from #temp group by 得意先コード

先月
select 得意先コード , 累積 = 売上金額 from #temp where 年月 = 200704

今月
select 得意先コード , 累積 = 売上金額 from #temp where 年月 = 200705

ここまで出来たらあとはjoinするだけ
ああ最初のcastはoracleでは使えないかもしれないから変えてね
258NAME IS NULL:2007/06/02(土) 13:34:23 ID:???

id   name_col
1    name_1
2    name_2
3    name_3
4    name_4
5    name_5

name_col の name_ を title_ に置換して

id   name_col
1    title_1
2    title_2
3    title_3
4    title_4
5    title_5

とするにはどうすればいいですか?
259NAME IS NULL:2007/06/02(土) 16:46:18 ID:???
replace(name_col,'name_','title_')
260NAME IS NULL:2007/06/02(土) 18:52:09 ID:F7i5c8na
すんません

GROUP BY と COUNT(*)を使ったクエリで
COUNT(*)が 0 になる場合も 0 を出力してもらう方法ってありませんか?
261NAME IS NULL:2007/06/02(土) 19:28:25 ID:???
col1
----
A
B
D
B

っていうテーブルがあったとして、

col1 count(*)
---- --------
A   1
B   2
C   0
D   1
E   0
・・・
Z   0

にして欲しいってこと?

無理だろ。
262NAME IS NULL:2007/06/02(土) 19:49:43 ID:???
A-Zだけじゃないでしょ
全ての文字列の組み合わせで、0件の出力しなくちゃ
263NAME IS NULL:2007/06/02(土) 20:03:01 ID:???
集計キーのマスタを用意すれば
外部結合とcoalesceで実現出来ると思う
264NAME IS NULL:2007/06/03(日) 01:50:06 ID:???
>261
そうそう
まぁ普通に無理っすね……

>263
別テーブルと結合って考えたんですけど
めんどくさいっすね……

--
ありがとうございました
265NAME IS NULL:2007/06/03(日) 16:50:29 ID:mw/dDSFg

Postgreでmemberの住所(address)が埼玉、群馬の女子(f)の人数を調べようと思うのですが
どのようなSQLを書いたらよいでしょう?

結果は
-------------
埼玉 50
群馬 30
-------------
のように表示させたいのですが、

select address ,count(*) from member where (address = '埼玉' or address '群馬') and (sex = 'f');

ではダメですか?
266NAME IS NULL:2007/06/03(日) 17:25:20 ID:???
>>265
group by
267NAME IS NULL:2007/06/04(月) 18:37:01 ID:???
>>257

257様 お力添えありがとうございます。
お教えいただいた方法で色々試してみました。
(1)と(2)で一時表(c表)を作成し(3)でd表に集計しようと考えてみましたが、
(3)のSQLを実行すると「ORA-00979 GROUP BYの式ではありません」とエラーとなってしまいます。
どのようなSQLを組んで良いのか…もう一度皆様のお力を貸していただけないでしょうか。
よろしくお願いします。


(1)
insert into c表
select 得意先コード,sum(売上金額) as 売上金額4,sum(0) as 売上金額5
from a表
where 売上日 <= '2007/04/30'
having sum(売上金額) != 0
gropu by 得意先コード

(2)
insert into c表
select 得意先コード,sum(0) as 売上金額4,sum(売上金額) as 売上金額5
from a表
where 売上日 > '2007/04/30'
having sum(売上金額) != 0
gropu by 得意先コード

(3)
insert into d表
select d表.得意先コード,b表.得意先名,c表.限度金額,sum(d表.売上金額4) as 売上金額4,
sum(d表.売上金額5) as 売上金額5
from b表,c表,d表
where d表.得意先コード = b表.得意先コード (+)
and d表.得意先コード = c表.得意先コード (+)
group by d表.得意先コード
268NAME IS NULL:2007/06/04(月) 18:41:38 ID:???
>>267


申し訳ありません。
間違ったSQLを貼り付けてしまいました。
こちらが実行したSQLです。

(1)
insert into d表
select 得意先コード,sum(売上金額) as 売上金額4,sum(0) as 売上金額5
from a表
where 売上日 <= '2007/04/30'
having sum(売上金額) != 0
gropu by 得意先コード

(2)
insert into d表
select 得意先コード,sum(0) as 売上金額4,sum(売上金額) as 売上金額5
from a表
where 売上日 > '2007/04/30'
having sum(売上金額) != 0
gropu by 得意先コード

(3)
insert into e表
select d表.得意先コード,b表.得意先名,c表.限度金額,sum(d表.売上金額4) as 売上金額4,
sum(d表.売上金額5) as 売上金額5
from b表,c表,d表
where d表.得意先コード = b表.得意先コード (+)
and d表.得意先コード = c表.得意先コード (+)
group by d表.得意先コード
269NAME IS NULL:2007/06/04(月) 19:59:56 ID:???
最近の Oracle は GROUP BY の前に HAVING 使えるのか?
まぁ普通に逆に書いてると予想。
270NAME IS NULL:2007/06/04(月) 20:24:35 ID:???
>>269

ありがとうございます。
(1)と(2)を単独に実行しても正常に通りますが、
ご指摘のとおりHAVINGの使い方をGROUP BYの後に書くよう改めます。

(3)ですが3つの表から1つにまとめたいのですが、
皆さんならどのように書かれますか?
271NAME IS NULL:2007/06/04(月) 20:43:46 ID:???
>>270
あんま読んでないけど
group by d表.得意先コード,b表.得意先名,c表.限度金額
じゃないのけ?
272NAME IS NULL:2007/06/04(月) 20:59:54 ID:???
>>271

271様
お教えいただいたとおり修正しましたら動きました!!
ありがとうございました。
まだまだ勉強不足だと痛感しています…。
273NAME IS NULL:2007/06/05(火) 01:28:00 ID:???
以下のようなテーブルがあって、ある指定された1つ以上のタグ全て含むfavorite_idを選択したいです。
例)SQLとC++が指定されたら、1と3が返ってくる
以下のようなSQLを考えたのですが、もっと良い書き方とか定番の書き方があれば教えてください。
SQLite使ってます。

SELECT favorite_id FROM fav_tag, tag
WHERE fav_tag.tag_id = tag.tag_id
  AND (tag.text = 'SQL' OR tag.text = 'C++')
GROUP BY fav_tag.favorite_id
HAVING COUNT(fav_tag.favorite_id) = 2;


テーブル名:fav_tag
favorite_id    tag_id
====================
1            3
1            4
1            6
1            7
2            13
2            15
2            21
3            3
3            4
3            13
4            4
5            31

・・・

テーブル名:tag
tag_id    text
====================
3        SQL
4        C++
6        HTTP
7        JAVA
13       DB
・・・
274NAME IS NULL:2007/06/05(火) 01:43:56 ID:PQi92ZZ4
どなたかご知見がありましたらご教授ください。

現在下記のような、selectした結果をそのまま
insertするsqlを組んでいるのですが、SQL内に計算式が含まれる為か
かなり処理速度が遅い状態です。
実際はinsert項目はもっと大量にあり、
かつ選択条件もキーだけではなく
like条件も含むやや複雑なものを使用しています。


INSERT INTO 表4
SELECT
ROUND(SUM(C.商品1単価 * B.商品の重量) / SUM(B.商品の重量),3),
ROUND(SUM(C.商品2単価 * B.商品の重量) / SUM(B.商品の重量),3),
ROUND(SUM(C.商品3単価 * B.商品の重量) / SUM(B.商品の重量),3),
ROUND(SUM(C.商品4単価 * B.商品の重量) / SUM(B.商品の重量),3),

ROUND(SUM(C.商品5単価 * B.商品の重量) / SUM(B.商品の重量),3) +
ROUND(SUM(C.商品6単価 * B.商品の重量) / SUM(B.商品の重量),3),

SUM(B.商品の重量)

FROM 表A,表B,表C

WHERE

A.キー1 = B.キー1 AND
B.キー2 = C.キー2 AND
(A.対象期間 >= '2006/04/01' AND A.対象期間 <= '2007/03/31')

この場合、一気に処理をしようとしないで、
カーソルで1行づつそれぞれの単価及び重量を取得して
どんどん足しこむ計算をプログラム内で用意し、集計した結果をinsertしたほうが
処理的にやはり早いのでしょうか?

もしくは各表毎に検索処理自体も分けて
検索も極力キーのみを使用するようにしたほうが
結果として早くなるのでしょうか?

insert対象が3000件ほどあるのですが
登録に1時間以上かかっております・・・。
275NAME IS NULL:2007/06/05(火) 05:23:15 ID:???
>>274
それはもう実行計画見ろとしかいいようがないな
276NAME IS NULL:2007/06/05(火) 11:31:24 ID:???
>>273
ほとんど変わんないけどちょっと手直し (入力データ流し込みやすいように)
SELECT favorite_id FROM fav_tag INNER JOIN tag using(tag_id)
WHERE tag.text IN ('SQL','C++')
GROUP BY favorite_id
HAVING COUNT(*) = (SELECT COUNT(*) FROM tag WHERE tag.text IN ('SQL','C++'))


それと相関サブクエリ使うやり方
SELECT DISTINCT favorite_id FROM fav_tag fav1
WHERE NOT EXISTS
(SELECT tag.tag_id FROM tag WHERE tag.text IN ('SQL','C++')
EXCEPT SELECT fav2.tag_id FROM fav_tag fav2
WHERE fav2.favorite_id = fav1.favorite_id);

どっちがパフォーマンス良いかは知らないので
実験して好きな方使ってくれ。

参考
ttp://codezine.jp/a/article/aid/1304.aspx?p=2
277273:2007/06/06(水) 00:56:27 ID:???
>>276
まだSQLに慣れてないので、別のやり方を挙げて頂けたのは勉強になり助かります。
ありがとうございました。
278NAME IS NULL:2007/06/06(水) 23:08:37 ID:GDaT0Jkl

学年 学籍番号 点数
1    0001    60
1    0002    80
2    0003    90
2    0004    20

このような表からそれぞれの学年ごとに、A(80〜100点の人数)、
B(70〜80点の人数) C(60〜70点の人数) D(0〜60点の人数)を
表にするにはどうしたらよいでしょうか?

学年 A  B  C  D
1   10  15  8  9
2   11  22  2  3
3   13  9  3  10

よろしくお願いします。
279NAME IS NULL:2007/06/07(木) 01:40:24 ID:???
>>278
SELECT 学年,
SUM(CASE WHEN 点数>=80 THEN 1 ELSE 0 END) AS A,
SUM(CASE WHEN 点数>=70 AND 点数<80 THEN 1 ELSE 0 END) AS B,
SUM(CASE WHEN 点数>=60 AND 点数<70 THEN 1 ELSE 0 END) AS C,
SUM(CASE WHEN 点数<60 THEN 1 ELSE 0 END) AS D
FROM 表 GROUP BY 学年;
280NAME IS NULL:2007/06/07(木) 21:05:56 ID:???
order by 学年 asc

をつけといた方がいいかも。
281NAME IS NULL:2007/06/08(金) 02:10:35 ID:oKxpcUps
SQLの勉強をしたいのですが無料で軽いフリーソフトがありましたら教えてください
282NAME IS NULL:2007/06/08(金) 04:28:57 ID:???
byteaで画像データを格納したいとき、画像のパスを指定して保存、は可能ですか?
283NAME IS NULL:2007/06/08(金) 07:00:28 ID:???
>>281
MySQL
SQL Server ExpressEdition
284NAME IS NULL:2007/06/08(金) 10:14:01 ID:???
SQLite
PostgreSQL
285NAME IS NULL:2007/06/08(金) 10:20:40 ID:???
>>281
FireBird
286NAME IS NULL:2007/06/08(金) 13:49:30 ID:4l/ZZkFv
SQLプログラマーの先輩様に質問があります
現在私は日本電子専門学校(情報処理科1年)で先週初めてSQLServer の授業が行われたのですがプログラムを作る際考え方がわからなくて困っています(ノ_<。)
隣にいる同級生はスラスラ解いているのに自分は教科書見て探している間に時間が過ぎてる毎日です
俺はこんな風に勉強して上手くなった 式の組合せはこう考えればいいよってことがありましたら教えてください(^人^;)
287NAME IS NULL:2007/06/08(金) 15:02:07 ID:???
DBに接続するアプリの作り方がわからないのか、SQLの書き方がわからないのかどっち?
288NAME IS NULL:2007/06/08(金) 15:14:58 ID:???
>>286
何をどうして良いのか分からないんだったら、
目的の物を得るためには
どういう順番で何をしなければならないかを
考える癖をつけた方が良いよ。

やらなければならないことを
ナンバリングしながら箇条書きにしていくだけでも、
基本的なロジックは組み上がるからね。
289NAME IS NULL:2007/06/08(金) 15:27:09 ID:???
あと、特に理由がなければ個人を特定されかねない情報は出すべきではないと思う。
エレクトロンの花とか言われるぞ。
290NAME IS NULL:2007/06/08(金) 23:35:26 ID:???
>>282
可能だろ。

君が「指定されたパスから画像を読み込んで、データベースに食わせる」ことができるなら。
291NAME IS NULL:2007/06/11(月) 14:52:31 ID:DdlgA2BI
+----------+--------+
|  DATE   | GENDER |
+----------+--------+
|2007-06-01 |  M    |
+----------+--------+
|2007-06-01 |  F    |
+----------+--------+
|2007-06-01 |  M    |
+----------+--------+
|2007-06-02 |  F    |
+----------+--------+

TOUROKUというテーブルに上記データがあるとして、
以下のように、日付毎の合計件数とMまたはFそれぞれの件数を同時に求めたいです。

+----------+------+--------+--------+
|  DATE   |COUNT|COUNT(M)|COUNT(F)|
+----------+------+--------+--------+
|2007-06-01 |  3  |   2   |   1   |
+----------+------+--------+--------+
|2007-06-02 |  1  |   0   |   1   |
+----------+------+--------+--------+

日付毎の合計を求めるだけなら
SELECT
DATE(CREATED) AS DATE,
COUNT(*) AS COUNT
FROM TOUROKU
GROUP BY DATE
;
として求められることがわかりましたが、
MとFを同時に求める方法がわかりません。
教えてください。MySQL4.2です。
292291:2007/06/11(月) 14:53:30 ID:DdlgA2BI
あ、ごめんなさい。
自分でわかったSQLは
日付毎の合計を求めるだけなら
SELECT
DATE,
COUNT(*) AS COUNT
FROM TOUROKU
GROUP BY DATE
;
でした
293NAME IS NULL:2007/06/11(月) 15:10:29 ID:???
>>291
SELECT date, count(*) AS COUNT,
(SELECT count(*) FROM Touroku WHERE gender='M' AND date=T0.date) AS COUNT_M,
(SELECT count(*) FROM Touroku WHERE gender='F' AND date=T0.date) AS COUNT_F
FROM Touroku AS T0 GROUP BY date;
294291:2007/06/11(月) 15:18:34 ID:???
>>293
ありがとうございます、できました!
なるほどこれがサブクエリーってやつなんですね。
勉強になりました。ありがとうございました。
295NAME IS NULL:2007/06/11(月) 19:49:09 ID:u6t10WUz
C#でOracleに接続してSQLの構文を書いてるのですが、ListBoxの選択されたアイテム
をWhereで抽出したいのですが、どのように書いてみたらいいですかね?
296NAME IS NULL:2007/06/11(月) 20:11:18 ID:???
>>295
in
297NAME IS NULL:2007/06/11(月) 23:55:58 ID:???
>>279
できました。
ありがとうございました。
298295:2007/06/12(火) 16:12:20 ID:pwv6P776
inを使って構文を書いたのですが、上手くいかず・・・具体的にどんな感じに
書いたらいいでしょうか?
299NAME IS NULL:2007/06/12(火) 16:28:08 ID:???
うまくいかなかった時のSQLを書いてよ

WHERE xxx IN (1,2,3,4,5)

とか
300295:2007/06/12(火) 17:10:51 ID:pwv6P776
WHERE xxx IN(' + listbox + ')
このような形で書いたのですが、上手くいかず。。。
301NAME IS NULL:2007/06/12(火) 17:33:31 ID:???
>>300
listboxの中身をちゃんと展開して、
>>299みたいなカンマ区切りの文字列にしろよ。
302295:2007/06/12(火) 17:40:22 ID:pwv6P776
listboxの中身を展開ってどうやればいいんですか?
303NAME IS NULL:2007/06/12(火) 18:42:35 ID:???
いや、最初っからSQLの話じゃなくてC#の話じゃねぇの。
聞くスレ間違っているよ。

SelectionModeがOneなら、
this.listBox1.SelectedItemで取り出せるんだから、
それをDbParameterかなにかで突っ込めばいいだろ。
マルチならthis.listBox1.SelectedItemsを展開連結なり何なりと。

>>300のやり方を見ると

WHERE xxx = ’" + listBox1.SelectedItem.ToString() + "'";
としたいのか。それでもいいが、
普通はDbParameter経由で押し込むべきだろう。

なんにせ、板違いのスレ違い。
304NAME IS NULL:2007/06/13(水) 01:14:47 ID:???
oracle 9

テーブル4つを共通キーで外部結合し、
他の項目をとってきてデータ出力したいが その際件数が合わない
おおよそこんな形

select t1.key1, t2.item1, t3.item1,t4.item1
from t1,t2,t3,t4
where t2.key1 = t1.key1
and t3.key1 = t1.key1
and t4.key1 = t1.key1

これだとキー以外の項目の組み合わせ分件数が膨れて出てくる
SQLで楽に以下のように出せる方法あるでしょうか?
(pl/sql等が妥当なのか?)

t1.key1, t2.item1 t3.item1 t4.item1
1 1 1 1
2 2
3
2 1 1 1
2 2
3
3 1
4 1

※テーブルの定義
table colum
t1 key1
t2 key1,item1
t3 key1,item1
t4 key1,item1
305NAME IS NULL:2007/06/13(水) 01:20:21 ID:???
例えるのが難しいんだけれど、DBを作った掲示板のようなシステムを作ったとして、

あるスレッドのデータだけを取り出せるシステムを組みたい場合のテーブル設計として、
スレッド別にテーブルを新規作成してFROM句を変えるものと、
1つのテーブル内でスレッドID列みたいなものを作って、WHERE区で判別して抽出する方法がありますが、

どちらの方がいい、とかあるんでしょうか?
ぽんぽんとテーブルを新規作成するのはマズイような気もするのですが、その根拠も分からないので迷っています。
306NAME IS NULL:2007/06/13(水) 01:22:17 ID:???
リストのイメージ訂正

t1.key1, t2.item1 t3.item1 t4.item1 |
--------------------------------------
1 1 1 1 |
2 2 |
3 |
2 1 1 1 |
2 2 |
3 |
3 1 |
4 1 |
307NAME IS NULL:2007/06/13(水) 04:36:38 ID:???
データマイニングって何か役に立ってるの?
308NAME IS NULL:2007/06/13(水) 07:48:13 ID:???
>>305
スレッド別に扱うデータ項目が異ならない限りは、
スレッド別にテーブル作る設計なんてあり得ないだろ。
309NAME IS NULL:2007/06/13(水) 18:34:40 ID:FlP9jY9L
>>305
スレッド死んだ時とか考えるのヤだなぁ、と思った俺は違うスレッドを想像していた模様なのはおいといて・・・

「効率いいだろうけど管理メンドクサイじゃん。テーブル10000ヶとか出てきたら俺逃げるぜ?」ってジレンマは
どうやら皆持ってたようで、SQL鯖2005では
「一つのテーブルだけどユーザ定義の関数に合わせて複数の実データ構造に分けて格納します。
クエリ次第では効率アップするかもよ?」
ってな不思議な仕組みが導入されています。勉強して使いこなしてください。正直、名前忘れたけど。

Oracleは不勉強につき勘弁。
310NAME IS NULL:2007/06/13(水) 22:09:32 ID:???
>>304
膨れた結果から不要なものを除外する条件を追加すれ
311305:2007/06/14(木) 07:24:47 ID:???
>>309
FROM句を変えるだけの手軽さや、他のスレッドデータも1テーブル内に混在するという怖さばかり見てて、
「テーブル10000ヶとか出てきたら」というのを余り深く考えてませんでした。
確かに逃げたくなりますね・・・

それを考慮し、SQLサーバーなどが機能面でサポートしようとしていることも知れ、勉強になりました。
ありがとうございました。
312NAME IS NULL:2007/06/14(木) 08:44:21 ID:???
>>309
Oracleならパーティショニングオプションと、
パラレルクエリーで、ってことになるだろうな。
313NAME IS NULL:2007/06/14(木) 10:39:31 ID:???
10000どころか、2つだってありえない
314NAME IS NULL:2007/06/14(木) 17:05:49 ID:???
カーソル定義で結合を行った場合でもSELECT FOR UPDATEで更新可能ですか?
Oracle10gです。

TBL01のPKがA,B
TBL02のPKがA,B,C

DECLARE CURSOR CUR IS SELECT * FROM TBL01 JOIN TBL02 USING(A,B)

に対して、FOR UPDATE文を指定してTBL02を更新出来るか教えて頂けませんか。
315NAME IS NULL:2007/06/14(木) 17:31:13 ID:???
>>314
何故、試さない?
316NAME IS NULL:2007/06/14(木) 18:05:01 ID:???
設計Phaseで試せる環境が無い ('A`
Accessならあるんだけど。
317NAME IS NULL:2007/06/14(木) 19:16:38 ID:???
>>316
OTNから試用版ダウンロードできるだろうに。
318NAME IS NULL:2007/06/15(金) 03:26:54 ID:???
>>304
マニュアル見てfull joinのネストかな?と思ってやってみたが
onの記述でわけわからん。テンプレみたら あったな。
やり方3つもあるの?へえ〜。
たすかったよ

http://oraclesqlpuzzle.hp.infoseek.co.jp/7-36.html

いやここすごいね。使えるわ。
319NAME IS NULL:2007/06/15(金) 09:55:52 ID:???
テーブルAとテーブルBがあって、テーブルBの主キーはテーブルAの
主キー+レコード適用日となっています。

日付を指定してレコードを検索した場合に、指定日≧適用開始日ならBから、
そうじゃないならAからレコードを取得したいのですが、これを一つのSQLで
実現する方法はないでしょううか?

なお、テーブルBには、適用日以外のキーが重複するレコードが複数います。

テーブルA
(1) ID=01, 〜

テーブルB
(2) ID=01, 適用日=6/20, 〜
(3) ID=01, 適用日=7/01, 〜

日付=7/15を指定した場合は(3)のレコードを取得したい。6/01を指定した
場合は(1)のレコードを取得したい。
320NAME IS NULL:2007/06/15(金) 10:16:52 ID:???
>>319
AとBを結合して、CASE式で場合分け出来そうな希ガス。
321NAME IS NULL:2007/06/15(金) 12:23:21 ID:???
多分Aを加工しBと同列でユニオンかな
322NAME IS NULL:2007/06/15(金) 13:04:48 ID:???
Aの加工って?
323NAME IS NULL:2007/06/15(金) 13:19:23 ID:???
>>322
システム日付でも固定値でも何でも良いから、
適用日の値を返すようなSQLで、
Aに対してSELECT書けば良いんだと思うが。

で、その結果とBのSELECTをUNIONして・・・
ってことだとオモ。
324NAME IS NULL:2007/06/15(金) 14:25:19 ID:???
いや、そうやってA'を細工したとしても

1) ID=1、適用日=0000/1/1、〜 (A'。Aに対して適当な固定日を付与)
2) ID=1、適用日=6/20、〜   (B)
3) ID=1、適用日=7/1、〜   (B)

の3行に対して、例えば日付=6/25を指定したときに(2)を取得すンのは
難しいのでは?

って、TBL設計の話になっちゃうけど、こういうのって普通適用開始日と
終了日の両方持つのが一般的のような。
325NAME IS NULL:2007/06/15(金) 14:39:18 ID:???
>>324
その場合どうなるべきか、ってのは
質問者の意図を推測するしかないが、
その例ではB表に7/1があるから、
指定日が6/25なら7/1のデータが
取得されないと不味いんじゃないか?
あるいはB表には6/25のデータがある、
ということなのかもしれん。

どっちにせよ、俺には>>319のデータ構造なら
A/Bの2表が有ること自体、変に思うんだが。
A表の履歴ログだ、ってことにしたって、
適用日が毎日ってならともかく、ある程度の間隔があるなら
お前さんの言うようにFrom〜Toで日付持たせてた方が
2次利用が楽なように思うしな。
326325:2007/06/15(金) 14:42:37 ID:???
あぁ、指定日≧適用開始日だったか。

だとしたらお前さんの言うとおり、
> 1) ID=1、適用日=0000/1/1、〜 (A'。Aに対して適当な固定日を付与) 
> 2) ID=1、適用日=6/20、〜   (B) 
> 3) ID=1、適用日=7/1、〜   (B) 

> の3行に対して、例えば日付=6/25を指定したときに(2)を取得
ってことだなぁ。
スマソ
327NAME IS NULL:2007/06/15(金) 16:04:36 ID:???
select tbl_A.ID, coalesce(tbl_B.col1,tbl_A.col1), coalesce(tbl_B.適用日,'---')
from tbl_A left join tbl_B on (tbl_A.ID = tbl_B.ID and tbl_B.適用日 <= 指定日)
where tbl_B.適用日 is Null or tbl_B.適用日=
(select max(subB.適用日) from tbl_B subB
where subB.ID=tbl_A.ID and subB.適用日 <= 指定日);

これで
tbl_A (ID, col1)
1, aaa
2, bbb
3, ccc

tbl_B (ID, col1, 適用日)
1, aaa1, 2007/06/20
1, aaa2, 2007/07/01
2, bbb1, 2007/05/22
2, bbb2, 2007/06/30
2, bbb3, 2007/07/01
3, ccc1, 2007/07/01

から、指定日=2007/06/30で
1, aaa1, 2007/06/20
2, bbb2, 2007/06/30
3, ccc, ---
と出るけどこういうことでよいのかな?

>適用日以外の"キーが重複するレコードが複数"います
ってのが意味わかんないので〜の所に何入ってるのかよくわからん。
328NAME IS NULL:2007/06/15(金) 17:50:58 ID:???
>>327
推測だが、例えば会社マスタ_カレントと会社マスタ_予約があって

会社マスタ_カレント:
会社CD=01、会社名=▲▲▲▲▲

会社マスタ_予約:
会社CD=01、適用日=6/1、会社名=▽▽▽▽▽
会社CD=01、適用日=7/1、会社名=■■■■■
会社CD=01、適用日=9/4、会社名=○○○○○

てなってて、日付=6/20でマスタを取得すると、"▽▽▽▽▽" が欲しい、て
ことなんジャマイカ?
329NAME IS NULL:2007/06/16(土) 00:49:00 ID:???
>>319
SELECT top 1 * FROM
(SELECT 名称 FROM TableA A
WHERE ID = 指定キー AND 適用年月日 <= 指定日
UNION ALL
SELECT 名称 FROM TableB B
WHERE ID = 指定キー
)
こんな感じか?
330NAME IS NULL:2007/06/16(土) 10:23:23 ID:???
A ORDER BY 適用年月日 DESC
ああしもた。いるなあ
331NAME IS NULL:2007/06/16(土) 10:59:56 ID:???
>>329
DESCでnullは最初になるんだっけ?最後になるんだっけ?

標準的なSQLで正攻法ならこうだな。

select ID, null from A
where A.ID=指定キー
and not exists (
select * from B B0
where B0.ID=指定キー
and B0.適用年月日<=指定日
)
union all
select ID, 適用年月日 from B
where B.ID=指定キー
and B.適用年月日<=指定日
and not exists (
select * from B1
where B1.ID=B.ID
and B1.適用年月日>B.適用年月日 )
332NAME IS NULL:2007/06/16(土) 16:51:29 ID:???
>>331
そのSQLは流石にあかんやろ。。。
333NAME IS NULL:2007/06/16(土) 22:43:56 ID:???
ん?なんかおかしいところあった?
環境の違いによらずに安定したパフォーマンスが出るよう書いたつもりだけどね。
334NAME IS NULL:2007/06/16(土) 23:01:09 ID:???
全然関係ないけどぉ、最近のOracleはSQLが拡張されまくってて便利つーか
ワケワカランつーか、全然追いつけない。

>319 の質問も、例えば環境を最新のOracle(10G?)に限定すればなんか使える
独自機能ないかなぁとオモテ調べてみたけど2分で挫折
335NAME IS NULL:2007/06/17(日) 11:04:55 ID:???
>>333
問題ないと思うよ
336NAME IS NULL:2007/06/17(日) 13:18:07 ID:???
>>333
>>335

下のほうのBテーブルから取ってくるところの
existsの中が間違ってるだろ。
指定する日付がBテーブルに存在する全ての適応日より
大きいなら欲しい結果が返ってくるけどね。
337NAME IS NULL:2007/06/17(日) 19:42:29 ID:???
>>336
あ、なるほど。

and B1.適用年月日<=指定日

が抜けてたってだけか。
338NAME IS NULL:2007/06/18(月) 15:35:48 ID:???
329と331って、なんとなく感覚的に331のほうがコスト高い気がするけど。
top nはsqlserver?oracleだと329をさらにselectで括ってrownum=1で抽出
か。sqlserverがあればサックリコスト見れるんだけど。
339NAME IS NULL:2007/06/18(月) 22:19:39 ID:???
あぁもう効率考えるの鬱陶しいから1時間に1回バッチ処理しちまえっ。お前ら10分間待てっ。
バッチ処理中の処理要請?そんなのキューに10分だけ溜めとけっ。
後でエラーは返送するから再入力よろしくっ。

…って、全部キューに溜め込んだ方が単純でいい?
…あれ?それぐらいCOBOLで30年前からできてる?
…え?FTPで都度転送するだけで仕様満たしちゃう?

嗚呼、汎用機万歳orz
340NAME IS NULL:2007/06/18(月) 23:33:04 ID:???
まあ、unionとか使い出すとCOBOLやらRPGの方が性能出るだろうなぁ。
341NAME IS NULL:2007/06/18(月) 23:37:57 ID:n2nHvTvM
SQLで、ある行の前後のデータをとってくるうまい方法はありますか。
たとえば
select id from blog_table where date = '2007-01-01';
というSQLを実行して id = 123 という結果が得られたとします。
そして、
select * from blog_table order by date;
というSQLを使って、dateで全データをソートしたうえで、id = 123 である行の前後の行をとってきたいのです。
今はうまい方法が思い浮かばないので、SQLだけでなくRubyとかを使って
list = execute('select * from blog_table order by date') # 全部とってくる
i = list.each_with_index { |v, i| break i if v == 123 } # データのindexを見つける
prev_data = list[i-1] # 前の行
next_data = list[i+1] # 次の行
としているのですが、どう考えても無駄すぎるので、うまい方法があれば教えてください。
342NAME IS NULL:2007/06/19(火) 00:55:13 ID:???
>>341
dateは一意?
343NAME IS NULL:2007/06/19(火) 01:37:37 ID:???
同じ値が無けりゃ、未満で最大とより大きい最小をもってくりゃいいな
344NAME IS NULL:2007/06/19(火) 01:51:23 ID:???
table名から察するにdateがdate型なら一意じゃなさそう。
dateが一意じゃなく複数ある場合、その順序は概ね一定になるが保証されているわけじゃない。

ブログの<link rel="next">と<link rel="prev">の分を抽出したいのなら、
記事毎にインクリメント(歯抜けあり)されているであろうidを使った方が早くね。

WHERE id = (SELECT max(id) FROM blog_table WHERE id < 123)
OR id = (SELECT min(id) FROM blog_table WHERE id > 123);

dateが一意なら上に挙げたSQL文のidをdateに変更すればおk。

まぁidが必ずしもdate順に並んでいない場合もあるだろうから、厳密にしたいのなら
min(date)で取り出した複数行の中からmin(id)を選ぶとか。
SQLで一発抽出も可能だが、DBのなかに記事はあるけど未公開になってる
とか、その他いろいろな条件も増えてWHEREが無駄に複雑になるから、
SQLである程度絞り込んだら、ホスト言語(Ruby)側で処理させる方が楽っぽ。
345NAME IS NULL:2007/06/19(火) 16:06:08 ID:nZn4pPC5
数値をカンマ区切りにしたいんですけど、できますか?
346NAME IS NULL:2007/06/19(火) 16:13:01 ID:???
to_char(num, '999,999,999');
とかでどうか
347NAME IS NULL:2007/06/19(火) 18:41:50 ID:JyFlQMM7
月の検索ってどうやったら良いですか?
「誕生日の近い人一覧」を表示したいのですが、
データベースに「1982-12-01」(データ型は日付)で入っていて、
年を無視して月のみで検索できずに悩んでます。
348NAME IS NULL:2007/06/19(火) 18:51:20 ID:???
>>347
where Month(日付)  = ?
Month()は日付から月だけを抜き出す関数の意味。標準じゃないから各DBMSのマニュアルで調べる。
ただし、この方法では日付に索引があってもつかわれないから、
頻繁にこの問い合わせをする必要があるなら、
別に月だけのフィールドをテーブルに追加して索引を作っておく。
349NAME IS NULL:2007/06/19(火) 18:54:42 ID:???
where to_char(hiduke, 'MM') = '01'
とか。

>>348も書いてるけどこのままじゃインデックスが使えないので
to_char(hiduke, 'MM') に対してインデックスを張るとか工夫が必要。
350NAME IS NULL:2007/06/19(火) 19:06:19 ID:???
日付関係はDBMSで違っていてほとんど統一が取れてないから
DBの種類は書いといたほうがいい。
351NAME IS NULL:2007/06/19(火) 19:30:02 ID:???
「誕生日に近い人」なら月よりも、その年の通算日数の方がよくね?
EXTRACT(DOY FROM 誕生日) 又は date_part('doy',誕生日);
月末基準で調べても、翌月初旬の日を出てくるし。

ex.) 誕生日が10日以内の人
SELECT * FROM Table
WHERE EXTRACT(DOY FROM 誕生日) - EXTRACT(DOY FROM CURRENT_TIMESTAMP)
BETWEEN 0 AND 10;
352347:2007/06/20(水) 11:01:23 ID:???
たくさんの回答に感謝です。
とても参考になりました。
ありがとうございます。
やり方もたくさんあるのですね。
決まった形が無いみたいで、自分みたいな初心者には、とても難しく感じますが、
がんばろうと思います。
お返事、遅れてしまい申し訳ありませんでした。


>>351
いわれて見るまで、気がつかなかったです。
そうですね。月末の事を考えると、この形式がベストみたい。
ありがとうございます。
 
>>350
DBは、postogresu使用です。
教えていただいたSQLが通ったので、よかったですが、
次回からはDBの種類も記入することにします。
ご指摘、ありがとうございます。

>>348,349
「インデックスを張る」ですか。
うーん。ちょっと難しそうなのと、>>351の方法で解決したので今回はなしで行きたいと思います。
インデックスについて、また調べてみますね。
勉強になりました。ありがとうございます。
353351:2007/06/20(水) 19:30:41 ID:???
>>352
postogresuってなんだよー。
まぁ俺も怪しい日本語が混じってたが。

で、インデックスを無視していたのでちょっと老婆心的補足。
誕生日通算日数の関数インデックスを作って、
CREATE INDEX birthday_doy_idx FROM Table(EXTRACT(DOY FROM 誕生日));

>>351で書いたSQLをちょっと変更。
SELECT * FROM Table
WHERE EXTRACT(DOY FROM 誕生日)
BETWEEN EXTRACT(DOY FROM CURRENT_TIMESTAMP)
AND EXTRACT(DOY FROM CURRENT_TIMESTAMP)+10;

とすれば、インデックスを使って抽出するようになる。
--元質の人はもう見てないだろうけどなぁ。
354NAME IS NULL:2007/06/21(木) 23:42:17 ID:???
SELECT TbmSection.SectionID, TbmSection.SectionCode, TbmSection.SectionName
FROM TbmSection INNER JOIN
( SELECT SectionID FROM TbmAssignSection WHERE DeleteFlg = 0
UNION
SELECT SectionID FROM TbmSectionExecutive WHERE EmployeeID = '000000' )
test_tbl ON test_tbl.SectionID = TbmSection.SectionID
WHERE TbmSection.DeleteFlg = 0

このようなSQL文を実行するとします。
下から二行目にUNIONで結合させたテーブル名にtest_tblと別名をつけていますが、
これを別名をつけずに実行しようとするとエラーになるのです。
実行環境はEnterprise Managerです。
ちなみに、別名をつけずに実行すると、Enterprise Managerが別名(test_tbl)があった
位置に勝手にDERIVEDTBLを付けてそれもまたエラーになってしまいます。

'これがその例です↓
DERIVEDTBL ON TbmAssignSection.SectionID = TbmSection.SectionID

長々と若干意味不明に書いてしまいましたが、要はtest_tblという別名を付けずに冒頭
のSQL文を正常に動作させたいのですが、なんとかならないものなのでしょうか?
テーブル定義書も無い中、解答が得られるとは考えにくいのですがわかる方いらっしゃった
らぜひお願いします。
355NAME IS NULL:2007/06/21(木) 23:47:04 ID:T2K/E1DB
現在学校でSQL Server の勉強をやってるんですが自宅でも勉強したいのですが無料で軽いフリーソフトがありましたら教えてください
356NAME IS NULL:2007/06/22(金) 00:00:10 ID:???
357355の者です:2007/06/22(金) 00:14:12 ID:Jkf5KiTi
先週ヤフオクでSQLの参考書(やさしいSQL入門)というのを購入したんですが
内容がSQL Serverのことが全然書かれてなかったので別の参考書を購入しようかと検討中なんですがお勧めの参考書ってありませんか?
問題と説明が詳しく書かれているのがありましたら教えてください
358NAME IS NULL:2007/06/22(金) 06:35:51 ID:???
>>357
普通にDBマガジンとかWEB+DBPRESSとか雑誌を買えよ。
359NAME IS NULL:2007/06/22(金) 06:48:27 ID:???
>>357
技術本、参考書のたぐいは
自分に合う合わないが有るから
本屋で立ち読み汁。
360NAME IS NULL:2007/06/22(金) 09:25:33 ID:???
>>358
そういう雑誌って初心者が見ても楽しめますかね?
361NAME IS NULL:2007/06/22(金) 11:14:57 ID:???
むしろ初心者向け情報が中心という気もする。
初心者と言わないでも、DB屋さん以外のPGとかが本棚に置いとくくらいには。

あと、定期的(毎年3〜4月号あたりかな?)に、初心者向け特集をやる技術系雑誌は多いと思う。
362NAME IS NULL:2007/06/22(金) 11:49:37 ID:???
>>361
ありがとうです。大学の図書館にあるか見てきますノシ
363NAME IS NULL:2007/06/22(金) 13:54:53 ID:H0pevYdj
Apache+Mysqlで原因不明のエラーが出るのだが
[error] [client] ( owner = 2 OR access IN ('PUBLIC', 'LOGGED_IN', 'user2') ) AND (weblog IN (1))

構文として間違っているのなら指摘してくれ
構文としておkなら考えられる原因を指摘してくれ
色々と初心者な上、オープンソースのプログラムを使ってるからよく分からんのじゃ
364NAME IS NULL:2007/06/22(金) 14:22:30 ID:???
>原因不明のエラー
こっちを詳しく
365NAME IS NULL:2007/06/22(金) 14:51:53 ID:H0pevYdj
>>364
詳しくと言われてもApacheのエラーログに出てくるのはコレだけなんだ
[error] [client] ( owner = 2 OR access IN ('PUBLIC', 'LOGGED_IN', 'user2') ) AND (weblog IN (1))

PHPでMYSQLにアクセスしているみたいなのだが
エラー出力がこれだけだとどうにも対応できず、ここに来てしまった
366NAME IS NULL:2007/06/22(金) 15:00:48 ID:???
そういう時はコマンドラインでもGUIでもいいからそのDBで
手でSQLを実行してみればいい
それはSQLの一部でしかないので、全体がわからんとあれだけど
前の行には出てないの?
あとMySQLのバージョンも書いてくれ
367NAME IS NULL:2007/06/22(金) 15:27:19 ID:???
>>363
Apache + MySQLとはいえ、
PHPで何かのスクリプトをApacheから動かしてるから
エラーがApacheのログに残ってるんだろ?
なんてスクリプトなのかもうちょっと詳しく。

エラーにある内容はWhere句の式としては
妥当である可能性は高いけれど。
368NAME IS NULL:2007/06/22(金) 15:31:21 ID:H0pevYdj
>>366
全体は分からんけど、とりあえず探してみる。
一つのPHPファイルに記述されているのはそれくらいで
RequireやらIncludeで辿ると膨大な数のファイルでちょっと無理かもしれんが・・・

何度そのPHPを実行しても出てくるのはその一行だけ。
Mysqlのバージョンは6.0Alpha
369NAME IS NULL:2007/06/22(金) 15:41:47 ID:H0pevYdj
>>367
$friends = run("friends:get",array($page_owner));
if (!empty($friends)) {
$where2 = "weblog IN (" ;
$first=true;
foreach($friends as $friend) {
if (!$first) {
$where2 .= ", ";
}
$where2 .= $friend->user_id;
$first=false;
}
$where2 .= ")";
$extensionContext = trim(optional_param('extension','weblog'));
$where3 = "";
if(is_array($CFG->weblog_extensions)){
if($extensionContext!='weblog' && array_key_exists($extensionContext,$CFG->weblog_extensions)){
if(array_key_exists('type',$CFG->weblog_extensions[$extensionContext])){
$extraType = $CFG->weblog_extensions[$extensionContext]['type'];
$where3 = "AND ident IN(select ref FROM ".$CFG->prefix."tags WHERE tagtype='weblog' AND tag=".$db->qstr($extraType).")";
}
}
else{
$nofilter = array();
foreach($CFG->weblog_extensions as $key => $value){
if($key!='weblog' && array_key_exists('type',$value)){
$nofilter[] = $value['type'];
}
if($key!='weblog' && array_key_exists('values',$value)){
if(is_array($value['values'])){
$nofilter=array_merge($value['values'],$nofilter);
}
else{
$nofilter[] = $value['type'];
}
}
}
if(!empty($nofilter)){
$nofilter = implode(',',array_map(array($db,'qstr'),$nofilter));
$where3 = "AND ident not IN(select ref FROM ".$CFG->prefix."tags WHERE tagtype='weblog' AND tag in (".$nofilter."))";
}
}
}

$where1 = run("users:access_level_sql_where",$_SESSION['userid']);
error_log('('.$where1.') AND ('.$where2.') '.$where3);
$posts = get_records_select('weblog_posts','('.$where1.') AND ('.$where2.') '.$where3,null,'posted DESC','*',$weblog_offset,POSTS_PER_PAGE);
$numberofposts = count_records_select('weblog_posts','('.$where1.') AND ('.$where2.') ' .$where3);

正直このerror_logが怪しくなってきた・・・
これ消すだけで解決したらすまん。
370NAME IS NULL:2007/06/22(金) 15:43:08 ID:H0pevYdj
if (!empty($posts)) {

$lasttime = "";

foreach($posts as $post) {

$time = gmstrftime("%B %d, %Y",$post->posted);
if ($time != $lasttime) {
$run_result .= "<h2 class=\"weblogdateheader\">$time</h2>\n";
$lasttime = $time;
}

$run_result .= run("weblogs:posts:view",$post);

}

$weblog_name = htmlspecialchars(optional_param('weblog_name'), ENT_COMPAT, 'utf-8');

if ($numberofposts - ($weblog_offset + POSTS_PER_PAGE) > 0) {
$display_weblog_offset = $weblog_offset + POSTS_PER_PAGE;
$back = __gettext("Back"); // gettext variable
$run_result .= <<< END

<a href="{$CFG->wwwroot}{$weblog_name}/{$extensionContext}/friends/skip={$display_weblog_offset}"><< $back</a>
<!-- <form action="" method="post" style="display:inline">
<input type="submit" value="<< Previous 25" />
<input type="hidden" name="weblog_offset" value="{$display_weblog_offset}" />
</form> -->

END;
}
if ($weblog_offset > 0) {
$display_weblog_offset = $weblog_offset - POSTS_PER_PAGE;
if ($display_weblog_offset < 0) {
$display_weblog_offset = 0;
}
$next = __gettext("Next"); // gettext variable
$run_result .= <<< END

<a href="{$CFG->wwwroot}{$weblog_name}/{$extensionContext}/friends/skip={$display_weblog_offset}">$next >></a>

END;
}

}
else{
$type =(isset($extraType))?$extraType:$extensionContext;
$run_result = "<p>".sprintf(__gettext("Your friends currently don't have any %s"), strtolower($type))."</p>";
}
}

上下少し省いたけどこんな感じ
371NAME IS NULL:2007/06/22(金) 15:49:12 ID:H0pevYdj
解決した
誰がどう見てもPHPにErrorを出力するスクリプトが書いてあっただけですね
だめだ俺・・・早くなんとかしないと・・・

もう済んでしまったことはしょうがないので今後気をつけます
スレ汚し失礼しますた
372NAME IS NULL:2007/06/22(金) 16:01:52 ID:???
ハゲワロス
373NAME IS NULL:2007/06/22(金) 16:14:03 ID:???
デバッグならcgiやphpやjspでSQLをstderrに出すのはよくやる。
残ってたって事か。しかしこのスレで延々とPHPのソース貼られても・・・
374NAME IS NULL:2007/06/23(土) 17:09:42 ID:???
以下の様にUNIONの結果をソートすると劇的に速度低下してしまいます。

SELECT 商品名,値段,産地FROM 肉
UNION ALL
SELECT 商品名,値段,産地 FROM 魚介
 ORDER BY 値段

上記クエリは簡略例ですがUNION結果に対するORDER BYは必須です。
ORACLE9です。ヒントでもいいので情報ください。
375NAME IS NULL:2007/06/23(土) 17:16:05 ID:???
SELECT 商品名,値段,産地FROM 肉 ORDER BY 値段
UNION ALL
SELECT 商品名,値段,産地 FROM 魚介 ORDER BY 値段

ってすればいいんでね?
376NAME IS NULL:2007/06/23(土) 18:23:49 ID:???
>>375
合わせた結果をソートしたものと、各々ソートしたものを合わせた
結果が同じとは限らんだろ。

そもそもそんな書き方できないし。

>>374
個々のテーブルのソートは早いの?
377NAME IS NULL:2007/06/23(土) 18:31:11 ID:???
>> 376
個々のテーブルのソートは早いです(Indexあり)
ただUnionした結果に対してのソートは遅いです。
データ件数(Unionした結果件数)に比例して速度低下しています。
378デフォルトの名無しさん :2007/06/23(土) 19:45:13 ID:jr0+yJsz
ご教授ください。
予算テーブルが
予算(年月、予算項目、予算金額);年月、予算項目が主キー
となっており、例えば
2007年6月、水道費、5000
2007年6月、光熱費、7000
2007年6月、食費、12000
とあって、縦持ちのテーブルを横持ちで↓

      水道費  光熱費  食費   
2007年6月  5000   7000   12000

と表示したい場合のSQL文を教えてください。
379NAME IS NULL:2007/06/23(土) 19:51:53 ID:???
>>377
UNIONしたVIEWにINDEX張ればいいんでね?
380NAME IS NULL:2007/06/23(土) 20:24:55 ID:???
9iはviewにインデックスなんて張れるんだっけか?
381NAME IS NULL:2007/06/23(土) 20:55:03 ID:???
viewにindex張れるのってSQL Serverだけ?
382NAME IS NULL:2007/06/24(日) 11:16:31 ID:???
>>378


http://oraclesqlpuzzle.hp.infoseek.co.jp/9-1.html
相関サブクエリを使用する方法はpostgresでも動きます。
ただ、このパターンだと横列数(予算項目数分)を
ハードコーディングする必要がありますね。

http://oraclesqlpuzzle.hp.infoseek.co.jp/10-75.html
階層問い合わせを使う方法はOracleでないと動作しないと思います。
このパターンは横列数は意識しませんが、指定文字をセパレータとして
1カラムとしてデータを出力します。

メンテナンス性、可読性を踏まえてプログラム側で出力加工してみては?
383NAME IS NULL:2007/06/24(日) 11:44:37 ID:???
>>378 クロス集計ですね。

select 年月,

sum(
case
when 予算項目 = 水道費 then 予算金額
else 0
end) as 水道費,

from 予算テーブル group by 年月;
384378:2007/06/24(日) 15:11:37 ID:+uq9wgbc
>>382,383
ご教授ありがとうございました。
参考にさせていただきます。
385NAME IS NULL:2007/06/25(月) 12:00:58 ID:???
ご教授とは - 大辞林 第二版 (三省堂) からの引用

(1) (ア) 児童・生徒に知識・技能を与え、そこからさらに知識への興味を呼び起こすこと。(イ) 専門的な学問・技芸を教えること。「国文学を―する」「書道―」
(2) 大学などの高等教育機関において、専門の学問・技能を教え、また自らは研究に従事する人の職名。助教授・講師の上位。

ご教示とは - 大辞林 第二版 (三省堂) からの引用

(1) [「きょうし」とも] おしえしめすこと。示教。「御―を賜りたく」
(2) 実験・調査で、研究者の意図する行動を被験者にとらせるための指示。
386NAME IS NULL:2007/06/25(月) 13:22:12 ID:???
>385

引用だけの文章は違法。
387NAME IS NULL:2007/06/25(月) 14:04:07 ID:???
引用先が書いてあればOK
元は紙媒体のケースもあるし
388NAME IS NULL:2007/06/25(月) 14:22:39 ID:???
>>387
質量ともに文章の本体が主、引用される物が従、
でなければ著作権違反に問われる可能性がある。
ttp://qrl.jp/?265873
389NAME IS NULL:2007/06/25(月) 15:38:56 ID:???
さあ、通報した。
390NAME IS NULL:2007/06/25(月) 20:20:11 ID:???
>>388
あーつまり、引用ってのは、利用する側の著作物が主、利用される側の著作物が従の関係のものを言う訳だ。
まとめると、
・385は引用では無い。
・386は間違っている(引用と言うからには利用される側の著作物が従であり、これは違法にならない)。
・388のリンク先ではモンタージュ写真の場合についてのみ語られている(385の場合ではどうなるかは正確には不明)。
・385は著作権違反に問われる可能性がある(素人考えだがモンタージュ写真だろうが辞書の内容だろうが俺は同じに思える)。
という事か。

後385は、辞書では無く↓(教授 教示でググって最初に出たサイト)のコピーに見える。
ttp://blogs.wankuma.com/jeanne/archive/2005/11/24/19566.aspx
391NAME IS NULL:2007/06/26(火) 00:46:24 ID:???
 皆様のお力をお貸しください。

 下記3テーブルがSQL Server 2005 Expressをインストールしたテーブル上にあります。

[製品マスタ]
製品名/生産親品番/製品タイプ/シリーズ/電圧記号/容量記号/特性1/特性2/特性3/サイズ記号/ユーザーコード/加工記号/社内管理識別記号/サイズ1/サイズ2
--------------------------------------------------------------------------------------------------------------------------
AAB1A100AAA/AAB1A010AAA/A/AB/1A/100/A/A/A/////1/1
AAB1A100AAA/AAB1A010AAA/A/AB/1A/100/A/A/A///TA//1/1
AAB1A100AAA      A/AAB1A100AAA      A/A/AB/1A/100/A/A/A////A/1/1
AAB1A100AAA1TA   A/AAB1A100AAA      A/A/AB/1A/100/A/A/A///TA /A/1/1
                             ・
                             ・

[注文テーブル]
注文番号/ 注文品番/分納番号/数量
-----------------------------
1/AAB1A010AAA/1/10
1/AAB1A010AAA/2/10
2/AAB1A010AAA1TA/1/3
3/AAB1A010AAA1TA   A/1/10
                             ・
                             ・

[進捗管理テーブル](工程管理コードが1000以上は2次加工品。それ以下は半製品)
製造日番/生産品番/工程管理コード/在庫数/良品数 
------------------------------------------
12345-03/AAB1A010AAA/1220/15/
12345-01/AAB1A010AAA1TA/1220/1/
23456-03/AAB1A010AAA/1100//5
23456-02/AAB1A010AAA1TA/1100//1
23456-01/AAB1A010AAA1TA   A/1100//2
45678-00/AAB1A010AAA/990//30
                             ・
                             ・

そこから下記のような

注文番号/ 注文品番/分納番号/数量/出荷予定製造日番
---------------------------------------------
1/AAB1A010AAA/1/20/12345-03
1/AAB1A010AAA/2/10/12345-03
1/AAB1A010AAA/2/10/23456-03
2/AAB1A010AAA1TA/1/3/12345-01
2/AAB1A010AAA1TA/1/3/23456-02
2/AAB1A010AAA1TA/1/3/45678-00
3/AAB1A010AAA1TA   A/1/10/23456-01
3/AAB1A010AAA1TA   A/1/10/45678-00
                             ・
                             ・

結果を取り出したいのですが、どのようなSQLを書いてよいものかわかりません。
もし、SQLだけで不可能なら、どこまでをSQL上で処理しますか?

ご指導のほどよろしくお願いいたします。
392NAME IS NULL:2007/06/26(火) 01:33:18 ID:???
>>391
製品マスタにプライマリキーのような物が見あたらね。
-- 複合で出せないわけではなさそうだが。
いったいマスタテーブルと他のテーブルとをどう関連付けりゃいいのやら。
出力例の1行目の数量が20になってのもイマイチ不明。
なんか、マスタの親品番を再帰的に掘っているようにも見えるが、再帰するときの条件も不明瞭。

設計からやり直した方がよだそうだな。
393391:2007/06/26(火) 04:03:22 ID:???
>>392殿

先ほどは各テーブルの要点になりそうなところだけを抽出したため、こんな感じになってしまいました。

実際のテーブルは以下のとおりです。


[注文テーブル]注文番号(PK)/ 注文品番/受注数量/注残数量/...
             └───┐
[引当基本情報テーブル]注文番号(PK)/引当番号(PK)/ 出荷予定品番/引当数量/...
                   │         │          └──────────┐
                   │         │                           │
[引当詳細情報テーブル]注文番号(PK)/引当番号(PK)/明細行番号(PK)/製造日番/...     │
                ┌─────────────────────┘        │
[進捗管理テーブル]製造日番(PK)/品番/工程管理コード/在庫数/良品数...            │
                                                         │
          ┌───────────────────────────────-┘
[製品マスタ]製品名(PK)/生産親品番/製品タイプ/シリーズ/電圧記号/容量記号/特性1/特性2/特性3/サイズ記号/ユーザーコード/加工記号/社内管理識別記号/サイズ1/サイズ2/...
394391:2007/06/26(火) 04:04:04 ID:???
・製品を大きく分けて3つに分けています。(コードの数字が大きいほど完成品に近い)
 ・在庫(工程管理コード:1220)
 ・2次加工仕掛品(工程管理コード:1200〜1000)
 ・1次加工仕掛品(工程管理コード:990〜0) 

・製造日番は各製品の不足合計を生産親品番でまとめて計上することになっています。
 計上した製造日番は"AAAAA-00"で工程管理コード0番から1次加工品工程を進め、工程管理コード990が完了後、2次加工で必要な分を"AAAAA-01"見たいな形で分割し、加工して倉庫へ入庫ます。

・生産親品番は
  製品タイプ+シリーズ+電圧記号+容量記号+特性1+特性2+特性3+サイズ記号+社内管理識別記号

  製品タイプ+シリーズ+電圧記号+容量記号+特性1+特性2+特性3+ユーザーコード+社内管理識別記号
で求めることができます。(ただし、サイズ記号orユーザーコードと社内管理識別記号との間はスペースで区切り、社内管理識別記号は18文字目になければならないというルールがあります)


 で、現在、どの注文にどの製造日番を割り当てるかを決めるSQL文を考えていたのですが、さっぱり考え付かず、ここに質問させていただいた次第です。
395392:2007/06/26(火) 06:08:47 ID:???
>>393-394
すまんが、そうゴチャゴチャ書かれても、理解する気力ない。
てか、>>391の製品マスタ.製品名のAAB1A100AAAは2行あるように見えるが?

とりあえず 最後の「どの注文にどの製造日番を割り当てるか」だけ注目して
他の余計な物をバッサリと捨てた。参考になるかどうかワカランが。

注文テーブル(正確に言うと受注残テーブルかな)
 注文番号 注文品番 注文数量

進捗管理テーブル(まだ在庫がある製造分と、これからの予定分...?)
 製造日番 製造品番 製造数量(在庫分のみ?)

SELECT T3.*,T4.製造日番 FROM
(
SELECT *,
COALESCE((SELECT sum(製造数量) FROM 注文テーブル WHERE 製造日番<T1.製造日番 AND 製造品番=T1.製造品番),0)AS ptotal,
COALESCE((SELECT sum(製造数量) FROM 注文テーブル WHERE 製造日番<=T1.製造日番 AND 製造品番=T1.製造品番),0)AS ntotal
FROM 注文テーブル AS T1
) AS T3
FULL JOIN
(
SELECT *,
COALESCE((SELECT sum(注文数量) FROM 進捗管理テーブル WHERE 注文番号<T2.注文番号 AND 注文品番=T2.注文品番),0)AS ptotal,
COALESCE((SELECT sum(注文数量) FROM 進捗管理テーブル WHERE 注文番号<=T2.注文番号 AND 注文品番=T2.注文品番),0)AS ntotal
FROM 進捗管理テーブル AS T2
)AS T4
ON (T3.製造品番=t4.注文品番 )
WHERE T4.ntotal BETWEEN T3.ptotal AND T3.ntotal
OR T4.ptotal >T3.ptotal
ORDER BY T4.注文番号;

製造日番と注文番号はユニークで昇順に処理していく。
また、納入済み分の処理などを考えるとさらに複雑になるヨカソ。
最後になんだが、SQL鯖使いじゃないので、SQL鯖で動くかどうかもワカラン。
396392:2007/06/26(火) 06:30:01 ID:???
あや、一部訂正。
製造数量(在庫分のみ?) → 製造数量(製造済み分は残っている在庫分のみ)
意味通じるかなぁ?

× WHERE T4.ntotal BETWEEN T3.ptotal AND T3.ntotal
○ WHERE T4.ntotal BETWEEN T3.ptotal+1 AND T3.ntotal
まぁ、WHERE (T4.ntotal > T3.ptotal AND T4.ntotal <= T3.ntotal) でもいいんだけど。

で、これ以上突っ込まれて聞かれても俺は答える気力ない。
と、先に断っておく、スマソ。
397392:2007/06/26(火) 07:35:56 ID:???
何度もスマソ。WHRER句のOR以下もおかしいな。一つにまとめて
WHERE (T3.ptotal < T4.ntotal AND T3.ntotal > T4.ptotal)
ORDER BY order_num;

って一つじゃないか。もう、頭まわってね...orz
まだ間違ってるかも。

398NAME IS NULL:2007/06/28(木) 14:42:43 ID:???
SELECT *
FROM テーブル
WHERE フィールド1 = 条件文
  OR フィールド2 = 条件文
  OR フィールド3 = 条件文


で検索した結果で、何に引っかかって表示されているのか調べる方法はないですか?
ずららーっと、結果は問題なく表示されてるけど、どの検索条件に一致しているのかを知りたい。
399NAME IS NULL:2007/06/28(木) 16:14:23 ID:???
>>398
取得するカラムの1つをCASE式で評価して
適当なフラグ立てると良いんじゃね?
400398:2007/06/28(木) 17:41:46 ID:???
ありがとう。
やってみる!
401NAME IS NULL:2007/06/29(金) 19:17:50 ID:0VuwylaN
住所 結婚
-------------
埼玉 未婚
群馬 既婚
埼玉 未婚
山梨 既婚
東京 既婚

こんな感じのデータを
↓のようなデータに表にまとめたいのですが、どのようなSQL文を書けばよいですか?

住所 既婚 未婚
----------------------
・・・・
群馬 3104 1202
埼玉 7937 3929
千葉 6113 3797
東京 9232 7088
山梨 2987 1022
・・・・
402NAME IS NULL:2007/06/29(金) 20:05:09 ID:???
select 住所
    ,sum(case when 結婚='既婚' then 1 else 0 end) 既婚
    ,sum(case when 結婚='未婚' then 1 else 0 end) 未婚
from テーブル
group by 住所;
403NAME IS NULL:2007/07/01(日) 08:47:40 ID:???
phpMyAdminでテーブルの作成日時と最終更新日が表示されていますが
システム関数みたいなもので取得できるのでしょうか。
404NAME IS NULL:2007/07/02(月) 03:13:23 ID:???
Enterprise Manager のクエリ実行で出てくる
DERIVEDTBL とは一体なんなんでしょうか? ヘルプ見ても載っていないし、
検索しても海外のサイトばっかりで訳わかめです(;´Д`)
405NAME IS NULL:2007/07/02(月) 20:19:15 ID:RRdUYWi/
とある Access2003 のデータベースにて、

SELECT * FROM 1 WHERE ホゲホゲ > 1

といった操作を行うと適切なデータが返されます。

しかし、

SELECT * FROM 1 WHERE 1.ホゲホゲ > 1

といった操作を行うと、

クリエ式1 「1.ホゲホゲ > 1」 の構文エラー:演算子がありません

といったエラーが返されます。

どういった原因により構文エラーが発生しているのでしょうか。
よろしくお願いします。
406NAME IS NULL:2007/07/02(月) 20:31:03 ID:???
あなた、何をしたいの?
407NAME IS NULL:2007/07/02(月) 20:54:04 ID:???
>>403
show table status like 'テーブル名';

>>404
derived table (導出表?)
クエリから導き出されるテーブルとかそんな意味合いだったと思う

>>405
[1].ホゲホゲ

全部RDBMS依存なんで次からは適切なスレを探してね
408403:2007/07/03(火) 02:58:32 ID:???
>>407 さん
ありがとうございます、取得できました!
descぐらいしか思いつかなかった自分がお恥ずかしい。
409NAME IS NULL:2007/07/03(火) 11:20:36 ID:kH14UgW7
Accessで質問です。

データで、「住所」フィールドから都道府県を抜き出したく思い
Accessのフィールドに↓のように書きましたが、うまくいきません。

都道府県: Left([住所],InStr([住所],"都" Or "道" Or "府"Or "県"))

どのようにしたらよいでしょうか?
SQLでもその他の方法でもかまいません。

元データ
東京都新宿区
埼玉県秩父市
東京都杉並区
群馬県高崎市
京都府舞鶴市


抜き出したいデータ
東京都
埼玉県
東京都
群馬県
京都府
410NAME IS NULL:2007/07/03(火) 12:05:06 ID:???
>>409
極論を言うとテーブル設計が悪い。
都道府県を切り出す必要があるのなら、
最初から住所は都道府県と市区町村以降は
分離すべきだろ。

SELECT 住所, Max(都道府県) AS 都道府県
FROM (SELECT テーブル1.住所, Left([住所],InStr([住所],"都")) AS 都道府県 from テーブル1 UNION ALL
SELECT テーブル1.住所, Left([住所],InStr([住所],"道")) AS 都道府県 from テーブル1 UNION ALL
SELECT テーブル1.住所, Left([住所],InStr([住所],"府")) AS 都道府県 from テーブル1 UNION ALL
SELECT テーブル1.住所, Left([住所],InStr([住所],"県")) AS 都道府県 from テーブル1
)
GROUP BY 住所;

でパフォーマンスは悪そうだけど、何とか取れるとは思うが。
411NAME IS NULL:2007/07/03(火) 14:22:42 ID:DZCkMDG+
>>407

どうもありがとうございます。
おかげで作業を進めることができました。
412NAME IS NULL:2007/07/03(火) 14:23:22 ID:DZCkMDG+
↑ >>405 です。
413NAME IS NULL:2007/07/03(火) 16:46:00 ID:DSeuzHZM
table名[ list** ]には 列名が[name]の1つだけあります。
いま、list01とlist02の積集合の数を得たいのですが、
「INTERSECTを使って」なるべくシンプルなSQLを教えてくださいm(_ _)m
(DBはSQLiteですが大体Oracle等と同じだと思います)

ちなみに、以下のSQLで得ることはできますが、サブクエリがなんか無駄
な感じがしてしまいます...

SELECT count(name) FROM list01
WHERE name IN
(SELECT name FROM list01 INTERSECT SELECT name FROM list02)
414NAME IS NULL:2007/07/03(火) 17:33:01 ID:???
SELECT count(name) FROM (SELECT name FROM list01 INTERSECT SELECT name FROM list02)
SQLiteだとこれでいけたけど。
PostgreSQLだと後ろに名前つけないとならんかった
415391:2007/07/03(火) 19:57:35 ID:wpvZa8NM
>>392殿

 返事が遅くなりまして申し訳ございません。
 教えていただいたSQL文を実際の環境に合わせて実装してみたいと思います。

 ありがとうございました。
416404:2007/07/03(火) 20:28:57 ID:???
>>407
ご解答ありがとうございました。
少しすっきり致しました
417NAME IS NULL:2007/07/04(水) 09:42:51 ID:qkT/tPH1
d_tbl
id | name | status | date
----+------+--------+------------
1 | ahoo | 1 | 2007-07-01
2 | hoge | 4 | 2007-07-01


m_tbl
id | name | order
----+------+-------
1 | 上 | 4
2 | 中 | 3
3 | 下 | 2
4 | 最悪 | 1

select d.name,m.name,d.date from d_tbl as d left join m_tbl as m on d.status = m.id order by d.id,m.order

普段上記でデータを取得して使用しているのですが
追加で作成したシステムでm_tblのIDの並びを4>1>2>3
の順で出力しなくてはならなくなりました。
ですが私の知る限りorder byでそういったことができないと思い
現状データを取得した後プログラムで並び替えを行わせています。
しかしこのままだとデータが増えた際に処理が遅くなるのは目に見えており
なんとかSQLでやりたいのですがどのようにすればできるのでしょうか?

DBはpostgres 8を使用しています。
418NAME IS NULL:2007/07/04(水) 10:10:25 ID:???
4123って4種類限定なの?
ORDER BY id = 4 desc, i
とか使えるよ
419NAME IS NULL:2007/07/04(水) 10:12:49 ID:???
最後、d が抜けた。 ORDER BY id = 4 DESC, id ASC ね
420417:2007/07/04(水) 10:16:13 ID:qkT/tPH1
>>418
ありがとうございます
実際には10種類ほどあります
id=[番号],で順番を指定できるんですね
421413:2007/07/04(水) 10:33:47 ID:???
>>414
ありがとう!その通りでいけました!FROMのところにサブクエリ使えるんだね・・・。
422NAME IS NULL:2007/07/04(水) 12:15:28 ID:???
外部参照キーが自分自身のテーブルにあるカラムをさす場合について質問です。

create table emp(
  id     integer      auto_increment primary key,
  name   varchar(50)  not null,
  mgr_id integer      references emp(id)
);

というテーブルがあったときに

select t0.id, t0.name, t1.id, t1.name from emp t0, emp t1 where t0.mgr_id=t1.id;

とした場合、mgr_idがnullの項目が検索されません。

select t0.id, t0.name, t1.id, t1.name from emp t0, emp t1 where t0.mgr_id is not NULL or t0.mgr_id=t1.id;

とすると、検索結果がおかしいです。
この場合、どのようなSQLを書けばいいでしょうか。
あるいはヒントとなるキーワードを教えてください。
423NAME IS NULL:2007/07/04(水) 13:26:46 ID:???
>>422
not外すとどうなる?
424仕様書無しさん:2007/07/04(水) 13:32:00 ID:fg5TH2Y3
>>422
なんでnot Nullなん?null項目がでるわけない上に、そりゃぁ検索結果
がおかしいでしょ。

NOTはずすか、外部結合だな。
425422:2007/07/04(水) 16:23:43 ID:???
反応ありがとうございます。
is not nullはis nullの間違いでした。しかしis nullにしてもやっぱり結果がおかしいです。
例えば

mysql> insert into emp values(NULL, 'Foo', NULL);
mysql> insert into emp values(NULL, 'Bar', 1);
mysql> insert into emp values(NULL, 'Baz', 2);
mysql> select * from emp;
+----+------+--------+
| id | name | mgr_id |
+----+------+--------+
| 1 | Foo | NULL |
| 2 | Bar | 1 |
| 3 | Baz | 2 |
+----+------+--------+

のときに、
mysql> select t0.id, t0.name, t1.id, t1.name from emp t0, emp t1 where t0.mgr_id is NULL or t0.mgr_id=t1.id;
+----+------+----+------+
| id | name | id | name |
+----+------+----+------+
| 1 | Foo | 1 | Foo |
| 2 | Bar | 1 | Foo |
| 1 | Foo | 2 | Bar |
| 3 | Baz | 2 | Bar |
| 1 | Foo | 3 | Baz |
+----+------+----+------+

となります。
mgr_idがnot nullであるようなテーブルしか使ったことなかったので、今回の場合はどうしたらいいか分かりません。
426422:2007/07/04(水) 16:28:06 ID:???
>>424
「外部結合」がキーワードのようですので調べてみます。

427仕様書無しさん:2007/07/04(水) 16:50:28 ID:fg5TH2Y3
select t0.id, t0.name, t1.id, t1.name
from emp t0 left join emp t1
on t0.mgrid=t1.id
428422:2007/07/04(水) 17:02:05 ID:???
>>427
ありがとうございます。外部結合のleft joinが答えでした。
こんなの知らなかったよー。SQL入門じゃ教えてくれなかったから、中級以上の機能なのでしょう。

where t0.mgr_id = t1.mgr_id を使う場合と比べて、パフォーマンスに違いはありますか。
もしよければ教えてください。
429NAME IS NULL:2007/07/04(水) 17:02:22 ID:???
ただ「おかしい」とか書くから、何回もやり取りしなくちゃ解決しないんだ
430仕様書無しさん:2007/07/04(水) 17:10:25 ID:fg5TH2Y3
>>428
この程度のコードだとパフォーマンスは変わらないと思う。
SQLはFROM句から評価されていくことは知ってるでしょ?
まずFROM句で直積をとってからWHERE句以降を評価し、最後にSELECT句
で抽出(射影)するから。

でもLEFT JOINには
select … from 表 left join (select… from表 where…)
on ○○ left join (select… from 表 where…) on ○○ 
とか続くのもあるから(というよりそんなのばっかり)、そうなると分からない。
431NAME IS NULL:2007/07/04(水) 17:10:51 ID:???
>>428
あんたの学習レベルが低いだけだよ
432422:2007/07/04(水) 17:59:56 ID:???
>>430
丁寧な回答ありがとうございます。
SQLは宣言的だから中の仕組みががblackboxであり、そのためにチューニングで苦労しますよね。
Javaのチューニングだったら簡単なのに。
433NAME IS NULL:2007/07/04(水) 18:08:47 ID:???
>>432
プロファイラとかついてるだろ?
434NAME IS NULL:2007/07/04(水) 18:11:44 ID:???
LEFT JOIN も知らなかったやつがチューニングの話をするなんて、
何かの冗談ですか
435NAME IS NULL:2007/07/04(水) 18:40:23 ID:qkT/tPH1
joinする対象が2つ以上あった場合どのようにして結合したらいいのでしょうか?
select d.*,c.name from
(select a.cid,b.name from Atbl as a left join Btbl as b on a.bid = b.id)
as d left join Ctbl as c on d.cid = c.id;
と書くしかないのでしょうか?
436NAME IS NULL:2007/07/04(水) 18:42:37 ID:???
よくわからんが、
FROM xxx
LEFT JOIN yyy ON 〜
LEFT JOIN zzz ON 〜

みたいに並べることはできる。
437435:2007/07/04(水) 18:44:01 ID:qkT/tPH1
>>436
ありがとうございます
並べて書いてみます
438NAME IS NULL:2007/07/04(水) 20:32:05 ID:???
>>434
ネタだろwww

・・・と思いたいが、パフォーマンス云々の寝言言う前に
とりあえず実行計画確認してから来いと言いたい訳だがwww
439NAME IS NULL:2007/07/05(木) 18:16:43 ID:XuEszA9P
インデックスのパフォーマンスに関する質問です。

性別のように、カーディナリティの低い(とりうる値の種類の少ない)
フィールドはインデックスを使ったほうが遅くなる、
むしろテーブルスキャンのほうが速い、とよく聞きます。

しかし、
select count(gender) from mytable where gender = 1
のように、単純に件数をカウントする場合は、
参照数も少なくて速いように思われるのですが、
こういうクエリが多い場合でも、インデックスは
使用しない方がよいのでしょうか。
440NAME IS NULL:2007/07/05(木) 19:03:14 ID:???
>>439
別にインデックス作っても良いんじゃね?
441NAME IS NULL:2007/07/05(木) 19:42:25 ID:???
インデックス作っても良いけど(コストベースオプティマイザのDBMSでは)
使われないかもね。

とりあえず作ってみて実行計画と実際の処理時間を
調べてみるのが早いと思うけど。
442NAME IS NULL:2007/07/05(木) 19:48:40 ID:???
>>439
別に作ったら作ったで検索は速くなると思うが、その分データの追加の時に
遅くなるからなぁ。

DB2とかは各カラムの統計情報を収集してオプティマイザが働くので、
まあ、性別みたいなのにはINDEXつけなくても、そこそこにスピードでるけど。

実際はRDBMSによって動作はまちまちなんで実行計画で確認汁。
443NAME IS NULL:2007/07/05(木) 20:07:59 ID:???
>>439
DBによって違うかな?
PostgreSQLの場合はとインデックスが張られているフィールドでCountしても
必ずテーブル本体を読みに行くので、プランナが判断でインデックス検索を
必要としないと下すと、端からインデックスは使用されない。

Oracleはインデックス検索だけで、Countできるらしいので、その場合は有用かも。
-- 本当かどうか、この質問にも当てはまるかどうかも知らないが、どっかにTipsとして取り上げられてた。

一応PostgreSQLの場合はと限定すれば、
プランナの判断とINSERT時のインデックス構築を考えれば、
使われなさそうなインデックスは張らないほうが得策となる。
444NAME IS NULL:2007/07/05(木) 21:25:31 ID:???
性別とかはインデックスはない方がいいと思うけどな〜
更新パフォーマンスがたおちじゃね?(SQL Server)
ttp://www.atmarkit.co.jp/fdb/rensai/drk05/drk05_3.html
445439:2007/07/05(木) 21:54:11 ID:???
>>440-444

回答ありがとうございます。
総合すると、エンジンによって処理が異なるため
一概にどれが正解ということはない、
オプティマイザの結果と相談、ということですね。

さらに、更新時のパフォーマンスとのトレードオフも
考慮すべきと(これはインデックスの一般的な検討事項ですが)。

大変参考になりました。
446NAME IS NULL:2007/07/05(木) 23:19:50 ID:CfhiNk+E
ORACLEで
列1だけ共通して、あとはバラバラのテーブルAとBがあって
列1が100のときの
Aの列2、Bの列5の集計を取り出したいとき

SELECT SUM(A.列2) + SUM(B.列5)
FROM A
LEFT OUTER JOIN B
USING(列1)
WHERE A.列1 = 100

で集計した結果と
AとBを別々に集計した結果が異なります

SQL全然触ったことないので
自分的にはWHEREとOUTER JOINの組み合わせが
ミスってるような気がします
職人の方、ご教授お願いします

別々で集計したときは

SELECT SUM(列2)
FROM A
WHERE 列1 = 100



SELECT SUM(列5)
FROM B
WHERE 列1 =100

の結果を集計をしました

(スレ用に可読性を考慮して、わざと全角で記入してます)
447NAME IS NULL:2007/07/06(金) 00:13:04 ID:???
>>446

突っ込みどころはいろいろあるけど、

SELECT *
FROM A
LEFT OUTER JOIN B
USING(列1)
WHERE A.列1 = 100

これで出てきた結果セット全てのsum()がとられていると言えば、
なぜおかしい結果になってるかを理解する一番早い方法かと。

基本的に、一意じゃない列同士をjoinすべきではない。
本当にm×nの総当りな結果セットが欲しいときくらい。
448NAME IS NULL:2007/07/06(金) 11:20:45 ID:???
こんなん書くの恥ずかしいんですが。。。どなたかお力を。
普段マイナー言語で開発やってて、sql使う機会があまり無い物で。

趣旨は、重複するレコードがあった場合、先頭レコードだけ抽出をしたい。

とあるテーブルに下記の様に4項目持ってたとして、項目1と項目2の値が重複していたら先頭レコードを抽出。

項目1、項目2、項目3、項目4
010,AAA,1000,1
010,AAA,2000,2
010,AAA,3000,3
020,BBB,1000,2
020,CCC,2000,2
030,AAA,2000,3
030,AAA,2000,4
030,AAA,2000,5

上記の様なデータから下記のデータを抜き出したい。
010,AAA,1000,1
020,BBB,1000,2
020,CCC,2000,2
030,AAA,2000,3

SELECT DISTINCT 項目1, 項目2 FROM テーブル
上の様なsql一度書いたのですが、これだと項目1と2しか結果に表示されなくて困ってます。

どなたかお手すきの方ご教授願えれば幸いです。
449NAME IS NULL:2007/07/06(金) 11:27:36 ID:???
>>448
先頭レコードの定義は?
ORDER BY 項目3,項目4
の先頭でいいのかな?
450NAME IS NULL:2007/07/06(金) 12:16:57 ID:KwXXH4Ws
すみませんがちょっと思いつかないので力を貸してください。

メインはDBはポスグレで後でファイアバードにも対応させなければいけないんですが
とりあえずポスグレターゲットでお願いします。

あるテーブルAがありそのカラムは
YMD Charactor(8) --YYYYMMDD形式で日付を保存
HMS charactor(6) --HHMMSS形式で時間を保存
KEY integer-- Key情報を保存

というテーブルがありこの3つでPrimaryKeyとなります。
このような形式のテーブルで
開始年月日〜終了年月日を指定してKEYをとってきたいのですが BETWEEN 開始日 AND 終了日 を使うのはわかっても
変換の方法がわかりません
たぶんこうなるであろうよそうですが、これでは怒られてしまいました

to_timestamp(YMD + ' ' + HMS ,'YYYY/MM/DD HH:MM:SS') BETWEEN  '#2007/1/1 06:00:00#' AND '#2007/1/1 12:00:00#' 

もしお判りになる方がいらっしゃいましたらご教授願えませんか?
451448:2007/07/06(金) 12:41:48 ID:???
>>449
失礼しました。
項目1と項目2が主キーです。
なので項目3と項目4の内容は問いません。
452NAME IS NULL:2007/07/06(金) 13:17:52 ID:???
>>448

テキトーでいいなら
SELECT 項目1, 項目2, min(項目3), min(項目4) FROM テーブル group by 項目1, 項目2

問題がありそうなら
SELECT distinct 項目1, 項目2,
(select top 1 項目3 from テーブル where 項目1 = a.項目1 and 項目2 = a.項目2),
(select top 1 項目4 from テーブル where 項目1 = a.項目1 and 項目2 = a.項目2)
FROM テーブル as a

「top 1」はMSSQLの方言だが、mysqlなら「limit 1」に書き換えるべし。
453NAME IS NULL:2007/07/06(金) 14:10:06 ID:???
>>448
PostgreSQL限定(だと思う)でよければ、
SELECT DISTINCT ON (項目1, 項目2) 項目1,項目2,項目3,項目4 FROM テーブル ORDER BY 項目1,項目2,項目3,項目4
とかも使える
454NAME IS NULL:2007/07/06(金) 14:15:45 ID:???
>>450
試してないけど、それでto_timestampでTIMESTAMP型にするなら
to_timestamp(YMD || ' ' || HMS ,'YYYYMMDD HH24MMSS')
じゃない?
455454:2007/07/06(金) 14:21:52 ID:???
ごめん、こうだな。
to_timestamp(YMD || ' ' || HMS ,'YYYYMMDD HH24MISS')
456NAME IS NULL:2007/07/06(金) 14:44:14 ID:KwXXH4Ws
>>455
理想通りの動作が来ました
単純に+じゃなく || 、日付の指定形式を間違えていたんですね・・・・
ありがとうございました!
457448:2007/07/06(金) 16:29:39 ID:???
いまさらですがDB2です。すいません。
FETCHとか使うって事ですかね?
アドバイス参考にやってみます。
ありがとうございます。
458NAME IS NULL:2007/07/06(金) 17:08:20 ID:???
>>457

まぁ、カーソルへのfetchを扱えるというのなら、
それが一番スマートで確実なやり方だろうな。

>sql使う機会があまり無い
と言うから、できるだけ簡単な方法を提示してみたのだが。
ちなみにfetchは、ストアドでやるって意味だよな?
クライアントサイドから全件fetchやろうとしてるなら、
いずれパフォーマンスで泣きを見るぞ。

別解として、更新時の処理をいじる余地があるのならば、
項目1と項目2が複合主キーな別テーブルを用意して、
トリガで1件目のときだけそっちにinsertするという方法もある。
459NAME IS NULL:2007/07/06(金) 20:20:25 ID:EkGmqGMy
以下のようなデータが入ってるtestというテーブルがあります。
+-------+------+-------+
| CLASS | NAME | COUNT |
+-------+------+-------+
| 1 | a | 1 |
| 1 | b | 2 |
| 3 | c | 10 |
+-------+------+-------+

CLASS別に最大のCOUNTを持つ行を取得したいと思います。
select CLASS,
NAME,
max(COUNT)
from test
group by CLASS;
というSQLを流した結果以下のようになってしまいました。
+-------+------+------------+
| CLASS | NAME | max(COUNT) |
+-------+------+------------+
| 1 | a | 2 |
| 3 | c | 10 |
+-------+------+------------+

期待していた結果は
+-------+------+------------+
| CLASS | NAME | max(COUNT) |
+-------+------+------------+
| 1 | b | 2 |
| 3 | c | 10 |
+-------+------+------------+
なのですが、どうしたらこのような結果を取得できますか?

すいませんがご指導よろしくお願いします。
460NAME IS NULL:2007/07/06(金) 20:29:54 ID:???
>> 459
問題の性質は、>>448 とほとんど同じだな。
解決法も似たようなものになる。
461NAME IS NULL:2007/07/06(金) 20:53:50 ID:???
>>459
例に出してるデータに
| 1 | d | 2 |
というレコードが加わったらどう出したいんだ?
話はそれからだ。
462459:2007/07/06(金) 21:00:15 ID:EkGmqGMy
レスありがとうございます。
>>460
order by をかけて一番大きい値順に出すと言う事でしょうか?
>>461
bでもdでも良いので1レコードだけ出てほしいです。

maxとgroupを使えば最大値の含まれる行が出ると思っていたのですがそうではなかったんですね。

463NAME IS NULL:2007/07/06(金) 21:59:55 ID:???
>>462
>order by をかけて一番大きい値順に出すと言う事でしょうか?
>>453 やFETCHするやり方ならそうなるかな。

仕事忙しいはずなのに、ほっとけなくなって回答例作ってみた。
select
class,
(select name from test where class = grouped.class and count = grouped.max_count),
max_count
from
(
select
class,
max(count) as max_count
from
test
group by
class
) as grouped

ただしこれだと >>461 の場合にエラー出るから、使ってるDBMSに応じて
top 1なりlimit 1なり付けるべし。
464NAME IS NULL:2007/07/06(金) 22:37:22 ID:???
スレが伸びてると思ったら…
われなべにとじぶたの品評会ですか?
465456:2007/07/06(金) 23:51:36 ID:???
>>463
お忙しい中ご回答ありがとうございました。

select class,
(select name from test where class = grouped.class and count = grouped.max_count limit 1),
max_count
from
(
select class,
max(count) as max_count
from test
group by class
) as grouped

とする事で解決しました。

本当にどうもありがとうございます。
466NAME IS NULL:2007/07/07(土) 13:19:44 ID:???
MSアクセスで同僚のためにクエリを書いたのですが、いくつものクエリを順番に実行するというスマートではないものになってしまいました。
一発でできないかご教授願います。

テーブルが2つあり、それぞれに品番と数量のフィールドがあります。
品番の重複がそれぞれのテーブル内であるので、品番ごとに数量を集計して2つのテーブルで品番ごとに数量の合計の差異があるか
どうか、また品番のマッチングがないものを調べたいのですが、集計した後にうまくJoinで合体できません。

仕方がないので、集計したテーブルをそれぞれSelect Into で別個に作成してからJoinを行っています。
できればこのステップを排除したいのですが、どうしたらよいのでしょうか?

今はこんな感じです。

Select 品番, SUM(数量) into temp_TableA
From TableA
Group By 品番

同様にTableB

その後

Select A.品番, A.数量-B.数量 From temp_TableA A
Join temp_TableB B
On A.品番 = B.品番
Where A.数量-B.数量 <>0
467NAME IS NULL:2007/07/07(土) 14:52:04 ID:???
select coalesce(A.品番, B.品番), A.数量小計, B.数量小計
from (select 品番, sum(数量) as 数量小計 from TableA group by 品番) as A
   full outer join
   (select 品番, sum(数量) as 数量小計 from TableB group by 品番) as B
   on A.品番 = B.品番
where A.数量小計 <> B.数量小計
or   A.数量小計 is null
or   B.数量小計 is null

とか。
MS Accessで書けるかどうかはシラネ。
468NAME IS NULL:2007/07/07(土) 20:58:16 ID:???
こんな感じの2つテーブルがあったとき

items
+---------+
| name |
+---------+
| folder0 |
| file-a1 |
| file-b1 |
| folder1 |
| file-c2 |
| file-d2 |
| file-e1 |
+---------+
consist
+---------+---------+
| parent | child |
+---------+---------+
| folder0 | file-a1 |
| folder0 | file-b1 |
| folder0 | folder1 |
| folder0 | file-e1 |
| folder1 | file-c2 |
| folder1 | file-d2 |
+---------+---------+

子のあるfolder1を再帰的に処理して、こんな結果を得たいのですが、どうすればいいでしょうか?
folder0
 file-a1
 file-b1
 folder1
  file-c2
  file-d2
 file-e1
469NAME IS NULL:2007/07/08(日) 09:17:55 ID:???
>>467
見たことのないコマンドがいきなり…
オラクルでしょうか? 似たようなのがSQLサーバやMSアクセスでないかどうか調べてみます。
ありがとうございました。

月曜日に早速試してみます。
470NAME IS NULL:2007/07/08(日) 10:27:05 ID:???
見たことないコマンドって... おいおい...

同僚のためにクエリ書くのもいいけど、もう少し本とかマニュアルとか
読んだほうがいいと思うよ。
471NAME IS NULL:2007/07/08(日) 11:14:03 ID:???
>>468
WITH RECURSIVE とか使うんだろうな。
でも俺は書いたことないから回答は書けない。
472468:2007/07/08(日) 11:36:50 ID:???
>>471 ご教示ありがとうございます。
WITH RECURSIVEをキーワードにググったところ、ヒントになりそうな情報
が見つかりました。
ちなみに、使用データベースは、postgresqlです。
473NAME IS NULL:2007/07/08(日) 13:45:40 ID:???
おお、俺もはじめて知ったよ WITH 句

サンクス ⇒ >>471
474NAME IS NULL:2007/07/08(日) 16:29:55 ID:???
PostgreSQLはRECURSIVEをまだサポートしてないだろ。
標準では入らないけど、用意されているconnectbyだったかを
加えればそれでできる。
475468:2007/07/08(日) 18:28:32 ID:???
>>474
再帰問い合わせは8.2でもできないとのことですが、CREATE FUNCITONを使って
同様のことができることを見つけたのですが、connectby(contrib/tablefunc
モジュール)の方法もわかりました。ご教示ありがとうございます。
476NAME IS NULL:2007/07/09(月) 14:46:41 ID:WLR34h5u
質問です
Postgresで以下のようなテーブルがあります。

ID,StartDay,EndDay,Name,その他のカラム........
1,2006/1/1,2006/12/31,AAAA(2006),
1,2007/1/1 ,9999/12/31,AAAA(2007),
2,2006/1/1,2006/12/31,BBBB,
2,2007/1/1 ,2007/12/31,BBBB,

このようなデータの時に 
指定された日付が開始、終了の範囲内のあるもので使用するのですが、今回は
一番新しいIDと名前の組み合わせを取得したいのです。
何とかして1激で取ってこれるような良い案はないでしょうか?
終了データは必ず9999/12/31で終わるようにはなっていないので 単純にWHERE条件で指定できない状態です。
477NAME IS NULL:2007/07/09(月) 14:55:50 ID:???
>>476

select * from table_name where cast('2007-07-09' as date)
between StartDay and EndDay order by ID limit 1
478NAME IS NULL:2007/07/09(月) 15:30:38 ID:WLR34h5u
>>477
すません、せっかく考えてくださったのに説明がうまく出来ておらず伝わっていなかったようで

日付関係なしに取ってきても現在あるデータの中で
EndDayが最高の値を持つ各ID列の一覧を取得したいんです。

上のたとえで言えば いつどんな日にデータを取得してきたとしても
1,2007/1/1 ,9999/12/31,AAAA(2007),
2,2007/1/1 ,2007/12/31,BBBB,
を抽出できるということです。
479NAME IS NULL:2007/07/09(月) 16:18:06 ID:???
そんな条件、>>476のどこにも見えないが・・・

GROUP BY IDと、MAX(date) でこの2つが出ると思うが、
それを元にSELECTしては。同じ値があったときどうするかとか
書いて無いので、このくらいしか書けないけど。
480NAME IS NULL:2007/07/09(月) 18:23:29 ID:???
PostgreSQL依存だが
SELECT DISTINCT ON (ID) * FROM Table ORDER BY ID,EndDay DESC ;
481NAME IS NULL:2007/07/09(月) 18:32:20 ID:y+tFWW+2
MySQL 4.1.20 を使っています。
>>482のようなテーブルとデータがあります。
2007年の当月分のデータだけを取得するため以下のSQLを実行しました。
(またラベルとして利用するために「日」を取得しています)

SELECT
dt,
DAY(dt)
AS d
FROM TEST
GROUP BY d
HAVING MONTH(dt) = MONTH('2007-07-01')
;

そうするとなぜか 2007-07-07 と 2007-07-08 のデータが出力されません。
ためしに (1, '2007-06-07 00:00:00') のレコードを削除してみると、
2007-07-07 のデータは出力されるようになりました。
全然理由がわかりませんが、なぜなんでしょうか?
482NAME IS NULL:2007/07/09(月) 18:33:27 ID:y+tFWW+2
CREATE TABLE `TEST` (
`id` int(10) unsigned NOT NULL auto_increment,
`dt` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=ujis AUTO_INCREMENT=33 ;

INSERT INTO `TEST` (`id`, `dt`) VALUES
(1, '2007-06-07 00:00:00'),
(2, '2007-06-08 00:00:00'),
(3, '2007-06-09 00:00:00'),
(4, '2007-06-10 00:00:00'),
(5, '2007-06-11 00:00:00'),
(6, '2007-06-12 00:00:00'),
(7, '2007-06-13 00:00:00'),
(8, '2007-06-14 00:00:00'),
(9, '2007-06-15 00:00:00'),
(10, '2007-06-16 00:00:00'),
(11, '2007-06-17 00:00:00'),
(12, '2007-06-18 00:00:00'),
(13, '2007-06-19 00:00:00'),
(14, '2007-06-20 00:00:00'),
(15, '2007-06-21 00:00:00'),
(16, '2007-06-22 00:00:00'),
(17, '2007-06-23 00:00:00'),
(18, '2007-06-24 00:00:00'),
(19, '2007-06-25 00:00:00'),
(20, '2007-06-26 00:00:00'),
(21, '2007-06-27 00:00:00'),
(22, '2007-06-28 00:00:00'),
(23, '2007-06-29 00:00:00'),
(24, '2007-06-30 00:00:00'),
(25, '2007-07-01 00:00:00'),
(26, '2007-07-02 00:00:00'),
(27, '2007-07-03 00:00:00'),
(28, '2007-07-04 00:00:00'),
(29, '2007-07-05 00:00:00'),
(30, '2007-07-06 00:00:00'),
(31, '2007-07-07 00:00:00'),
(32, '2007-07-08 00:00:00');
483NAME IS NULL:2007/07/09(月) 18:42:40 ID:???
>>478
普通に
select A.ID, A.StartDay, A.EndDay, A.Name, A.その他のカラム
from TABLE_NAME A
   inner join
   (select ID, max(EndDay) as MaxEndDay from TABLE_NAME group by ID) B
   on A.ID = B.ID
   and A.EndDay = B.MaxEndDay
;
じゃないの?
IDとEndDayの組合せで一意になるという前提だが。
484NAME IS NULL:2007/07/09(月) 18:44:49 ID:???
>>482

まず
SELECT
dt,
DAY(dt)
AS d
FROM TEST
GROUP BY d;
だけを実行してみなよ。
その結果にhavingの条件が適用されることを考えれば、
なぜそうなるのかわかるはず。
485NAME IS NULL:2007/07/09(月) 18:53:50 ID:WLR34h5u
>>479,>>480,>>483
レス遅くなってすみません。
あれから夢中になっていろいろ試してみてました
どうも>>483さんの方法でできそうな気がします。
ちょっとこれから試してみようかと。

下手糞な質問の仕方でご迷惑をおかけしました。
486NAME IS NULL:2007/07/09(月) 19:06:30 ID:???
>>484
ありがとうございます。
そうか、日だけでGROUP BYしてたから、6月と7月で同じ日の
データがグループ化されてしまっていたんですね。
ありがとうございました。
487NAME IS NULL:2007/07/09(月) 19:20:36 ID:???
>>486
そもそもGROUP BYの使い方を間違ってるような。
単にWHERE句で日付範囲を指定すればいいだけでは?
488NAME IS NULL:2007/07/10(火) 03:02:44 ID:???
mysql5でtypeが重複しているものはtimeが最も新しいレコードを表示する
という処理をしたいと思っています。

id   type value time
1   a   12   12:38
2   b    8    9:12
3   a   14   13:22
4   a   10   11;21
5   b   13    7:35

期待する表示は
3   a   14   13:22
2   b    8    9:12
です。

現在
SELECT *
FROM (
 SELECT *
 FROM test
 ORDER BY time DESC
) temp
GROUP BY temp.type

で実現できているのですが件数が増えるにつれパフォーマンスに問題が出てきます。
このSQL文より速度が出る書き方はありませんでしょうか。
489NAME IS NULL:2007/07/10(火) 03:52:08 ID:???
>>488
新しいという意味が最大値ということでいいのなら、
select
type,value,max(time) as mt
from test
group by type
order by mt desc;
490NAME IS NULL:2007/07/10(火) 04:11:01 ID:???
>>489
スマンvalueが、、、

select * from test where time in
(select max(time) from test group by type)
でとりあえずとれるけど、あんまり速くないか、、
491NAME IS NULL:2007/07/10(火) 04:37:58 ID:???
>>490
すまん、何度も間違えた、アホな俺

select t.* from test as t, (select type,max(time) as mt from test group by type) as t2
where
t.type=t2.type
and
t.time=t2.mt;
492NAME IS NULL:2007/07/10(火) 05:32:41 ID:???
>>489 さん
ありがとうございます。実環境で計測したところ3倍程高速になりましたヽ( ´¬`)ノ
493NAME IS NULL:2007/07/10(火) 06:20:58 ID:???
もし、typeとtimeを複合インデックスにしてなかったら
alter table test add index(type, time);
analyze table test;
した後の計測結果を教えてほすぃ
もちろん無理だったらいいです
494NAME IS NULL:2007/07/10(火) 06:46:28 ID:???
スレ違いかもしれんが、SQL実装時の効率のためにということで質問させて
ください。というか、この手のスレが閑散としているので。

[Company]
- ID
- Name
- Address

のような表があったとして、その会社の役割を表すのに、

- CustomerFlag
- VendorFlag
のような属性を[Company]に追加するか?

[Customer]
-CompanyID (FK)
[Vendor]
-CompanyID (FK)
のようにラッパー表を作るか?
のどちらがいいでしょうか?
簡単な問い合わせは前者の方が楽ですが、例えば、Customer固有の属性を追加
するときなどは後者の方がきれいにできるかと思います。
ご教示いただければ、ありがたく思います。よろしくお願いします。
495NAME IS NULL:2007/07/10(火) 06:58:07 ID:???
>>494
固有属性がたくさんあるなら後者だろうが、
最終的にはパフォーマンスと相談じゃないか?
496NAME IS NULL:2007/07/10(火) 23:16:16 ID:???
>>494
自分で答え書いてる気が...

> 簡単な問い合わせは前者
> Customer固有の属性を追加するときなどは後者

どっちのケースがどれぐらいあるかは君にしかわからないよ。
497NAME IS NULL:2007/07/11(水) 15:51:57 ID:tW1Thc0z
論文(年度,論文番号,論文名) ※主キー;年度,論文番号
著者(年度,論文番号,著者順位,著者名) ※主キー;年度,論文番号,著者順位
というテーブルがあり,
【年度,論文番号,著者1,著者2,著者3,著者4,著者5】という結果を出すSQL文を
作成しましたが,(著者順位は最大5まで),クエリ式の構文エラー;演算子がありません
とプログラムから怒られました.どこが間違っているのでしょうか教えて下さい.

SELECT R.年度,R.論文番号,R.論文名,A.著者名 AS 著者1 ,B.著者名 AS 著者2,C.著者名 AS 著者3,D.著者名 AS 著者4,E.著者名 AS 著者5
FROM 論文 R LEFT JOIN (SELECT * FROM 著者 WHERE 著者順位=1) AS A ON R.年度=A.年度 AND R.論文番号=A.論文番号
LEFT JOIN (SELECT * FROM 著者 WHERE 著者順位=2) AS B ON R.年度=B.年度 AND R.論文番号=B.論文番号
LEFT JOIN (SELECT * FROM 著者 WHERE 著者順位=3) AS C ON R.年度=C.年度 AND R.論文番号=C.論文番号
LEFT JOIN (SELECT * FROM 著者 WHERE 著者順位=4) AS D ON R.年度=D.年度 AND R.論文番号=D.論文番号
LEFT JOIN (SELECT * FROM 著者 WHERE 著者順位=5) AS E ON R.年度=E.年度 AND R.論文番号=E.論文番号
ORDER BY R.年度,R.論文番号
498NAME IS NULL:2007/07/11(水) 16:39:53 ID:???
>>497
本当にちゃんと回答してもらいたいなら、使用してるDBMS書こうぜ・・・

見た感じ、Accessだろうと推測できるが、その前提ならば、
Accessのjoin句はややクセがあって、他のDBMSのように
複数の結合対象テーブルを並列に記述できない。
サブクエリでネストする感じで書くしかない。

SQLというよりはAccessの方言の問題だから、Accessを使って
3つ以上のテーブルをjoinしてるSQLのサンプルを探してみな。
499497:2007/07/11(水) 17:16:59 ID:tW1Thc0z
すみません.お察しの通りDBはAccessです.
ちょっと調べてみます.
500NAME IS NULL:2007/07/11(水) 22:57:58 ID:???
select A,B from hogeTable where ・・・
って文をSQLExecDirectで実行した結果取得できた行数を、
取得するVCの関数or方法ってありませんか?

SQLRowCount関数を試したところ、
全結果セットをSQLFetchした後にしか正しい値が帰ってきません。

whereのあとに続く条件が多いため
select count(A) from hogeTable where ・・・
という同じようなSQL文を2回も発行したくないんですよね。

ちなみに何がしたいかっていうと、実行したSQLで取れるレコード数の
領域を確保して、結果セットを全てメモリに入れたいのです。
501NAME IS NULL:2007/07/11(水) 23:46:25 ID:???
>>500
たぶんSQLRowCountの仕様じゃないかな。

その要求を聞くに、ADOで言うところのGetRows()が最も適切なんだろうけど、
これに相当するODBC APIが何なのか、あるいはあるのかはわからん。

あと、レコード数わからなくても、メモリを動的に確保する方法はあると思うが。
C++なら、STLのコンテナクラス使ってレコードなくなるまでpushとか。
Cだったら・・・自作listとかでガンガれ。
502NAME IS NULL:2007/07/12(木) 11:36:17 ID:???
SQL SERVERを使用しているのですが、
数値データを取得する時に書式を指定するには
どうすれば良いのでしょうか?
503NAME IS NULL:2007/07/12(木) 13:02:45 ID:???
>>502
3桁ごとのコンマの付与なら、money型をconvert(case)するときに
styleに1を指定することでできるっぽいが、
アプリケーション側で変換した方がいいと思うけどなあ。
504NAME IS NULL:2007/07/12(木) 13:12:40 ID:???
>>503
なるほど、ありがとう!
試してみます。
505NAME IS NULL:2007/07/12(木) 23:31:50 ID:???
2005で.NET使ってるならアプリ側でやるよりCLR関数作ったほうがいいんじゃね?
2〜3パターンならめんどうだけどT-SQL関数でも作れない事はないし
実際そうしてる
506506:2007/07/12(木) 23:48:01 ID:???
>>505
俺がアプリ側の方が好ましいと言ったのは、
例えば「カンマ編集するかどうかを出力オプションで設定できる」みたいな
要求が出てきたときに、柔軟に対応できる余地を残したいからだったんだけどね。
まーその辺のバランス加減は質問者に委ねるよ。
507503:2007/07/12(木) 23:49:59 ID:???
>>506
名前欄間違えた。503=506ね。
508NAME IS NULL:2007/07/12(木) 23:53:54 ID:???
sqlについて質問です。
selectの結果セットに固定のデータを潜りこませたい場合

( select "aaa", "bbb" ) union ( select f1, f2 from t1 )

こんな感じで考えて実際に動作はしているようですが
もう少しスマートな書き方はありますでしょうか。

環境はmysql5を使用しております。
509NAME IS NULL:2007/07/13(金) 00:06:13 ID:???
>>508
そんなスマートじゃない要求にスマートに応える方法などないと思うが。

蛇足ながらUNIONよりはUNION ALLのほうが多少速いかもね。
510NAME IS NULL:2007/07/13(金) 00:09:51 ID:???
>selectの結果セットに固定のデータを潜りこませたい場合
この時点ですでに泥臭いとオモ
511NAME IS NULL:2007/07/13(金) 00:18:10 ID:???
やはり無いですか
マスタテーブルを作って、そこに固定データを置いてjoinするのが正しいとは思うんですけどね
512NAME IS NULL:2007/07/13(金) 10:15:12 ID:???
それこそ泥臭い
513492:2007/07/15(日) 11:28:23 ID:???
>>493 さん
大分遅れましたが><
うろ覚え+実環境ではもっと複雑なため目安程度ですが
インデックス無し 旧:13s 新:100s以上(計測不能)
typeにインデックス 旧:12s 新:8.5s
type,time個別インデックス 旧:12s 新:4.7s
type+time複合インデックス 旧:11.7s 新:4.6s

旧SQLでは一度全件取得するため安定して遅く
type,timeをそれぞれ別々にインデックスと複合インデックスでは
速度的にはほとんど変わらないという結果が出ました。
その後、サブクエリの中で結合していたのを外に出したりして
最適化した結果1s以下で表示出来るようになりましたm(_ _)m
514NAME IS NULL:2007/07/17(火) 09:23:21 ID:2WDZRR0w
id, type というフィールドがあるテーブルで、
id は UNIQUE かつ type は UNIQUE でないとする。
このとき、それぞれの type から、1つだけレコードを取り出すには
どうしたらよいでしょうか。

つまり、
id=1, type=100
id=2, type=100
id=3, type=200
id=4, type=200
id=5, type=200
とあったとき、たとえば、
id=1, type=100
id=3, type=200
だけを選択するような SQL ってできますか?
SELECT DISTINCT type FROM table1;
までは分かったのですが、その後、各 type から
1つだけレコードを抜き出してくる方法がわからない。
515NAME IS NULL:2007/07/17(火) 09:30:03 ID:???
>>514

select min(id), type
from table1
group by type
516NAME IS NULL:2007/07/17(火) 09:50:00 ID:???
>>515 ありがとう!助かった。
517NAME IS NULL:2007/07/18(水) 16:28:20 ID:???
month, id, scoreの3つのカラムがあるテーブルがあります。
month毎にscoreが最大になる行をselectしたいのですが、
いい方法はないですか。idがいらなければgroup byとmaxで
いけるんですが、それだとidがわからなくなっちゃうの
ですよね。monthとmax(score)でもういちど探すのもなんか
馬鹿みたいだし...

518NAME IS NULL:2007/07/18(水) 16:38:12 ID:???
>>517
同一monthで最大scoreのidが複数存在するときの扱いは?
519NAME IS NULL:2007/07/18(水) 16:56:18 ID:???
postgresに関する質問です。
connectbyで階層問い合わせを実行すると、階層がカンマ区切りで表示されます。

------------
親キー ans
------------
1    1,2,3,4

これを次のようにカンマ区切りで複数行に分割するにはどうすればいいですか?

------------
親キー ans
------------
1    1
1    2
1    3
1    4
520NAME IS NULL:2007/07/18(水) 17:05:47 ID:???
>>518
idのもっとも小さい奴ということにします。可能?
521NAME IS NULL:2007/07/18(水) 17:59:17 ID:???
>>518
なんか、このスレではFAQ化してきてる内容だな。

select
month, max_score,
(select id from table where month = grouped.month and score = max_score order by id limit 1)
from
(
select
month, max(score) as max_score
from
table
group by
month
) as grouped
522NAME IS NULL:2007/07/18(水) 18:09:51 ID:???
>>521
副問い合わせで見かけ上はひとつのselectになってるとはいえ、結局のところ
monthとmax(score)でもう一度ひきなおすしかないんですね。SQLっていまいち
だなぁ... それとも超高度なオプティマイザが全部解析してmaxもとめたときの
行をおぼえて内部的には余計なqueryはせずに返してたりするんだろうか?
523NAME IS NULL:2007/07/18(水) 18:51:15 ID:???
>>522
mysql4.1.15では

EXPLAIN実行結果>
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived3> system 1
3 DERIVED table9 ALL 2 Using temporary; Using filesort
2 DEPENDENT SUBQUERY table9 ALL 2 Using where; Using filesort

内部的にselectは2回されてるね。インデックスつけても1回にはならなかった。
524NAME IS NULL:2007/07/18(水) 20:20:39 ID:???
>>522

select month, id, score
from table A
where not exists (
select * from table B
where B.month = A.month
and ( B.score > A.score or ( B.score = A.score and B.id > A.id ))
)

相関サブクエリはほとんどのDBMSで適切に最適化されるので、
(month,score,id)というindexがあればデータの偏りによらず
これが安定して速いし、(month,score)や(month)だけのindexしか
なかったとしてもそれなりのパフォーマンスが期待できる。

scoreもidも同じレコードがあったら両方出ちゃうけどね。
525NAME IS NULL:2007/07/18(水) 21:14:50 ID:???
PL/SQLの質問です

クエリ実行→結果を引数にして同じクエリ実行→・・・値がとれなくなるまでループ
のようなファンクションを作りたいのですが
やり方がよくわかりません

FUNCTION HOGE(A in number,B in number) RETURN VARCHAR2
IS
ZZ VARCHAR2(10);
CURSOR CC(AA in number,BB in number)
IS
SELECT DD||EE FROM FF WHERE GG = AA AND HH = BB;
BEGIN
OPEN CC(A,B);
FETCH CC INTO ZZ;
CLOSE CC;
RETURN ZZ;
END;

↑これは1回分だけです

引数はクエリ実行結果の値をAとBに分解するつもりですが
ループのところはどのような記述をすればいいのでしょうか?
526NAME IS NULL:2007/07/18(水) 21:54:30 ID:???
>>525
その質問内容では、どこでつまづいているのか理解できる人は少ないと思う。
ファンクションからファンクションを呼ぶ方法がわからんのか、
終了条件の分岐のロジックがわからないのか、そもそも再帰の概念自体わからないのか。
527NAME IS NULL:2007/07/18(水) 22:23:16 ID:???
>>525-526
「再帰呼び出し」でぐぐれ。でいいような。
528NAME IS NULL:2007/07/20(金) 14:24:37 ID:5xOFcdu1
COL_A COL_B COL_C
1、1、AAA1
1、2、AAA2
1、3、AAA3
1、4、AAA4
2、1、BBB1
2、3、BBB3
3、1、CCC1
3、2、CCC2
3、3、CCC3
4、1、DDD4

というデータがあり

1、4、AAA4
2、3、BBB3
3、3、CCC3
4、1、DDD4
このような感じで
COL_Aで重複があればCOL_Bが最大のもの
COL_Aで重複しないものであればそのまま
という結果を得たいのですが

SELECT COL_A, COL_.B, COL_C FROM テーブル名
GROUP BY COL_A, COL_.B;
こんな感じになるのでしょうがココから
どのようにSQLをくっつけていいか思いつかなくて手が止まっています。
どのような感じにすればいいんでしょうか?

ACCESS2000を使用しています。
529NAME IS NULL:2007/07/20(金) 15:10:56 ID:???
>>528

マジでw「重複してるときは一行だけ取り出す」関連の質問多すぎwwwww
質問者が全部同一人物なのかと疑ってしまうくらいにwwwwうはwwおkwwww
誰が教えてやるもんかwwwwwwwwwww





























SELECT COL_A, COL_B_MAX,
(SELECT TOP 1 COL_C FROM テーブル名 WHERE COL_A = GROUPED.COL_A AND COL_B = COL_B_MAX)
FROM (
SELECT COL_A, MAX(COL_B) AS COL_B_MAX FROM テーブル名
GROUP BY COL_A) AS GROUPED;
530NAME IS NULL:2007/07/20(金) 15:19:55 ID:5xOFcdu1
>>529
そのツンデレぶりにはたいへん驚かされましたが…

なるほど!
FROM のテーブルをサブクエリで一意に取ってきたデータに置き換えるんですね
で、名前はそのキーから取得すると・・・

目から鱗です!
ありがとうございました
531NAME IS NULL:2007/07/20(金) 21:53:50 ID:ZGZ4CJa3
psqlについて質問です
psqlでDBを作りたいのですが
データを入力する際に、invalid byte sequence for encoding "EUC_JP"というエラーが出て日本語の入力ができません。

使用しているOSは Fedora Coreで
文字コードを UTP-8を変換しようとしています

よろしくお願いします。
532NAME IS NULL:2007/07/21(土) 01:00:47 ID:???
どういう環境かよくわからんが、
クライアントの文字コードにあわせて、set client_encoding TO 'UTF-8'; とかやってみそ
つーか、PostgreSQLのスレで聞いたほうがいいと思うぞ
533NAME IS NULL:2007/07/21(土) 04:02:10 ID:???
以下のようなSQLを作成しようとして途方に暮れています。
・カテゴリごとに最古のn個(ここでは2個としておきます)のレコードを含む結果を1回のSQL文で取得したい。
・結果レコードの総数は最大で(カテゴリの数xn)になる。
・結果はカテゴリ、日付順で返す
・MySQL5.0用 できれば汎用

テーブルはたとえばこんな感じ
id category tm(日付)
1 1 4/ 1
2 1 3/10
3 1 10/ 1
4 2 6/ 1

得たい結果はこんなかんじ
(カテゴリー1の第3位となるid=3が除外される)
2 1 3/10
1 1 4/ 1
4 2 6/ 1

SELECT * FROM timetest TX WHERE tm<=
(SELECT MAX(T.tm) FROM
(SELECT tm FROM timetest T1
WHERE T1.category = TX.category
ORDER BY tm LIMIT 2
) AS T)
ORDER BY category, tm

とりあえず上記のようなSQL文で試してみたのですが、
サブSELECTのWHEREのところでTXを参照できないようです。

グループごとの第2位の日付がわかる表ができれば、
後はJOINとかでなんとかなりそうなのですが、
MAX,GROUP BY,LIMITを併用すると、グループごとにLIMITが効いてくれず、方法がわかりません。
お願いしますm(_ _)m
534NAME IS NULL:2007/07/21(土) 04:21:18 ID:???
>>533
SELECT * FROM
(SELECT (SELECT count(*) FROM timetest WHERE category=T1.category AND tm<=T1.tm) AS num,category ,tm FROM timetest AS T1 ) AS T2
WHERE num <= 2;

DBによってはWHERE句をもうひとつ中に入れて、
大外のSELECTは要らないけどな。
535533:2007/07/21(土) 04:43:46 ID:???
>>534
おお、ありがとうございます!
たしかに期待通りの結果になりました。結構びっくりです。

ところで、解釈上やや複雑そうに見えるのですが、
この方法はDB内部でうまく最適化されてくれるのでしょうか?

カテゴリごとに分けてSELECTを呼ぶ場合より時間がかかったりしなければ問題はないのですが。
(カテゴリの数は10程度として)

何にせよありがとうございます。COUNTを使うというのは、目から鱗です。
536525:2007/07/21(土) 19:57:22 ID:???
事故解決しますた
文法ミスでした

>>526
すんません、切羽詰ってて説明不足でした

PL/SQLの文法解説してるサイトってあまりないですね

Oracleのマニュアルが凄い充実してることに驚いたのですが
初級者には全体的に理解し難い感じです

これを読みやすくしたような書籍無いでしょうか?
使用例も多いと助かります

>>527
再帰は知ってたけど、文法がわからんかったのです
537NAME IS NULL:2007/07/21(土) 20:25:23 ID:???
なんかDB2で仕事しているとOracleの書籍の多さには羨ましい限りなのだが・・・。

しかし回答者はエスパーじゃないんだからテメエで本屋逝って探せよ。
538sage:2007/07/22(日) 21:13:07 ID:FhbbgWhN
SQLでプログラム言語でいうところのif文の命令あるの?

例えば、もしAというカラムの値が1なら0を出力する。
もしAというカラムの値が2なら1を出力する。。みたいな
539NAME IS NULL:2007/07/22(日) 21:20:20 ID:???
>>538
CASE(SQL-92)
540NAME IS NULL:2007/07/22(日) 22:45:53 ID:???
>>538
DECODE
541NAME IS NULL:2007/07/22(日) 22:50:18 ID:CkTSSgqR
只今勉強中の初心者です。教えて下さい。
下のような表があって、それぞれの点数の部分を
選択している科目には点数を、選択していない部分は
NULLを表示したいのですが、どうしたらよいのでしょうか?

↓この表を      ↓このように表示したいのです

氏名 科目 化学 生物  氏名 科目 化学 生物
-- -- -- --      -- -- -- --
AAA 化学 30  30   AAA 化学 30 NULL
BBB 物理 50  50   BBB 物理 NULL 50
CCC 化学 90  90   ・・・
DDD 化学 80  80
EEE 物理 70  70
542NAME IS NULL:2007/07/22(日) 22:56:39 ID:???
select
氏名, 科目,
case 科目 when '化学' then 化学 else null end as 化学,
case 科目 when '生物' then 生物 else null end as 生物
from 表
order by 氏名;

typo あったらすまん。
543538:2007/07/22(日) 23:18:33 ID:FhbbgWhN
>>539,540
dクス
544NAME IS NULL:2007/07/22(日) 23:42:32 ID:???
>>542
group by しないと無理じゃね?
545NAME IS NULL:2007/07/23(月) 00:45:53 ID:???
取扱商品
品番 品名 売価
----
1 ペン 100
2 消しゴム 100
3 鉛筆 50
4 ノート 150

売上
店舗番号 品番 個数
------- ----
1 1 1
1 2 1
1 3 2
1 4 1
2 1 1
2 4 5
3 1 3

↑のテーブルから商演算を用いて、全種類の商品を売った店舗番号を抽出したいのですが
旨くいきません・・・・どなたかご教授お願いします。
代数演算は分かりづらい。。
546NAME IS NULL:2007/07/23(月) 01:01:36 ID:???
select 店舗番号
 from (select 店舗番号, 品番
    group by 店舗番号, 品番)
group by 店舗番号
having count(店舗番号) = (select count(*) from 取扱商品)
547NAME IS NULL:2007/07/23(月) 01:17:34 ID:???
俺の場合商演算はNOT EXISTSのネストでやってるなぁ。

select distinct 店舗番号 from 売上 AS 売上A
where not exists(
 select * from 取扱商品
 where not exists
 (select * from 売上 where 店舗番号=売上A.店舗番号 AND 品番=取扱商品.品番)
)
548NAME IS NULL:2007/07/23(月) 01:37:46 ID:???
>>546,547
ありがとうございます。
教科書もNOT EXISTS を使ってるみたいなんですけど
どうも分かりづらいです。。。
何か作り方の手順があればやりやすいのに・・
549541:2007/07/23(月) 12:06:02 ID:RqjUNL36
>>542さん
>>544さん遅くなりまして申し訳ございません
CASE〜でできました。ありがとうございました。
550533:2007/07/24(火) 04:58:39 ID:???
>>534-535 について続報。
速度テストしてみましたが、
レコード1万ぐらい入れて、カテゴリあたりのレコードが十分多い状況だと、
実行に10秒程度かかるようです。(MySQL5.0 ノートPC)

一応インデックスはちゃんと張ってるつもり。
多分内部処理でレコードごとにループしちゃってる?

#もし同じ事を行う高速な手法(外部でループする以外)があれば教えてください・・・

いずれにしても参考になりました。ありがとうございましたm(_ _)m
551NAME IS NULL:2007/07/24(火) 06:44:51 ID:???
>>550
select t1.id, t1.category, t1.tm
from timetest t1, timetest t2
where t1.category = t2.category
and t1.tm >= t2.tm
group by t1.id, t1.category, t1.tm
having count(*) <= 2
とか。
脳内で書き方変えただけで、テストしてないけど。
552NAME IS NULL:2007/07/24(火) 07:08:24 ID:???
row_number partition が使える処理系なら効率よく処理できるのだが、
そうじゃない処理系でデータ数が多いなら、シーケンシャルに全件順に読んで
ユーザープログラムで読み飛ばしたほうが速いケースもある。
553533:2007/07/24(火) 15:31:17 ID:???
>>551
ありがとうございます。
例の1万件でテストしてみますと、ほぼ >>534 と同等の結果でした。
MySQLの内部処理的には似た感じなのかも。

>>552
この処理を1回で高速に処理するにはMySQLの機能不足という感じでしょうか。

DBにはできるだけ負荷をかけたくない処理ですので、
今のところ カテゴリ抽出→カテゴリごとにORDER BY&LIMIT とかでなんとかしようと思っています。
554NAME IS NULL:2007/07/24(火) 15:52:16 ID:???
>>553
念のため確認だが、
>一応インデックスはちゃんと張ってるつもり。
とのことだけど、(category, tm)の複合インデックスだよね?
このインデックスがあれば、1万レコードでも10秒てのは
遅すぎるような気がするのだが。
ちなみにDBMSによっては、(category, tm, id)でさらにselectが速くなる場合もあるけど
ほとんどの場合は大差ないかな。
555533:2007/07/24(火) 17:01:17 ID:???
>>554
実際の問題ではカテゴリが2つあり、
(category1, category2, tm) の複合インデックスを作っています。
このため、テーブルが多少違う部分はSQLも書き換えていますが、ストレートな変換のみです。

ためしにこのインデックスを外してみると >>534 の実行に72秒かかったので、効いているようです。
>>551 のほうは87秒でした。
ただしテスト環境は3年前のノートPC(1.3GHz)です。最近のPCでやってみると時間は半分ぐらいです。

作成したデータは、カテゴリの組(category1, category2)ごとにtmの異なるレコードが1000件あるデータです。
カテゴリの組は全部で9組なので合計9000件です。
556NAME IS NULL:2007/07/24(火) 17:52:40 ID:???
>>555
そっか、余計な心配だったか。
お詫びというわけではないが、別解を書いてみた。
まーかなりネタも混ざってるし、仕事でこんなSQL書いてるやついたら
俺は殴るかもしれんが。

select id, timetest.category, timetest.tm
from timetest
inner join
(select category, min(tm) as min_tm from timetest group by category) t1
on
t1.category = timetest.category and t1.min_tm = timetest.tm
union all
select id, timetest.category, timetest.tm
from timetest
inner join
(select category, min(tm) as min_tm
from timetest
where id not in
(
select id
from timetest
inner join
(
select category, min(tm) as min_tm
from timetest
group by category
) t1
on t1.category = timetest.category and t1.min_tm = timetest.tm
)
group by category
) t2
on t2.category = timetest.category and t2.min_tm = timetest.tm
order by category, tm
557533:2007/07/24(火) 18:35:33 ID:???
>>556
なんかすごいのきた^^;

後で読み解いてみます。
ありがとうございますm(_ _)m
558NAME IS NULL:2007/07/25(水) 22:36:43 ID:oJzPaskR
今仕事で複数テーブルから結果を求めるSQLを作っているのですが07年合計金額の結合部分でよく分からないのでご教授ください。

欲しい結果
大分類名 小分類名 06年合計金額 07年合計金額
-------- -------- ------------ ------------
 AAA     A     20000    30000
 AAA     B     30000    10000
 BBB     A     15000    20000

参照元テーブル
テーブル1
大分類コード 小分類コード 年度 金額

テーブル2
年度 大分類コード 大分類名

テーブル3
年度 小分類コード 小分類名

select a.大分類名,b.小分類名,sum(DISTINCT c.金額)

from
(テーブル1 c INNER JOIN テーブル2 a on c.年度 = a.年度 AND
c.大分類コード = a.大分類コード)
INNER JOIN テーブル3 b on c.年度 = b.年度 AND
c.小分類コード = b.小分類コード

where
c.年度 = 2006
GROUP BY
a.大分類名,b.小分類名,c.年度,a.大分類コード,b.小分類コード

ORDER BY
a.大分類コード,b.小分類コード ASC


大分類名 小分類名 06年合計金額
-------- -------- ------------
 AA    A     20000
 AA    B     30000
 BB    A     15000

↑のSQLで↑までは出せたのですが再度テーブル1から07年合計金額を出す方法が分かりません。
UNIONを使った方法でやりたいのですが分からなかったので申し訳ありませんがご教授お願いいたします。
559558:2007/07/25(水) 22:37:51 ID:oJzPaskR
SQL言語はOracleです。
560NAME IS NULL:2007/07/25(水) 23:06:14 ID:???
>>558
テーブル2とテーブル3のデータの保持形式がよーわからん。

テーブル2
年度 大分類コード 大分類名
2006 AAA 2006年のときの名前
2007 AAA 2007年のときの名前

みたいになってるってことか?
なら、今回は2007年のときの名前を表示したいと勝手に決め付けて書くとこうなる。

select 大分類名, 小分類名,
(select sum(金額) from テーブル1 where 大分類コード = t1.大分類コード and
小分類コード = t1.小分類コード and 年度 = 2006),
(select sum(金額) from テーブル1 where 大分類コード = t1.大分類コード and
小分類コード = t1.小分類コード and 年度 = 2007)
from (select distinct 大分類コード, 小分類コード from テーブル1) t1
inner join テーブル2
on テーブル2.大分類コード = t1.大分類コード
and テーブル2.年度 = 2007
inner join テーブル3
on テーブル3.小分類コード = t1.小分類コード
and テーブル3.年度 = 2007

履歴がないものはnullじゃなくて0を表示したいならnvl関数。
561558:2007/07/25(水) 23:24:16 ID:oJzPaskR
>>560
さっそくレスありがとうございます。
データを書いた方が分かりやすかったですね。申し訳ありません。
テーブル2
年度 大分類コード 大分類名
---- ------------ --------
2006    10000  AAA
2006    20000  BBB
2007    10000  AAA
2007    20000  BBB

テーブル3
年度 小分類コード 小分類名
---- ------------ --------
2006    10000  A
2006    20000  B
2007    10000  A
2007    20000  B

先ほど書いた現段階の出力の部分に誤りがありました。性格には下記のようです。
大分類名 小分類名 06年合計金額
-------- -------- ------------
 AAA    A     20000
 AAA    B     30000
 BBB    A     15000
562NAME IS NULL:2007/07/25(水) 23:29:17 ID:???
>>561
推測したとおりで大丈夫だったってことかな。
なら、>>560 でいけると思うんだが。
unionを絶対に使わないといけないわけじゃないんでしょ?
563558:2007/07/25(水) 23:36:24 ID:oJzPaskR
>>562
多分大丈夫だと思います。明日さっそく試してみます。
それと申し訳ないのですがunionを使った方法も教えていただけないでしょうか?
564NAME IS NULL:2007/07/25(水) 23:45:09 ID:???
>>563
出したい結果を考えると、unionを使う意味、というか使う余地はないのだが。
2006年と2007年を縦に並べるなら使うこともできるだろうけど。
横に並べたいのなら、サブクエリやファンクションで実現するのが一般的。
565558:2007/07/26(木) 07:12:29 ID:sS8BKlCY
>>564
上司に昨日尋ねたらunionで出来るという事なので参考までに聞いたのですが横だと意味がないんですね。
勉強になります。
教えていただき助かりました。ありがとうございました。
566NAME IS NULL:2007/07/26(木) 12:15:13 ID:XmvrlBD0
テーブルAの項目をテーブルBの項目でUpdateしたいのですがどうすればいいのでしょうか。
AとBはジョインできますが両テーブル共に複数レコード存在します。
567NAME IS NULL:2007/07/26(木) 13:33:35 ID:???
>>566
update...from句
568566:2007/07/26(木) 14:34:42 ID:???
>>567
できました。
ありがとうございました。
569NAME IS NULL:2007/07/26(木) 21:17:38 ID:???
項目1 項目2 金額1 金額2
------ ------ ------ ------
 0001 合計  6000  600
 0001  01  1000  100
 0001  02  2000  200
 0001  03  3000  300
 0002 合計  15000 1500
 0002  01  4000  400
 0002  02  5000  500
 0002  03  6000  600

上記のような結果をoracle10gで出したいのですが出せずに困っています。
GROUP BY でROLLUPを使用し出力をしようとすると

項目1 項目2 金額1 金額2
------ ------ ------ ------
 0001  01  1000  100
 0001  02  2000  200
 0001  03  3000  300
 0001 NULL   0  600
 NULL NULL   0   0
以下略

と上記のような形になってしまいます。金額1と金額2は同テーブルでサブクエリーを使用し出力しています。
申し訳ありませんがどなたが力をお貸しください。
570NAME IS NULL:2007/07/26(木) 21:34:14 ID:???
>>569
元のクエリも書いた方がレスが付きやすそうだが
571NAME IS NULL:2007/07/26(木) 22:09:34 ID:???
手元に元のクエリが無いので記憶的で簡単なものになりますが

Select 項目名1,項目名2,SUM(金額1),SUM(金額2)
FROM(
SELECT a.項目No AS 項目No,
    a.項目2No AS 項目No2,
    a.項目1 AS 項目名1,
    a.項目2 AS 項目名2,
    sum(a.金額) AS 金額1,
    0 AS 金額2,
from テーブル1 a,
   テーブル2 b,
   テーブル3 c
where
   a.項目No = b.項目No AND
   a.項目2No = c.項目2No
Group By
    a.項目No,a.項目2No,a.項目1,a.項目2

UNION

SELECT a.項目No AS 項目No,
    a.項目2No AS 項目No2,
    a.項目1 AS 項目名1,
    a.項目2 AS 項目名2,
    0 AS 金額1,
    sum(a.金額) AS 金額2
from テーブル1 a,
   テーブル2 b,
   テーブル3 c
where
   a.項目No = b.項目No AND
   a.項目2No = c.項目2No
Group By
    a.項目No,a.項目2No,a.項目1,a.項目2
)
Group By ROLLUP(項目No,項目2No),項目名1,項目名2
Order By 項目No,項目2No

大方このようなクエリだったと思います。
572NAME IS NULL:2007/07/26(木) 22:32:50 ID:???
>>571
テーブル2と3が、joinしてるのに結果に使われていないのは謎。
まぁ、「キーが存在することが条件」てのならわかるけど。

でrollupについてだが、それをどう直せばいい、というよりは、まず
[項目No1 項目No2 金額1 金額2]
の結果を出力するクエリを作ってみることをお勧めする。
つまり、項目名1,項目名2を考えずにってことな。
なんかrollupがごちゃごちゃしてるのがまずいと思うんだ。
これがうまくいってから、項目名1,項目名2をもってくることを考えようぜ。
573NAME IS NULL:2007/07/26(木) 22:35:45 ID:???
>>572
さっそくありがとうございます。
実際は項目1と項目2の部分に該当した名前が入るんですけど分かりやすいようにコードとして表記させていただきました。
574NAME IS NULL:2007/07/26(木) 23:02:35 ID:???
>>571
それじゃあfrom句の中の一個目のselectでの「金額1」と
二個目のselectでの「金額2」が同じじゃん。

>>569の結果を出したいときのテーブル1のデータ内容はどんなん?
575NAME IS NULL:2007/07/26(木) 23:11:52 ID:???
>>574
Where句の条件が足りなかったですね。
上のWhere句に
a.toshi = 2006
下のWhere句に
a.toshi = 2007
という感じです。
金額1には前年度、金額2には今年度という感じです。

テーブル1としては

項目No 項目2No 年 金額

必要なフィールドだけを取り出すと上記の形になります。
576NAME IS NULL:2007/07/26(木) 23:30:15 ID:???
>>575
つまりテーブル2とテーブル3はそれぞれ項目Noから名前をとってくるだけか。
だったらこんな(↓)感じのやつに後から名前をくっつけたら?
>>572 もそういうことを言っているんだと思うけど。

select 項目No,
    項目2No,
    sum(case when 年 = 2006 then 金額 else 0 end) as 金額1,
    sum(case when 年 = 2007 then 金額 else 0 end) as 金額2
from テーブル1
group by rollup(項目No, 項目2No)
order by 項目No, 項目2No
577NAME IS NULL:2007/07/27(金) 17:57:43 ID:SeTyNiJf
すいません。質問です。宜しくお願いします。
ID CODE フラグ
1  1 0
1 2 0
1 3 1
2 1 0
2 2 0
3 1 0
3 2 1
上記のようなテーブルからIDでグループ化して
フラグが1のデータがあった場合はONを全部0だったらOFFをだして
ID 結果
1 ON
2 OFF
3 ON
のような結果をだすにはSQLをどのように書いたらいいでしょうか?
お願いします
578NAME IS NULL:2007/07/27(金) 18:00:40 ID:SeTyNiJf
あ、MAXもってくればいいのか。
579NAME IS NULL:2007/07/27(金) 18:10:26 ID:???
ハヤ!
580NAME IS NULL:2007/07/28(土) 09:22:39 ID:eFtPhvG6
MySQLを利用しています。gidごとに値を積算して積算順にソートを
掛けたいのですが、下記だとgidごとにソートかかかってしまいます。
descと組み合わせるとエラーになるし、どうすればいいんでしょう。

select sum(data),gid from user_tp group by gid;
581NAME IS NULL:2007/07/28(土) 12:04:59 ID:???
>>580
select sum(data),gid from user_tp group by gid order by sum(data) desc;
582NAME IS NULL:2007/07/28(土) 12:24:35 ID:???
>>581
アドバイスありがとうございます。
ただ、上記実行してみましたが

ERROR 1111 (HY000): Invalid use of group function

となってしまいます。もしかして、MySQLのバージョンが古い!?(T.T)
ちなみにバージョンは、4.1.20です。
583NAME IS NULL:2007/07/28(土) 12:33:25 ID:???
>>581
解決しました!

select sum(data) as sum,gid from user_tp group by gid order by sum desc;

で関数値にエイリアスを切ったら解決でした!
本当にありがとうございました。助かりました。感謝です!
584NAME IS NULL:2007/07/28(土) 12:39:24 ID:???
>>582
それは4.xのバグらしい。
回避策は>>583
585NAME IS NULLPO:2007/07/28(土) 17:38:07 ID:crv3ux+p
オラクルを利用しています。質問があります。

以下の通り実行する場合にテーブルをロック、アンロックする方法を教えて下さい。

1.テーブルAをロック

2.テーブルBを更新(UPDATE)

3.テーブルAにSELECT文を実施

4.テーブルAのロックを解除。
586NAME IS NULL:2007/07/28(土) 18:53:52 ID:???
>>585
テーブルロックは LOCK TABLE 文。
アンロックは COMMIT または ROLLBACK。

しかしテーブル全体をロックしなければならないっていう設計はちょっとどうかと。
せめて 1. の代わりに SELECT 〜 FOR UPDATE ぐらいにしたほうがマシかも。
まあ詳しい要件が分からんので何とも言えんけど。
587NAME IS NULL:2007/07/28(土) 20:05:45 ID:???
SP実行開始時には、更新を行うテーブルは必ずテーブルロックを行う事。

という共通規約が存在する漏れのプロジェクト・・・
588NAME IS NULL:2007/07/28(土) 20:31:54 ID:???
>>587
かかわりたくない池沼なプロジェクトだな。
589NAME IS NULL:2007/07/28(土) 20:37:39 ID:???
あまり優秀じゃないプログラマを何人も使うようなプロジェクトじゃよくあること。
590NAME IS NULL:2007/07/28(土) 22:33:37 ID:???
それはあまり優秀どころか、ロックの存在をしらなくて、バッチ処理しか経験のない
元COBOLerの素人集団では・・・。
591名無しさん@そうだ選挙に行こう:2007/07/29(日) 07:47:30 ID:???
>>587のところがそうなのかは知らないが、デッドロックを防ぐために
トランザクションの最初に特定の順序でテーブルロックするのは
普通だろ。
592名無しさん@そうだ選挙に行こう:2007/07/29(日) 08:11:36 ID:???
>>591
「必ずテーブルロックを行う事」っていう前提があればそうするかもしれないけど
その前提がそもそもバッチ志向から抜け出せていないっていう話では?
593名無しさん@そうだ選挙に行こう:2007/07/29(日) 09:15:41 ID:???
>>592
なぜここでバッチが出てくるのかわからないが、テーブルロックでなければならない
理由は、単にリソースのロック獲得順を明示的に制御できるのがテーブル単位だからだろ。
594名無しさん@そうだ選挙に行こう:2007/07/29(日) 09:22:15 ID:???
>>593
Oracleとかなら行単位でもロックできるけどね。

てかスレ違いだな。
595名無しさん@そうだ選挙に行こう:2007/07/29(日) 09:47:50 ID:???
ここで言ってるストアドプロシージャが、全件カーソルをまわして
1件ずつ更新して行くようなバッチ処理を想定してるのだろうな。
こういう処理が頻発するようならシステムの基本設計に問題があるとしかいえないな。
596名無しさん@そうだ選挙に行こう:2007/07/29(日) 09:53:39 ID:???
あー、なんか根本的に理解されていないみたいだけど、そういう理屈を全員に
教え込むのは大変だから、「更新するテーブルは最初にこの順番でロックすること。
これが決まりだ。」ってなるわけよ。
597名無しさん@そうだ選挙に行こう:2007/07/29(日) 09:57:44 ID:???
>>596
いや、それは分かるよ。
でも、そんなルールを作らなければならないようなプロジェクトには
できれば関わりたくないよね、と。
598名無しさん@そうだ選挙に行こう:2007/07/29(日) 12:33:19 ID:???
あ、>>596>>594宛ね。
この場合、明示的行ロックの機能があるかどうかってのは関係ないわけなんで、
そういうセリフが出てくるということは、まさにそういうプロジェクトで想定している
人材なのではないかと。
599名無しさん@そうだ選挙に行こう:2007/07/29(日) 13:50:21 ID:???
>>598
えと、俺は>>592=>>594=>>597なんだけど、
このスレにも「そういう人」がいることが分かって、
かと言ってこのスレ違いな議論をこれ以上続けるのもどうかと思って、
やや強引に議論を終わらせようとしただけなんだ。
600名無しさん@そうだ選挙に行こう:2007/07/29(日) 15:33:35 ID:???
MySQL4.1を利用しています。教えてください。

ある問題の過去問で

Q:
月間の残業時間が75時間以上の社員の社員コードと氏名を求めるSQLを実行したところ、
エラーで返された。
なぜエラーになったのか、20文字以内で記せ。

入力SQL文:
select 社員コード,氏名 from 社員テーブル where 社員コード = (select 社員コード from 勤務実績テーブル group by 社員コード having sum(残業時間) >=75);


なお、社員テーブルには
社員コード,氏名,課コード

勤務実績テーブルには
社員コード,年月日,所定労働時間,残業時間であり
各社員の1日ごとの所定労働時間,残業時間が1レコードとして1か月分入っている。

課テーブルには
課コード,課名

が入っている。

***
このとき、正しいSQL文はどうなるのでしょうか?
お願いします。
601名無しさん@そうだ選挙に行こう:2007/07/29(日) 15:56:20 ID:???
>>600
= を in に変えればとりあえず動くには動くだろうな。
602名無しさん@そうだ選挙に行こう:2007/07/29(日) 16:00:50 ID:???
>>600
=をINにする。理由くらい自分で調べろ。
603NAME IS NULL:2007/07/30(月) 11:34:34 ID:???
すいません。
顧客情報管理のDBを作成していて、
文字列の結合でつまってしまいました。。

Name Hobby
--------------------
aaaa 読書
aaaa 映画
bbbb 水泳
--------------------

上記のようなDBが有った場合に、

Name Hobby
--------------------
aaaa 読書、映画
bbbb 水泳
--------------------

と、表示させるSQLを教えてください。
異なるレコードの文字列結合が、うまく出来ない・・・
604NAME IS NULL:2007/07/30(月) 12:00:08 ID:???
>>603
普通にName別にHobbyの内容を取得した後、
アプリケーション側で処理した方が楽だと思われ。
つ〜か、Nameが同一のレコードが1億件存在したら、
それだけ繋ぐ、って事だろ?正気の沙汰じゃないwww

俺なら
aaaa 読書 
bbbb 水泳 
が既存データとして存在していて、
そこに
aaaa 映画
を追加する必要が生じたら、
aaaa 読書、映画 
となるように最初からデータ操作するが。
605NAME IS NULL:2007/07/30(月) 12:10:30 ID:???
>>604
おっしゃる事は、ごもっともなのですが、
どうやら仕様上そういう風にSQLを練らないといけないようで。。。
(HOBBYを個々に扱う場所も有るから、まとめて登録も不可のようです)
CONCATをうまく使って、レコード間の結合なんて出来ないかしら?と、思って
調べているのですが、自分の技術力ではサッパリです。

ご回答、ありがとうございます。
606NAME IS NULL:2007/07/30(月) 12:42:19 ID:???
group_concat(Hobby separator '、')
607606:2007/07/30(月) 13:13:46 ID:???
ゴメン、MySQLスレと勘違いしてた
group_concatとRDBMS名でググればヒントあるかも
608NAME IS NULL:2007/07/30(月) 14:04:48 ID:???
>>606
調べてみました。
残念ながら、当方、postgresなので使えない様子。
DBの種類は最初に書くべきでした。
申し訳ないです。

ひきつづき、調べます。
ヒント、ありがとうございます。
609NAME IS NULL:2007/07/30(月) 16:31:56 ID:???
PostgreSQLでは複数行の文字列連結はなかったはず。
PL/pgSQLなどで関数自作するしかないな。
610NAME IS NULL:2007/07/30(月) 16:33:46 ID:w7x3AyYR
>>198とよく似た疑問なんですが
1列目…2つの日付の差を表示
2列目…それが7日以上差があれば○と表示
というSQL文で(DBMSはOracleです)

SELECT TO_DATE(DATE1,'YYYYMMDD')-TO_DATE(DATE2,'YYYYMMDD'),
CASE WHEN TO_DATE(DATE1,'YYYYMMDD')-TO_DATE(DATE2,'YYYYMMDD') >= 7
THEN '○' ELSE NULL END FROM TABLE1 ...

この重複しているTO_DATE〜の2回目をもっと簡潔に書く方法は
やっぱりないんでしょうか?
611NAME IS NULL:2007/07/30(月) 17:53:56 ID:???
>>610
Oracleで動くかどうか知らんが、FROM句のない相関クエリで多少短くなる。

SELECT TO_DATE(DATE1,'YYYYMMDD')-TO_DATE(DATE2,'YYYYMMDD') AS ITV,
(SELECT CASE WHEN T1.ITV >= THEN '○' ELSE NULL END) FROM Table1 AS T1;
612NAME IS NULL:2007/07/30(月) 17:56:02 ID:???
あ、うそ。T1.ITVってないな。
ゴメソ。
613NAME IS NULL:2007/07/30(月) 19:27:36 ID:???
>>610
サブクエリにして別名つけるとか。

SELLECT ITV, CASE WHEN ITV >= 7 THEN '○' ELSE NULL END
FROM (SELECT TO_DATE(DATE1,'YYYYMMDD')-TO_DATE(DATE2,'YYYYMMDD') AS ITV FROM TABLE1 ... )
614NAME IS NULL:2007/07/30(月) 20:07:51 ID:???
>>610
システム内でその演算の出現頻度が高いなら、ファンクション化。
615NAME IS NULL:2007/07/31(火) 12:22:42 ID:JPI88QGA
SQL文に現在時刻を使う場合、
アプリ側かSQL側(CURRENT_DATEなど)、どちらで取るほうがよいでしょうか?

ちなみに私の環境は、アプリ側はPHP5、MYSQL5で、
WEB、DBとサーバーが別です。

私の環境において、一般的に、どちらでも構いません。
理由をつけてご回答頂けると幸いです。
よろしくお願いします。
616NAME IS NULL:2007/07/31(火) 12:31:54 ID:???
>>615
おれはサーバー側で取るようにしてる。理由は、クライアントの時間が信用できないから。
ま、Web サーバーがひとつだけなら大丈夫なんだろうけど。
617NAME IS NULL:2007/07/31(火) 14:02:11 ID:???
>>615
何を重視するかによるかな。
DBに対してアクセスするクライアントが複数ある場合は、
DBの時刻関数を使うことで一貫性が保てる。

逆にアプリで時刻を取得した方がいいケースとしては、
複数のクエリを発行するときにその中で現在時刻が要求され、
それぞれが同じである必要がある場合など。
動的に時刻を取得すると、毎回違う時刻になっちゃうからな。
618NAME IS NULL:2007/07/31(火) 15:13:45 ID:???
Oracle10gです。

カーソル定義の際に 複数テーブル(5つ位)をJOINで結合させたカーソルに対
して "FOR UPDATE" 句を使用し、カーソル内で CURRENT行 に対する UPDATEを
行いたいんですが。

UPDATE出来るテーブル、出来ないテーブルの違いは何でしょうか。
例えばこれが2つのテーブルA・Bで、結合結果がA:1対B:多となるような場合に
テーブルAに対して CURRENT OF cur でUPDATE出来ないのは分かるんですが。

単純に「UPDATEしたら複数行が更新されそう」なTBLはUPDATE不可、と考えて
大丈夫でしょうか?
619615:2007/07/31(火) 17:18:25 ID:???
>>616,617
ありがとうございます。
環境により使い分けるってことですね。ごもっともです。
私の場合、特にMYSQLのNOW()や型のTIMESTAMPなどは便利なので、
何とかSQL側で使ってやりたいというのが本音ですが、
逆にログに出したときに分かりにくい、保守性も少し下がるというのが
懸念点です。
620NAME IS NULL:2007/07/31(火) 17:24:26 ID:???
>逆にログに出したときに分かりにくい、保守性も少し下がるというのが
kwsk
621615:2007/07/31(火) 17:46:17 ID:???
>>620
アプリ側で時間を取得して実行した場合には、ログには
 SELECT * FROM TABLE WHERE time > '2007-07-31 17:42:00'
のように出ますが、SQL側で取得した場合には
 SELECT * FROM TABLE WHERE time > NOW()
のように、これを見ただけではどのようなデータが出たのか分かりくいと思いまして。
まあ、そのログの時間を考えれば分かるのですけど。

また、保守性に関してですが、アプリ側だけで考えた場合には
何をしているのか読みにくいのかなぁと思いまして。
特にSQLはほとんど基本だけ押さえてそれ以上は勉強しない人が多いようですし。

ちょっと断定するほどの理由にはなりませんね、申し訳ないです。
622NAME IS NULL:2007/07/31(火) 20:17:31 ID:gWtvLAd+
PostgreSQL8.2.3です。

lhs,rhs,result
---------------
1,3,0
4,1,0
1,0,0
8,8,0

というテーブルに以下のSQLを流してresultを一括更新しようと思っています。
UPDATE テーブル名 SET result = lhs / rhs;

しかし1行でもrhsに0が入っていると、division by zeroのエラーが出てしまいます。
その1行が更新されないのは仕方ありませんが、他の行まで更新されないので困っています。
なにか良い方法は無いでしょうか?
623NAME IS NULL:2007/07/31(火) 20:19:55 ID:???
> UPDATE テーブル名 SET result = lhs / rhs;
where rhs <> 0

でいいやん
624NAME IS NULL:2007/07/31(火) 20:19:56 ID:NYEBxcjn
access2000のMDBファイルにCreate文を投げて10進型のカラムを10桁&小数点3で作成したいのですが
decimal という型はないようなのです
numericだとどうもDoubleになっているようだし・・・
すみませんがご存知の方お教え願えませんか?
625NAME IS NULL:2007/07/31(火) 20:22:08 ID:???
>>624
10進型なら、Currency になるはず。桁数の指定はできないよ。
626NAME IS NULL:2007/07/31(火) 20:33:57 ID:???
>>618
更新可能な結合ビュー(↓)と同じ条件と思っていいんじゃない?知らんけど。
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19215-02/schema.htm#5107
627624:2007/07/31(火) 20:48:47 ID:NYEBxcjn
>>625
レスありがとうございます。
やってみたんですが、どうも通貨型になっているようです。
説明の方法が悪かったような気がするのですが
10進型というのはACCESSのデザインでいうところの
数値型のカラムでフィールドサイズが10進型ということなのです・・・
説明悪くてごめんなさい
628NAME IS NULL:2007/08/01(水) 01:40:00 ID:???
すいません。

date data
--------------------
7/24 aaa
7/25 bbb
7/26 ccc
--------------------

上記のようなDBが有った場合に、

date data
--------------------
7/25 bbb
7/26 ccc
7/27 ccc
--------------------

一番古いレコードを削除して、新しいレコードを
コピーしたあと、日付を+1したいのですが
削除は出来ても、dateがユニークであるため
コピーして更新が出来ません・・・。
どうしたら良いのでしょうか?
629NAME IS NULL:2007/08/01(水) 02:01:52 ID:???
>>628
dateがDATE型かどうかわかんらが、こういうことかな?
INSERT INTO Table SELECT date+ interval'1 day' FROM Table WHERE date=(SELECT max(date) FROM Table);
630NAME IS NULL:2007/08/01(水) 16:52:16 ID:???
628です。ごめんなさい。書いた後にすぐ落ちてました(汗
ふーむ、やっぱり、1つのコマンドで足りるんですね。
ありがとうございました。参考にさせて頂きます。
631NAME IS NULL:2007/08/03(金) 16:37:00 ID:dBeTviY8
質問です。
DBはORACLE9iで下記SQLを実行すると
delete from
(select * from
(select rn ,id from
(select rownum rn ,id from
(select rowid id from AAAA order by update_time desc)))
BBBB, AAAA where AAAA.rowid = BBBB.id AND AAAA.rn > 3)

「SQL実行中に以下のエラーが発生しました。」
「ORA-01752: 複数表のビューから削除できません。」

のように表示されます。何か対処法はあるのでしょうか?
やりたいことはAAAAテーブルのupdate_timeが最新の項目を3項目残し、
残りは削除したい。

後、以下のようなSQLを実行すると

select count(*) from AAAA where itmcnt='05'

「ORA-00937: 単一グループのグループ関数ではありません。」

AAAAテーブル内のitmcnt=5のカウントを求めたいだけなんですけど。

以上、宜しく御願いします。
632NAME IS NULL:2007/08/03(金) 17:53:07 ID:???
delete from の後ろに消したいテーブル名入れて、その後ろに条件入れる
あと、count(*) はgroup by itmcnt でどうか
633NAME IS NULL:2007/08/03(金) 18:15:40 ID:???
こんな感じで。

delete AAAA
where rowid in (
select rowid from (
select rowid from AAAA order by update_time desc
) where rownum <=3);

後者はcounr(*)以外に何かはいってませんか?
グループ関数のみの場合はgroup by指定しないでもいけたとおもうんだけど。
634NAME IS NULL:2007/08/06(月) 04:46:21 ID:HzzUCyP6
とりあえずMySQLです。

  あるフィールドが「NULLではなく、かつ 1 以上」だったら〜

という条件式は、比較的色んなところで使いそうな気がするのですが、
これをさくっと記述する方法はありませんか?

素直にANDで2つ書くしかないでしょうか。
635NAME IS NULL:2007/08/06(月) 04:51:35 ID:???
>>634
単純に column >= 1 だけでいいんじゃないの?
IS NOT NULLは書かなくてもNULLは弾かれるだろうし。
636634:2007/08/06(月) 05:21:22 ID:???
ごめん。超ごめん。寝ボケてた。
NULLもしくは0のフィールドです。全くもって逆です。吊ってきます。

(column >= 1)=0 とかでイケるかな?とか思ったけどダメだった。
637NAME IS NULL:2007/08/06(月) 06:06:40 ID:???
>>636
MySQLでは無理かもしれんが、それに近いのに
(column >= 0) IS NOT TRUE
がある。さくっと記述できるかどうかはナニだが。

他には COALESCE(column,0) = 0 とか。
638634:2007/08/06(月) 06:12:07 ID:???
>635>637
2人ともこんな時間にありがとう。色々試してみることにします。そして寝る。
639NAME IS NULL:2007/08/06(月) 06:13:27 ID:???
補足。
(column >= 0) IS NOT TRUE と COALESCE(column,0) = 0 両方とも
インデックスが効かない可能性がある。その辺りはDBに依存するだろうけど、
現実的にはCOALESCEで関数インデックスかな。使えればの話だけど。
640NAME IS NULL:2007/08/06(月) 06:24:28 ID:???
NULLをインデックスで引けるDBMSなんて存在するの?
641NAME IS NULL:2007/08/06(月) 06:41:15 ID:???
>>640
あ、言われてみればそうだなw。
MS-SQL鯖なら引きそうな気もするが。
642NAME IS NULL:2007/08/06(月) 06:41:32 ID:???
確かSQLServer
ただ、UNIQUEでNULLは1レコードのみって理解に苦しむ仕様だったような。
643NAME IS NULL:2007/08/06(月) 07:46:10 ID:zdKH8zBk
644NAME IS NULL:2007/08/09(木) 11:53:46 ID:???
JOINってカッコで囲わなくても問題無いのは、もしかして常識?

今までずっと

((A JOIN B USING 〜) JOIN C USING 〜) JOIN D USING 〜

て書くのが当たり前だと思ってなんですが、ふと思って

A
JOIN B USING 〜
JOIN C USING 〜
JOIN D USING 〜

て書いてもなんらエラーにならなかったんで。これでいくつテーブルを
繋げてもそれなりに見やすいSQLになるかな
645NAME IS NULL:2007/08/09(木) 12:37:49 ID:???
>>644
たぶんみんな知ってる。
でも、Accessだけは、ネストして書かないと通らない。
646NAME IS NULL:2007/08/09(木) 22:44:24 ID:xEU1tKZW
minus
これはなんて読むんでしょう?
647NAME IS NULL:2007/08/09(木) 22:45:07 ID:xEU1tKZW
マイナス?
648NAME IS NULL:2007/08/09(木) 22:50:27 ID:???
マイナス。
649NAME IS NULL:2007/08/09(木) 22:53:00 ID:xEU1tKZW
>>648
マイナスで合ってます?UNIONは読めたのですが、
こちらは一瞬わからなかったです(^▽^;)
ありがとうございました。
650NAME IS NULL:2007/08/09(木) 22:54:39 ID:xEU1tKZW
教えてください。

所属A 所属B 所属C
A    B    C
B    C    D
C    D    E

この状態で、所属Cに、まだ登録されていない
所属A,所属Bの人間を集めたいのですが、、、
(最終的に、所属Cには(A,B,C,D,E)という状態にしたい)

この場合、NOT EXISTSを使った、INSERTが早いでしょうか?
MINUSを使った、INSERTが早いでしょうか?

アドバイスがありましたら、よろしくお願いいたします。
651NAME IS NULL:2007/08/09(木) 23:03:38 ID:???
>>650
直感的にはNOT EXISTSだと思うけど
実データに近い形で実行計画とってみないと何とも。
652NAME IS NULL:2007/08/09(木) 23:13:35 ID:xEU1tKZW
>>650 の続きです、、

1つのSQLで行う方法と、2つのSQLで行う方法は、
この場合、どちらが処理的に効率が良いでしょう?

@1つのSQLの場合
・所属A,所属BをUNIONしたあとで、MINUS(またはEXISTS) 所属C という方法と

A2つのSQLにわける場合
・所属A MINUS(またはEXISTS) 所属C
・所属B MINUS(またはEXISTS) 所属C


経験が浅く、SQLの知識があまりないもので、、
質問ばかりになってしまいましたが、お力をお貸し下さい。。
653NAME IS NULL:2007/08/09(木) 23:20:45 ID:xEU1tKZW
>>651
やはりNOT EXISTの方が若干はやいでしょうか?
それとも、そんなに変わらなければ、気にしなくても良いのかななんて(^▽^;)
654NAME IS NULL:2007/08/09(木) 23:37:55 ID:???
>>653
数百〜数千レコードの規模のデータ量なら、どれも大して変わらなそう。
パフォーマンスを気にするのは、その上のオーダーからかな。
1か2で選ぶなら、俺なら2の方。

極限のパフォーマンスを目指すなら、

- 一時テーブルDを作成
- Cにインデックス付与
- A-CをDにinsert
- B-CをDにinsert
- Cのインデックス除去
- Dにインデックス付与
- DのdistinctをCにinsert
- Dをdrop

でもここまでやる必要があるのは、数百万件クラスのバッチ処理くらいかと。
655NAME IS NULL:2007/08/10(金) 13:50:15 ID:nDGcrBFR
>>654
処理レコードは数千レコードあって1万レコード
ですので、それほど意識しなくてもよさげですね
アドバイスありがとうございました。
656NAME IS NULL:2007/08/10(金) 21:11:29 ID:???
>>654
それ何回 full scan かかるんだぁ?
657NAME IS NULL:2007/08/11(土) 18:37:34 ID:???
簡単に極限とか言っちゃダメだよ

プラチナムより上のクラス(計測不能)の人がここ覗いてるんだからさ
658NAME IS NULL:2007/08/16(木) 03:25:21 ID:???
MySQL をよく使っています。

二つのある特殊な検索エンジンからの検索結果の積集合をとれるような
アプリケーションを考えています。検索エンジンからの回答には、
スコアなどの付帯情報はありません。単に8文字の文書IDのみが返ってきます。
LOAD DATA を使って外部から回答をもらってくることを想像しています。

片方の検索結果は0から1000万件、片方の検索結果は0から1万件前後出てきます。
一度 MySQL にインポートする、というのもそもそも考えなければならないと思いますが、
これはいったいぜんたいどのように設計すればよいでしょうか。

Table: search_result_1
Create Table: CREATE TEMPORARY TABLE `search_result_1` (
`qid` int(11) NOT NULL,
`result` varchar(8) NOT NULL,
KEY `qid` (`qid`)
) ENGINE=MEMORY DEFAULT CHARSET=latin1

Table: search_result_2
Create Table: CREATE TEMPORARY TABLE `search_result_2` (
`qid` int(11) NOT NULL,
`result` varchar(8) NOT NULL,
KEY `qid` (`qid`)
) ENGINE=MEMORY DEFAULT CHARSET=latin1

Table: search_query
Create Table: CREATE TEMPORARY TABLE `search_query` (
`qid` int(11) NOT NULL,
`expression` varchar(255) NOT NULL,
`lastused` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`qid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

上記のような感じで手元で試してみました。

SELECT COUNT(*) FROM search_result_1 WHERE qid=1; -- 1995259件
SELECT COUNT(*) FROM search_result_2 WHERE qid=1; -- 147件
このような状況で、次のようなクエリを投げました。

SELECT search_result_1.result
FROM search_result_1, search_result_2
WHERE search_result_1.result = sarch_result_2.result
AND search_result_1.qid=1 AND search_result_2.qid=1;

一分半かかりました。CPUは100%使いきり、スワップは起こっていないようです。
ハードウェアに多少お金がかかってもいいのでもう少し高速に結果を得たいのですが
(願わくは1秒以内) 、なにかアドバイスをいただけませんか。
659658:2007/08/16(木) 03:34:26 ID:???
というかすいません、一分半で御の字のような気がしてきました。
それぞれの検索結果の取得でも何分もかかるわけですし。
むしろスケールアウトするような構成を考えなければならないような。
もう寝るべきですね。スレを汚してすいません。
660NAME IS NULL:2007/08/16(木) 07:18:01 ID:???
>>658
書いた内容だと、やりたい事が完全に理解しきれない。

まず、search_queryは何に使うのか。

それと、LOAD DATAはエンドユーザからの検索に対して
毎度行われるのか、それともLOAD DATAがされた後に
そのデータが使いまわされて、それを高速にしたいのか。

後者の場合なら、search_result_1の内容をsearch_result_2に
存在するresultのものだけ残すようにすればレコード数は格段に減る。

メモリが潤沢なら、type=heapでのcreate tableも試してみたら?
661NAME IS NULL:2007/08/16(木) 07:21:57 ID:???
>>660
すまん、ENGINE=MEMORYって書いてあるから、type=heapと
同じことは既に試してるんだね。この記述は無視して。
662NAME IS NULL:2007/08/16(木) 09:14:23 ID:???
>>658-659
> 一分半で御の字のような気がしてきました。
> それぞれの検索結果の取得でも何分もかかるわけですし。
自分で答え書いてんじゃん。

それはともかく、検索エンジンからとってきた結果を一回しか使わないなら
そもそもDBに入れる意味が薄い。
DBに入れるオーバヘッドが余計にかかるだけ。
スケールアウトするって言ってもそのためのオーバヘッドもかかるし。
それよりはファイルに落としてsortしてcommしたほうが速いんじゃないの?
それか、ハッシュテーブル作るプログラムを自前で書くとか。
663NAME IS NULL:2007/08/16(木) 09:51:39 ID:???
俺ならresult2のqid=1なresultでハッシュ作っておき、result1を
読みつつハッシュひいてあれば出力みたいにすると思う。result2は
8文字の文書IDが1万件までって条件だからハッシュはメモリに置いて
全く問題ない量だろ。これだけのことのためにDB使うのは無駄だな。
664NAME IS NULL:2007/08/16(木) 14:28:25 ID:rMjnc/Rn
INSERT文で聞きたい。SQLServer2005を使用。

テーブル名:Table

ID 名前1 名前2
-----------------
1  山田  太郎
2  鈴木  一郎

このようなテーブルがあるとして

IDが「1」の情報をINSERT文で作りたい。
しかしID「1」の情報はわからず、
ID「1」の情報をコピーして、同じテーブル内で
新規作成したい。

結果として

テーブル名:Table

ID 名前1 名前2
-----------------
1  山田 太郎
2  鈴木 一郎
3  山田 太郎

このような結果にしたい。
どんなSQL文にしたらいいのか?

665NAME IS NULL:2007/08/16(木) 14:34:14 ID:???
IDをどうやって生成するのかわからんけど
INSERT INTO の VALUES 以降を SELECT文にできるよ
666NAME IS NULL:2007/08/16(木) 14:34:30 ID:???
insert into Table(名前1, 名前2) select 名前1, 名前2 from Table where ID = 1
667NAME IS NULL:2007/08/16(木) 15:50:36 ID:rMjnc/Rn
>>665-666

やってみたんだが、IDがプライマリキーなのかもしれないが、
キーが重複している…というようなエラーがでてしまった。

原因はわかる?
668NAME IS NULL:2007/08/16(木) 15:57:47 ID:???
>>667
666でやるならIDはIndentity属性(自動採番)になってる必要がある。
insert into table select * from tabel where なんてやってたら重複するのは当然。
新規IDはmax+1でも何とかなるが実務で使うのはやめとけ。
669NAME IS NULL:2007/08/16(木) 16:08:07 ID:???
>>667
insert into Table
select A.max_ID + 1, B.名前1, B.名前2
from (select max(ID) as max_ID from Table) A,
   (select 名前1, 名前2 from Table where ID = 1) B
670NAME IS NULL:2007/08/16(木) 16:11:53 ID:???
>>664の通りにやるなら
INSERT INTO table (ID,名前1, 名前2) SELECT 3, 名前1, 名前2 FROM table WHERE ID = 1
でいいけどなー
671NAME IS NULL:2007/08/16(木) 16:25:02 ID:rMjnc/Rn
>>670

確かに。これだったらID「1」の情報がコピーされて
ID「3」として新規作成される。

でも、テーブルに今使えるIDがわからなかったとしたらどうだろうか?
MAX(ID)を試しに、SELECT文後のIDの所に入れてみたが
GROUP BY句…のようなエラーがでた。
672NAME IS NULL:2007/08/16(木) 16:30:55 ID:???
>>671
単純にMAX(ID)と書けないから、結果的に >>669 のような書き方にならざるを得ない。
答えが書いてあるのに、なぜ試さない?
673NAME IS NULL:2007/08/16(木) 16:37:06 ID:rMjnc/Rn
>>672
>>669

すまない。試してみるよ。
また何かあったら頼む。
674NAME IS NULL:2007/08/16(木) 16:53:48 ID:rMjnc/Rn
>>673です。

>>672
>>669

やってみた。確かにきれいにテーブルに反映される。
答えてくれてありがとう。

しかし、自分はまだまだSQL初心者。
聞きたいことがあるんだが、
A・Bとか、あれはなんだろうか?

解説が聞きたい。意味も知らずに使いたくはないので
ご教授願いたい。
675NAME IS NULL:2007/08/16(木) 17:06:15 ID:???
>>674
それは別名(Alias)で直前の括弧の中のSELECT分の結果をAという名前のテーブルに見立て、
外側のSQLからその名前で参照する。

>ご教授願いたい。 
普通に教えてくれとなぜ言わない。使い慣れない敬語使わんほうがいい。
676NAME IS NULL:2007/08/16(木) 17:37:47 ID:???
そこかしこで見るから最近は 「か、漢だ…!」系ネタに見える <ご教授ください
677NAME IS NULL:2007/08/16(木) 17:37:52 ID:rMjnc/Rn
>>675

教えてくれてありがとう。
なんとなくだがわかった。

また何かあったら頼む。
678NAME IS NULL:2007/08/16(木) 18:42:37 ID:ANt5VVpQ
やり方があったら教えてください。

上位10件を取得するとき、Oracleだと
WHERE ROWNUM <= 10 ....
SQL Serverだと
SELECT TOP 10 ...
と書きますが、
Derbyだとどのように書けばいいのでしょうか。
調べた限りだとそのような物は準備されていないので、
そのやり方を教えてください。お願いします。
679NAME IS NULL:2007/08/17(金) 04:03:29 ID:???
>>678
マニュアルに載ってなければないんじゃない?
無理やりやるなら>>551あたりを参照。
680NAME IS NULL:2007/08/17(金) 10:58:46 ID:???
>>679
ありがとうございます。やっぱり無理そうですね。

素直にカーソルまわします。
681NAME IS NULL:2007/08/17(金) 11:36:49 ID:???
DerbyはまだLIMIT OFFSET対応して無いのか・・
682NAME IS NULL:2007/08/17(金) 11:43:08 ID:H0kCuNJM
おそらく初心者質問でありそうで悪いのですが、

SELECT *
 FROM T_TEST1
 INNER JOIN T_TEST2
  ON T_TEST1.ID = T_TEST2.ID

というSELECT文だとT_TEST1.IDがT_TEST2.IDに存在するものだけ抽出されますが、
逆にT_TEST1.IDがT_TEST2.IDに存在「しない」ものだけ抽出するにはどうすればよいですか?
T_TEST2.IDが拒否リストであるようなイメージです。

検索キーワードだけでも結構ですので、よろしくお願いします
683NAME IS NULL:2007/08/17(金) 12:08:17 ID:???
ぱっと思いつくのはこんなんかな。
select * from T_TEST1 where T_TEST1.ID not in (select T_TEST2.ID from T_TEST2)
select * from T_TEST1 where not exists (select * from T_TEST2 where T_TEST1.ID = T_TEST2.ID)
684NAME IS NULL:2007/08/17(金) 14:54:21 ID:???
SQL2000で教えてください

テーブルにint型の列A〜Zがあり、その合計値を新しく追加するint型の列Summaryに書きだす必要があります
列A〜ZにはNULL値が入る場合もあります
列A〜Zの合計値はint型で記憶できる範囲を超えることはありません(各列の値は-100〜100かNULL)

最初UPDATE文で Summary = A + B + ... + Z とやってみたのですが、途中にNULLが一つでもあると結果がNULLになってしまいます
全てNULLのときはNULLに、NULL以外の値があるときはその値の合計値にしたいです

とりあえず CASE WHEN A IS NULL AND ... AND Z IS NULL THEN NULL ELSE ISNULL(A, 0) + ... + ISNULL(Z, 0) END とかやってみましたが、スマートな感じがしません
何か良い方法はないでしょうか
685684:2007/08/17(金) 14:57:38 ID:???
書き忘れていました

対象は SQL Server 2000 Enterprise Edition (SP4) です

同じようなテーブルが100以上あり、それぞれ百万件単位のデータが日々入れ替わるので、できるだけ処理を軽くしたいです
SQLの自体はどんなに長くても構わないので、処理の速さを求めています。。。
686NAME IS NULL:2007/08/17(金) 15:03:05 ID:???
CASEよりCOALESCEの方がちょっぴり短くなる。
>スマートな感じがしません 
>処理の速さを求めています
どっちを優先したいのよw
687NAME IS NULL:2007/08/17(金) 15:52:58 ID:???
入力日、入力者、入力時刻、金額のフィールドーが有る仮定で、そのテーブル
から

日々の合計金額
一日の中で最後に入力された時刻
その時刻に入力した入力者

を取得したいんですが、SQL1発で取得する良い方法はありませんか?
サブクエリでmax(入力時刻)を求めた上で、その値に一致する行の入力者を求
める、という方法なら普通に分かるのですが、折角のOracle10gなんで
partition by?last?みたいな関数を使えばもしかするとすっきり書いたり
出来るんでしょうか?
688NAME IS NULL:2007/08/17(金) 16:14:05 ID:???
>>686
情報ありがとございます、BOL見てみます

> どっちを優先したいのよw

自分で書いたのが無駄に長く遅いような感じがして、スマートじゃないと表現してしまいました
目的はあくまでも処理の速さです
689NAME IS NULL:2007/08/17(金) 16:19:53 ID:???
>>684
case
when coalesce(a, b, c, ..., x, y, z) is null then null
else isnull(a, 0) + isnull(b, 0) + isnull(c, 0) + ... + isnull(z, 0)
end

> テーブルにint型の列A〜Zがあり
> 同じようなテーブルが100以上あり

ネタだと思うが、マジなら設計を見直した方がいいと思う。
690NAME IS NULL:2007/08/17(金) 16:20:22 ID:???
>>688
じゃあえて反対を(笑)、スマートだけど処理速度は保証できない。
プランを確認して中間表を作ってないようなら使えるかもしれない。

select tt.id, sum(tt.sf) as total from 
 (select id, A as sf from table
  union all select id, B from table
   :
  union all select id, Z from table
) tt
691NAME IS NULL:2007/08/17(金) 17:16:15 ID:BRmKGHeD
SQL ServerのSQLにて、日付型の表記を yyyy/MM/dd hh:mm:ss と
する事は出来ませんか?

Convertで120を設定すると yyyy-MM-dd hh:mm:ss になってしまいます。
692NAME IS NULL:2007/08/17(金) 17:33:00 ID:???
>>691
111 は?
693691:2007/08/17(金) 17:40:27 ID:???
>>692
どうもです。

111 の場合、日付のみで、時間が入らないようです。
694NAME IS NULL:2007/08/17(金) 17:42:01 ID:???
>>693
じゃ、120でやってREPLACE()で。
695691:2007/08/17(金) 17:58:28 ID:???
>>694
出来ました!
ありがとう御座います。

うーん、しかし、グリッドへの表示に置換までする価値が
あるのか自分の中で悩む。

表記は統一したいけど、余計な負荷が掛からない様にしたい。。
(まあ、3000件程度では、体感で何も変わりは無かったですが。)
696NAME IS NULL:2007/08/17(金) 22:15:15 ID:???
>>691-695
convert(char(10), 日時, 111) + ' ' + convert(char(8), 日時 , 8) とかは?
697684:2007/08/17(金) 22:28:51 ID:???
>>689
情報ありがとうございます
686さんの情報を元に同じクエリを作ったところでした

>ネタだと思うが、マジなら設計を見直した方がいいと思う

ネタではなく本当なのです。。。
世界中の拠点からデータを集約しているのですが、各国で求められる情報が違い、設計当時(SQL Server 6.5の頃)はハードやインフラも貧弱で、論理的な対応ではなく物理的な対応でこなした名残だそうです
今は SQL Server 2008 を目指したリプレースの計画をしていて、1つのテーブルと、複数の変換パッケージで収まるようにするらしいです

>>690
そんな書き方もあるんですね
今回はもうテストに回してしまいましたが、個人的にチェックしてみようと思います
情報ありがとうございました
698NAME IS NULL:2007/08/18(土) 03:27:40 ID:???
MySQL4で

SELECT COUNT(*) AS count したものを
WHERE count > 5 のように指定できないのですが仕様ということでいいですか?

他に同じことをする方法はありませんか?
699NAME IS NULL:2007/08/18(土) 04:05:20 ID:???
>>698
MySQLに限らず仕様。
SELECTリストでの別名をWHERE句やHAVING句では使えない。
そもそもそこは、HAVING句じゃね。

SELECT c1,count(*) AS count FROM Table GROUP BY c1 HAVING count(*)>5;
700NAME IS NULL:2007/08/18(土) 08:08:19 ID:???
>>699
で、できましたーーーーー!
ありがとうございます。

未だにWHEREとHAVINGの違いがわかってないようです
701NAME IS NULL:2007/08/19(日) 23:49:03 ID:???


テーブル名:Table

番号 年月
-----------------
1   19230411   
1   19990621
1   20071211 ★
2   20011103
2   20060211 ★
3   20070222
3   20070413
3   20070802 ★

となっているとき
★マークのついた、各番号の最新の年月だけ抽出するには
どうすればよいでしょうか。よろしくお願いします><
702NAME IS NULL:2007/08/20(月) 00:20:53 ID:???
>>701
過去スレをみればなんども出てくる質問だぞよ
703NAME IS NULL:2007/08/20(月) 06:33:13 ID:???
さすがに初歩的すぎてレスつかないね。

select 番号, max(年月) from Table group by 番号
704NAME IS NULL:2007/08/20(月) 12:35:47 ID:???
>>703
それじゃ駄目だろ。
705NAME IS NULL:2007/08/20(月) 13:54:54 ID:???
703じゃないけど、何が駄目なの?
706704:2007/08/20(月) 15:12:19 ID:???
は?なに言っているんだよ。

と、思いましたが、すみません。
再度>>701を読み返したら、自分が勘違いしていました。
>>703であっています。
707NAME IS NULL:2007/08/20(月) 15:52:27 ID:???
過去スレ、レスで何度も出てくるのは
カラムがそれより多いケースだよなw

>>701のはあまりにも基本的過ぎる
708NAME IS NULL:2007/08/20(月) 21:11:14 ID:???
ここは「宿題は自力でやれ」ってレスすべきだったんじゃないのか?
709NAME IS NULL:2007/08/20(月) 23:26:52 ID:???
まあ、それじゃあんまりだから、「group by と max を調べてみな。」ぐらいでどうか。
710NAME IS NULL:2007/08/21(火) 07:51:49 ID:hZSddUM6
カラムにHTML形式のデータ100行ぐらい分まるごと放り込むって
バカな仕様でしょうか?
カラムに放り込むデータが大きすぎるとパフォーマンスは落ちますか?
711NAME IS NULL:2007/08/21(火) 09:32:18 ID:???
それが必要ならそうすればいいと思うよ
712NAME IS NULL:2007/08/21(火) 10:54:22 ID:???
>>710
経験的には、そういうシステムは何度か見てきた。
ファイルで保持するケースとで、一長一短だよ。
それぞれで実装した場合を見比べて、これから作ろうとしてる
システムではどっちが後々困らないか検討すべし。
713NAME IS NULL:2007/08/21(火) 20:16:27 ID:???
postgreSQLで質問です
EXTRACT()ですが、下記の様なテーブルに対して
SELECT EXTRACT(MONTH FROM TIMESTAMP '日付') as date from テーブルA
というようなクエリは不可能なのでしょうか?

テーブルA
----------------
ID (integer)
名前(text)
日付(timestamp)
----------------

つまり、EXTRACTの”EXTRACT (field FROM source)”の
sourceの部分に既存カラム名を指定、という事です。
psqlから実行する限りでは
ERROR: invalid input syntax for type timestamp: "日付"
というエラーになりますが、なにかTipsでこういった事が実現できたらと思いまして…。
714NAME IS NULL:2007/08/21(火) 20:46:10 ID:???
>>713
カラム名で指定する場合は、クォーテーションで囲む必要なし。
715713:2007/08/21(火) 21:00:57 ID:???
>>714
ありがとうございます
ERROR: syntax error at or near "日付" at character 37
のエラーとなりました。
*「日付」は実際にはシングルバイトのカラム名です

今、to_char(timestamp, text)も試してたんですが
やはり” timestamp”の所にカラム名を入れるとエラーになってしまいます…。
こちらの場合は
ERROR: function to_char(text, "unknown") does not exist
HINT: No function matches the given name and argument types. You may need to add explicit type casts.
のエラーだったんで::TIMESTAMPとか入れてキャストしてみようかと。
716713:2007/08/21(火) 21:20:05 ID:???
型キャストもどうにもダメで下記で解決しました

SELECT substr(日付,0,8) as date from テーブルA
SQLは色んな表現の仕方があっておもしろいです。

実行速度も計ってみたいんで引き続き
>>713
>>715
のような表現の正しい表記を教えて頂きたいです。
717710:2007/08/21(火) 22:18:56 ID:???
>>711 >>712
ありがとうございます。
HTML放り込みという使用もありなのですね。
ファイルで保持させようとも考えていたのですが
ページごとに必要でファイル数が5000を軽く超えてしまいそうなので・・
参考になりました。どうもありがとうございました。
718714:2007/08/21(火) 22:37:47 ID:???
>>715
あ、timestamp'...' が余計なんだよ。
SELECT EXTRACT(MONTH FROM 日付) AS date FROM TableA;
これでいけるはず。
719714:2007/08/21(火) 22:45:49 ID:???
>>715
> 今、to_char(timestamp, text)も試してたんですが
> やはり” timestamp”の所にカラム名を入れるとエラーになってしまいます…。
> こちらの場合は
> ERROR: function to_char(text, "unknown") does not exist

つーかさぁ、なんでto_charの第一引数がtext型と認識されてんの?
to_char(日付,'YYYY-MM-DD')としてて、同じエラーが出るのなら
日付カラムが本当にtimestamp型になっているのかと。
720713:2007/08/21(火) 23:18:41 ID:???
>>719
申し訳ないです、日付のカラムが複数あって、誤ってtext型のカラムを対象にしてしまっていました
下記、コピペなので正確ですが、calendar_dateカラムを対象にしてしてしまっていました。


Column | Type | Modifiers
---------------+-----------------------------+------------------------------------------------------
id | integer | not null default nextval('public.blog_id_seq'::text)
category_id | integer |
title | text | not null
contents | text | not null
img | text |
calendar_date | text | not null
insert_date | timestamp without time zone | default ('now'::text)::timestamp(6) with time zone
last_update | timestamp without time zone | default ('now'::text)::timestamp(6) with time zone

お詫びに実行速度を…。
721713:2007/08/21(火) 23:25:54 ID:???
EXPLAIN SELECT EXTRACT(MONTH FROM insert_date) AS date FROM blog;
QUERY PLAN
----------------------------------------------------
Seq Scan on blog (cost=0.00..1.06 rows=5 width=8)
(1 row)

EXPLAIN select to_char(insert_date,'YYYY/MM') as date from blog ;
QUERY PLAN
----------------------------------------------------
Seq Scan on blog (cost=0.00..1.06 rows=5 width=8)
(1 row)

EXPLAIN SELECT substr(insert_date,0,8) as date from blog;
QUERY PLAN
----------------------------------------------------
Seq Scan on blog (cost=0.00..1.07 rows=5 width=8)
(1 row)


という事でsubstr()を使うのが一番コスト的には悪いようでした。
ケアレスミスでごめんなさい、ありがとうございました
722NAME IS NULL:2007/08/22(水) 14:59:38 ID:???
ADO経由でAccessのmdbをいじってます

顧客テーブル
 顧客ID
 顧客名
 地域ID

地域テーブル
 地域ID
 地域名

購入テーブル
 購入ID
 顧客ID
 購入額

払込テーブル
 払込ID
 顧客ID
 払込額

こんなテーブル達があります
(購入額計)-(払込額計)が0以上の顧客数を地域別に勘定したいときは、どのようにすればいいでしょう?
723NAME IS NULL:2007/08/22(水) 15:28:12 ID:???
>>722
購入テーブルから 顧客ID, sum(購入額) を求める。
払込テーブルから 顧客ID, sum(払込額) を求める。
上記2つの結果と顧客テーブルを全て顧客IDでJOINし、
where句にsum(購入額)-sum(払込額)>=0をつけた上で
地域IDでグループ化してcount(*)する。
(地域名が必要なら地域テーブルもJOINする。)

ってのを、SQLで書けばいいんじゃね?
724FOX:2007/08/22(水) 15:39:39 ID:h8h7Zigl
2つのテーブルで同じ連番のレコードを一括削除したいのですがうまくいきません。
どなたかご教授よろしくお願いします。
725NAME IS NULL:2007/08/22(水) 15:42:12 ID:???
>>724
質問に対する質問しかレスされなそうな質問だな。
726FOX:2007/08/22(水) 15:46:00 ID:h8h7Zigl
すみません。
DELETE [Aテーブル][Bテーブル]
FROM [Aテーブル] INNER JOIN
[Bテーブル] ON [Aテーブル].連番 = [Bテーブル].連番
WHERE ([Aテーブル].連番 IN (00001, 00002))
にSQL文を書くとAテーブルしか削除できませんでした。
727NAME IS NULL:2007/08/22(水) 15:53:59 ID:???
>>726
x: [Aテーブル][Bテーブル]
o: [Aテーブル], [Bテーブル]

というオチでは。
728FOX:2007/08/22(水) 16:01:59 ID:h8h7Zigl
727さんありがとうございました。
,入れてみましたが実行できませんでした。
729NAME IS NULL:2007/08/22(水) 16:06:32 ID:???
どのRDBMS?バージョンも
730FOX:2007/08/22(水) 16:20:57 ID:h8h7Zigl
RDBMSはSQL Serverになります。
731NAME IS NULL:2007/08/22(水) 17:18:17 ID:???
DELETE文の一般的な構文は
 DELETE FROM テーブル名 [WHERE句]
だと思うけど。

てかそもそもDELETE文で複数テーブルを対象にできるの?
外部キーでCASCADEにでもしてなきゃ無理じゃね?
それかSQL Serverではできるとか?

知らんならレスするなって?
はい、すみません。
732NAME IS NULL:2007/08/22(水) 17:43:45 ID:???
一部のDBMSはできるみたい。
SQLServerは無理なんじゃかなー、知らんけど。
ビュー作ってトリガで消すかCASCADEにするのが自然か。
733NAME IS NULL:2007/08/22(水) 18:03:58 ID:???
mysqlでは可能。
SQL Serverは、Books OnlineでDELETEのBNF見た限りでは
サポートされてないようだ(2000しか見てないが)。
734NAME IS NULL:2007/08/23(木) 09:57:44 ID:1Mq4cvM8
インデックスってWHERE句で指定する条件が単一でない場合に作成すると
高速効果が期待できますよね?
WHERE句で指定する条件が単一の場合インデックス作成する意味はないですよね?
735734:2007/08/23(木) 10:45:37 ID:1Mq4cvM8
あぁなんか完全に勘違いしてますね。。
レコードが多く、更新度が低く、抽出結果・重複が少ない
場合に有効なのですね。
ユニークに設定してあると自動でインデックスされているんですよね?
736NAME IS NULL:2007/08/23(木) 10:55:18 ID:???
>>735
ユニーク制約だけでは、本来はインデックスが作成されることは保証されない。
だが、内部的にユニークインデックスを作成してるDBMSはあると思う。
心配なら、使ってるDBMSのマニュアル読んでみれば書いてあるはず。
737734:2007/08/23(木) 11:36:25 ID:1Mq4cvM8
>>736ありがとうございました。調べてみます!
738NAME IS NULL:2007/08/23(木) 12:17:30 ID:???
発言テーブル.id = コメントテーブル.comment_idという関連性があります。
(掲示板のスレとレスみたいな関係だと思って頂ければ…。)

発言テーブル AA
id, user_id, body, datetime
1 a 'aaa' 2007-08-10 10:00:00
2 a 'bbb' 2007-08-16 10:00:00
3 a 'ccc' 2007-08-18 10:00:00
4 b 'ddd' 2007-08-21 10:00:00
5 c 'eee' 2007-08-23 10:00:00


コメントテーブル BB
id, comment_id, user_id, body, datetime
1 2 b 'aaa' 2007-08-19 10:00:00
2 2 c 'bbb' 2007-08-22 10:00:00
3 4 a 'ccc' 2007-08-23 10:00:00

して、質問なのですが。

AAテーブルのdatetime最新順にソートするのですが
BBにコメントが存在していた場合は、そのdatetimeも含めてソートしたいのです。

AA.id, AA,user_id, AA.body, AA.datetime, BB.datetime
5 c 'eee' 2007-08-23 10:00:00
4 b 'ddd' 2007-08-21 10:00:00 2007-08-23 10:00:00
2 a 'bbb' 2007-08-16 10:00:00 2007-08-22 10:00:00
3 a 'ccc' 2007-08-18 10:00:00
1 a 'aaa' 2007-08-10 10:00:00

上記の様な形をイメージして居ります。
AA.id = BB.comment_idで外部結合し
GROUP BY AA.idで纏めているのですが…

どの様な形でorder byすれば適当でしょうか。
環境はMYSQLです。
739NAME IS NULL:2007/08/23(木) 12:33:20 ID:???
ORDER BY AA.datetime, BB.datetime
でいいのかな?
740NAME IS NULL:2007/08/23(木) 12:59:43 ID:???
>>739
返信有難う御座います。

既にそれは試してみたのですが、
AA.datetimeの方でのソートが優先され、BB.datetimeの方は見られていませんでした;
また、表示順が
1 a 'aaa' 2007-08-10 10:00:00
2 a 'bbb' 2007-08-16 10:00:00 2007-08-22 10:00:00
3 a 'ccc' 2007-08-18 10:00:00
4 b 'ddd' 2007-08-21 10:00:00 2007-08-23 10:00:00
5 c 'eee' 2007-08-23 10:00:00
の様に逆になってしまいます。
その為、DESCを付けたりもしてみたのですが…どうも思い通りに行かなくてorz
741NAME IS NULL:2007/08/23(木) 13:30:37 ID:???
BB.datetimeがAA.datetimeより古い場合は存在しない。
BB.datetimeがあればそちらを優先、でなければAA.datetimeでってことだろ。
MySQLで動くかどうか知らんが、

ORDER BY CASE WHEN BB.datetime IS NOT NULL THEN BB.datetime ELSE AA.datetime END DESC

でいけるんじゃね?
742NAME IS NULL:2007/08/23(木) 13:32:49 ID:???
ちょっと誤解を生みそうだ。突っ込まれる前に訂正。
×BB.datetimeがAA.datetimeより古い場合は存在しない。
○「BB.datetimeがAA.datetimeより古い」という状況は存在しない。
743NAME IS NULL:2007/08/23(木) 13:47:54 ID:???
>>742
返信有難う御座いました!
そして、その記述で望む動作を得ることが出来ました。
成程、条件で見る値を切り替えるのですね…
本当に有難う御座いました。
744NAME IS NULL:2007/08/23(木) 14:26:34 ID:???
>>738 の例が意味不明だと思ったが、そういう意味だったのか・・・
745NAME IS NULL:2007/08/26(日) 12:40:30 ID:???
日のアクセス2万ほどなのですが、現在ファイルでアクセスカウントしています。
現在TOPページのみでカウントしています。
全てのページにおいてカウントさせたくてpostgreSQLで管理しようと思うのですけど
やめておいた方がいいように言われました。(人伝いに)
どういった理由が考えられますか?
DBを使ってのアクセスカウントってあまり向いてないのでしょうか?
ページ数は1000ページほどです。
746NAME IS NULL:2007/08/26(日) 12:47:54 ID:???
WebPageの話か?
Web鯖がapacheだとしたら、apacheのログを解析するだけで済むと思うのに、
なぜにRDBで管理なんてヘンテコな事考えるんだ?

しかもたかが1000明細(ページ)の為に。

そんなのExcelやAccessで十分過ぎるだろ。
747745:2007/08/26(日) 12:55:20 ID:???
ありがとうございます、
そうです、Webです。
すいません抜けてました。
ページごとにアクセス表示させたいのです。
748NAME IS NULL:2007/08/26(日) 13:52:37 ID:???
>>747
> アクセス表示
って何を指してるんやら?
とりあえず、ページ毎にアクセスログをDBに記録して、

1. ページ毎にアクセスカウンタを埋め込む?(普通の閲覧者がカウンタを見れる)。
2. アクセス解析用(管理人しか見ない)

のどっちか? まぁ、2の場合だったら悩むほどのもんでもないだろうけど、
1ならトリガで...って書きかけたけど、1は単なる管理人の自慰行為だよね。

まぁ、DBにアクセスログを入れておけば、SQLだけでいろんな解析ができるだろうから、
俺的にはありだが。
749748:2007/08/26(日) 13:56:31 ID:???
にょ、途中で送ってしまった。

俺的にはありだが、httpdのアクセスログから1日分をバッチ処理して
DBに落としてからで十分だよね。
750745:2007/08/26(日) 15:54:15 ID:???
ありがとうございます。
1です。ページにアクセス数表示させるためです。
自慰行為でもなくて、そのページのアクセス数をリアルタイムで
知りたい人も尋ねてくるページなのです。
なのでそのページでその都度アクセス数を表示させておく必要がありまして。。

ファイルでカウントさせておくほうが良いでしょうか?
DBでアクセスカウントさせるとなるとリソース食いますか?
751NAME IS NULL:2007/08/26(日) 16:52:05 ID:???
どうしてもその機能が必要なら喪前の好きな方法でいいのでは?
perlでもJavaでもいいからサ。

ただ「そのページのアクセス数をリアルタイムで
知りたい人も尋ねてくるページなのです。」
なんてのは意味ない行為って教えてやればいいと思うが。

リアルタイムのアクセスレポートの機能の為に
高性能の鯖を買ってくれるお客ならやればいいと思うんだが、
リソースとか気にするならヤめとけ、としか言いようが無い。
752748:2007/08/26(日) 17:48:54 ID:???
カウンタだけならログをとる必要もないし、
SELECT FOR UPDATE でロックして、
後にインクリメントさせるだけでいいのかな?

いいんじゃね、やってみれば。
カウンタのためだけにDB使うってなら、躊躇してしまうところだが、
永続化やpgpoolなどを使えば、それほど気になるものでもないかも。
俺的には「そんなこと止めれ」とは言わない。

それはそうと、ちょっとスレ違いなネタなんだよな。
753NAME IS NULL:2007/08/27(月) 20:39:46 ID:xlZ83oxI
PL/SQLの質問です

ファンクションで
変数に2000文字以上の文字列を入れる処理があるのですが
VARCHAR2型だと大きさが足りなかったので
CLOBに変えたのですが
エラーが発生します

変数の宣言のところで

hoge clob;

にしました

CLOBは制限が多いとリファレンスに書いてましたが
適例が無く、読み解けませんでした

何か他の設定?が必要なのでしょうか?
754NAME IS NULL:2007/08/28(火) 00:31:23 ID:???
CLOBはあんまり使わない方がいいよ

使わない方向で改修無理なの?
755NAME IS NULL:2007/08/28(火) 14:53:30 ID:naFGM+aI
質問です。

主キーやインデックス等の質問なんですが
---------------------
table AAA
col1
col2
col3
index1:col1, col2
---------------------

---------------------
table AAA
col1
col2
col3
index1:col1
index2:col2
---------------------
とでは、

SELECTなどで、col1とcol2を条件にいれた場合、
同じようなスピードになるのでしょうか?(何十万件単位)


もしかしたらとんちんかんな質問かもしれませんが
宜しくお願いします。

756NAME IS NULL:2007/08/28(火) 15:01:52 ID:???
1)検索条件がcol1, col2 両方の場合、上はindex1が使用され、下はindex1かindex2のどちらかが使用される。
2)検索条件がcol1だけの場合、上はindex1が使用され、下はindex1が使用される。
3)検索条件がcol2だけの場合、下はindex2が使用されるが、上は使用されない。
1のケースでは上の方が検索スピードが速くなる可能性が高い。
(col1だけで十分件数を絞りlこめている場合はその限りではない。)

757NAME IS NULL:2007/08/28(火) 15:28:49 ID:???
>>755
基本的には >>756 の言うとおりだが、DBMSによっては、col2だけの条件でも
DBMSによっては(col1, col2)のインデックスが使われる場合もある。
col1のカーディナリティが低い場合は、効果が期待できることがあるため
(col1が1種類の値しか取らない場合を考えるとわかりやすい)。
とはいえ、(col2)のインデックスより勝るということはないが。
758NAME IS NULL:2007/08/28(火) 17:13:22 ID:???
>>757
OracleのCompress索引でしたっけ?
あれは第一キーのカーディナルがほんとに低いときしか効果が無いからなぁ。
759757:2007/08/28(火) 17:19:25 ID:???
>>758
そうそう、Oracleだったっけ。どれで実装されていたか確信がなかった。
補足してくれてありがとう。
760755:2007/08/28(火) 18:01:21 ID:naFGM+aI
756-759
皆様丁寧な説明ありがとうございます。
すごい勉強になりました!!
761NAME IS NULL:2007/08/28(火) 23:41:36 ID:mh0ASi6S
SEQUENCEオブジェクトをサポートしていないDBで
次のことをしたいのですが・・・。

■テーブルAはカラムa1,a2,a3・・・で構成される
 主キーは(a1,a2)
 行の追加はあるが更新と削除はない

■テーブルBはカラムb1,b2,b3・・・で構成される
 主キー設定は(b2,b3)
 行の追加はあるが更新と削除はない

上記にて、
・b1は数値である。
・b1はユニークではないが、同一の値の行は、一回のトランザクションで作成される。
・(b2,b3)には(a1,a2)の値が入る。

目的は、Aの行のいくつかをまとめてグループ化したいのと、
そのグループにユニークな番号をつけたいのです。
またAの行は複数のグループに存在してはいけないのですが、
これはBの主キー制約で回避できます。

このような場合、
トランザクション内で、テーブルBをロックして、
MAX(b1)+1を新しいグループの番号にするのがベストでしょうか。
テーブルBの行追加の頻度は高くありません。(既存行の更新はなし。)

テーブルロック以外にいい方法がありましたら、ご教授ください。
よろしくお願いします。


762NAME IS NULL:2007/08/29(水) 02:22:38 ID:???
>>761
そもそもトランザクションはロックのおかげで一貫性を保っているようなもんだから、
ロックせずにできないかと言われてもな。
質問内容からは、トランザクションで何を実現したいのかも見えてこないし。

- エラー時にrollbackしたいのが目的?
- Bへの更新者が複数いるからその競合の回避が目的?
- commitするまで更新中のBのデータが参照されないようにするのが目的?
763NAME IS NULL:2007/08/29(水) 09:33:37 ID:???
>>761
テーブルA,Bは同一キーで1:1の関連だからテーブルを分ける意味があまりない。
a1, a2, b1, a,3 ... でいいのでは?(もとろん分けてもいいが)

IDENTITY制約列(オートナンバー)がサポートされているなら
b1(PK)IDENTITYのテーブルを作りそこで生成される番号を使用する。
サポートされてないなら採番用のテーブルまたはレコードを準備する。
これについてはいくつか方法がある。
764NAME IS NULL:2007/08/29(水) 15:33:10 ID:2iUsCkc+
765NAME IS NULL:2007/08/29(水) 22:50:57 ID:skWgmgeO
>761
not exists (select * from tbl b where max(a.b1)+1=b.b1)
っていう条件をくっつけときゃロックしなくても大丈夫。
ただし、insertもできない場合がある。
そんときゃ、出来るまでループという手もあるけど。
766NAME IS NULL:2007/08/30(木) 00:55:07 ID:JDv5Lyba
みなさんレスありがとうございます。

>- エラー時にrollbackしたいのが目的?
>- Bへの更新者が複数いるからその競合の回避が目的?
はいそうです。グループ化の作業をWebページから複数の人が同時に行う可能性(低いけど)を
完全に削除しなければならないのです。

>- commitするまで更新中のBのデータが参照されないようにするのが目的?
ロックの目的はそのとおりです。
IsolationLevelをSerializableにするだけでは、ほぼ同時にグループ化をした場合、
同一グループ番号が割り振られる可能性を排除できないので。

>テーブルA,Bは同一キーで1:1の関連だからテーブルを分ける意味があまりない。
説明不足ですみません。Aは既存のソフトウェアの管理下のテーブルで、
今回の目的のためにBを新規に作成します。またBにはAにない情報も記録して
半永久的にデータを保持します。

>IDENTITY制約列(オートナンバー)がサポートされているなら
>b1(PK)IDENTITYのテーブルを作りそこで生成される番号を使用する。
IDENTITYはサポートされています。
そのIDENTITYのテーブルを占有ロックすれば(トランザクションの間、結果的に占有ロックかかりますね)、
ユニークな番号を取得できますが、
それなら1カラム1行のテーブルで、占有ロックして数字を増やしていくのでも同じですよね。
テーブルを分けたほうがパフォーマンス的にもいいと思いますので、それでやってみようと思います。


>not exists (select * from tbl b where max(a.b1)+1=b.b1)
>っていう条件をくっつけときゃロックしなくても大丈夫。
ごめんなさい。よくわかりません。
テーブルaにはカラムb1はないのですが・・・。
767NAME IS NULL:2007/08/30(木) 06:40:39 ID:???
>>766
質問の要領が悪いな。思い込みが激しい上に複数のことをごちゃ混ぜに考えてるように思える。
要はシーケンスのように、特定のレコードに紐つかないID値が欲しいわけだ。
その方法はひとつではないのでいくつか分類してあげてみる。

以下、グループ化してbレコードにレコードを追加する処理を主処理。
新規IDを発行する発番処理と呼ぶことにする。

発番処理を主処理のトランザクションに含む。
主処理が済むまで次の発番および次の主処理はブロックしておくか
IDが競合するようなら失敗または(自動または手動で)再処理させる必要がある。
ブロックさせるのがお前さんが考えてる方法。
>>765のやってるのは再実行の例で
ブロックの必要はないが他の主処理と競合したら再実行になる。

発番処理を主処理のトランザクションに含まない。
シーケンスを使う。
または、主処理のトランザクションの前に発番処理済ませておく。
または、主処理とは独立した接続で発番処理を行う。
同時実行性は高いが主処理がロールバックした場合に空き番号が発生する可能性がある。

IDENTITY制約をもつ発番テーブルを使う。
発番処理を主処理のトランザクションに含むことになるが
それぞれ別のレコードになるため競合はなくブロックする必要はない。
発行した番号はレコードとして残る。ただしID成後すぐにレコードを削除しても良い。
主処理がロールバックした場合はそのIDのレコードは残らない。
同時実行性は高いが主処理がロールバックした場合に空き番号が発生する可能性がある。
768NAME IS NULL:2007/08/30(木) 07:16:11 ID:???
>>765の意味は俺も分からん。
not exists (select * from テーブルB b where b.b1 = 入れようとしている番号)
なら分かるけど。
769NAME IS NULL:2007/08/30(木) 15:28:54 ID:???
テーブル1と2があって
1はA、B、C、D、Eとカラムがあって
2はF,Gとカラムがあるんだけど
1は単独で利用する場合があって
2と1を結合して利用する場合もある。
それで
2と1結合して利用する場合に2パターンあって
完全に2と1のデータ利用する場合と
2と1のEカラムだけ利用する場合があるのね。
そういう場合データ重複するけどテーブル2にもEカラムのデータおいたほうがいいのかな?
770NAME IS NULL:2007/08/30(木) 19:48:44 ID:???
>>769
参照時のパフォーマンス重視ならいいんじゃないかな。
更新と整合性管理のコストがかかるけど。
「インデックス付きビュー」、「マテリアライズド・ビュー」も参照されたし。
771NAME IS NULL:2007/08/31(金) 07:03:18 ID:???
>768
765だけど、そういうこと
772NAME IS NULL:2007/08/31(金) 11:24:39 ID:YdfX5avM
ある抽出条件に該当する、テーブルAのflgを1にUPDATEし、
テーブルAと1:多の関係にあるテーブルB、
テーブルBと1:多の関係にあるテーブルCの、
テーブルAのキーであるIDに紐付いたレコードに対しても
flgを1にUPDATEしたいのですがどのようにすればよいでしょうか?
そもそもうまく説明ができないのですが。。
773NAME IS NULL:2007/08/31(金) 12:22:58 ID:???
>>772
flgというのはA、B、Cそれぞれにあるの?
774NAME IS NULL:2007/08/31(金) 12:28:36 ID:YdfX5avM
>>773
あります。
775769:2007/08/31(金) 13:21:37 ID:49luVNYp
>>770
参考になりました、ありがとうございました。
776NAME IS NULL:2007/08/31(金) 13:41:28 ID:???
>>772
Aをupdateした後に、
update B set flg = 1 where id in (select A.key_b from A where A.flg = 1);
update C set flg = 1 where id in (select B.key_c from B where B.flg = 1);
こんな感じでできない?
レコード数多くて重いようだったら、もうちょい工夫する必要はあるが。
777NAME IS NULL:2007/08/31(金) 13:48:18 ID:YdfX5avM
>>776
inですか。なるほど。
できそうな気がします。
レコード数はそれほどでもないので大丈夫です。

どうもありがとうございました!
778NAME IS NULL:2007/08/31(金) 14:00:12 ID:c64PJJrl
質問です。

VBAでDBを組んでいるのですが。
列名が毎回変わるようにPGを組みたいのです。
どのようにテーブルをつくればいいですか?

2つのワークテーブルを使用したいとおもっています。
1つはフォームオープンしたときに、サブフォームにもたせる空の表です。
(見た目、なかみのないからのテーブル)
2つめは、検索をかけた時や一覧表示を押したときにサブフォームに
一覧や、検索結果を表示させるテーブルです。

2つめの表が問題になってます。
CD検索をかけた際、「日付のみ」がかわるようにしたいのです。

表1にある日付のデータを
表2の列名にしたいのです。

表1:
物件CD|枝番|符号|数量|日付|   ←列名
−−−−−−−−−−−−−−
0001|01|01|01|2007/8/31   ←データ
0002|02|01|02|2007/9/3
0003|01|01|01|2007/8/13
0004|01|01|01|2007/9/15




『検索 0001』
表2:
物件CD|枝番|符号|数量|***|***|2007/9/1|・・・(10行)|
0001|01|01|01|   |   |    | ←データ
0001|02|01|02|   |   |    | ←データ
0001|03|01|00|   |   |    | ←データ
0001|03|02|10|   |   |    | ←データ




*に表1の日付を10行もたせたいのです。

職場の方に聞いたら
CREATE TABLE
で出来そうだけどと言われました。

PGになってまだ2ヶ月で初心者です。
どなた様かお力を分けてください。
779NAME IS NULL:2007/08/31(金) 18:16:39 ID:???
>>778
VBAなら「ADOX テーブル作成」とかでググった方が早い。
SQLでどうこうするよりADOXでの操作は面倒だけどな。

でも、テーブル作成して実データを毎回突っ込むよりは、
多少複雑でもADOXでVIEWを作るだけに留めた方が良くないか?
780NAME IS NULL:2007/08/31(金) 22:57:58 ID:???
>>778
VBAといってるけど、MS-ACCESS?その辺の情報を出せば何か方法が出るかもしれないよ。
781NAME IS NULL:2007/09/02(日) 01:49:53 ID:???
勝敗の表示
自分 相手  勝敗
a     b    win
a     b    win
a     b    lose
a     c    win
a     c    lose
a     d    lose  
h     x    win
h     x    win
h     y    lose
h     z    lose  
みたいなテーブルがあって

where 自分 = aのとき
相手 合計 勝ち 負け 勝率
b     3    2    1   0.66
c     2    1    1   0.50
d     1    0    1   0.00

となるようなDB依存しないSQLってどうかけばいいのでしょうか?
ありがちなので、なめてかかってたらさっぱりわかりませんでした。
count, group byとサブクエリあたり使うと思うけど・・・
782NAME IS NULL:2007/09/02(日) 02:20:04 ID:???
>>781
JOINで結合してもいいかなと思ったが、WHERE 自分='a' が複数出てきそうなので、
以下なら、GROUP BY の前にひとつ入れるだけで済むからこっちの方がいいかなと。
SELECT 自分, 相手, count(*) ,
(SELECT SUM(CASE result WHEN 'win' THEN 1 ELSE 0 END ) FROM Table WHERE T1.自分=自分 AND T1.相手=相手) AS 勝ち,
(SELECT SUM(CASE result WHEN 'lose' THEN 1 ELSE 0 END ) FROM Table WHERE T1.自分=自分 AND T1.相手=相手) AS 負け
FROM Table AS T1 GROUP BY 自分,相手;
もっと楽にできそうな気もするが...
783782:2007/09/02(日) 02:25:10 ID:???
あ、resultは勝敗のことね。count(*)も AS 合計を付け忘れちゃった。
勝率は出してないけど、勝ち/合計で出せる。
SQLでするなら
SELECT * ,勝ち/合計 FROM (>>782のクエリ) AS T2
とさらに包んだ方がいいかな。
784782:2007/09/02(日) 02:28:40 ID:???
気になったので...連想スマソ。
"引き分け"を考えてなかったが、
あるんだったら勝率は
勝ち/(勝ち+負け) ですね。
785NAME IS NULL:2007/09/02(日) 03:45:03 ID:???
>>782
↓な感じに若干修正したら期待通りになりました。
SELECT 自分, 相手, COUNT(*) AS 合計,
       SUM(CASE 勝敗 WHEN 'win' THEN 1 ELSE 0 END) AS 勝ち,
       SUM(CASE 勝敗 WHEN 'lose' THEN 1 ELSE 0 END) AS 負け
  FROM 勝敗表
 GROUP BY 自分, 相手

Javaで作られたDerbyっていうDBMSなのでもしかしたら他のDBと
挙動が違うかもしれません。
ちなみに Derby だとCASE WHEN 勝敗 = 'win' THEN 1 ELSE 0 END と記述します。
非常に参考になりました。CASEって初めて使いました。
ありがとうございます。
786782:2007/09/02(日) 04:21:12 ID:???
そうか、勝敗はCASE内に出てきてもSUMで集約されるから、
わざわざサブクエリにする必要なかったか。こりゃ失礼。
787NAME IS NULL:2007/09/03(月) 06:25:45 ID:EUzll27l
初の質問です。
今php+postgresql+fedoracore4でシステムを作っているんですが、
どうも原因がpostgresqlにあるとわかってきました。
自分はDBを作るときまず文字コードをeucに変えて入力するんですが
invalid byte sequence for encoding "EUC_JP": 0xe988
というエラーがでます。
PHPのソースはhttp://www.mywave.co.jp/~ike50/chapter5.zip
にあります。
ぜひ教えてください。
788NAME IS NULL:2007/09/03(月) 06:48:13 ID:???
>>787
板違い。
PHP + PostgreSQLスレに池。

PHP + PostgreSQL
http://pc11.2ch.net/test/read.cgi/php/983128806/
789NAME IS NULL:2007/09/03(月) 07:09:51 ID:EUzll27l
今回初めて質問します。
fedoracore4でpostgresql+phpのプログラムを動かそう
としているんですが、データベースがうまく入ってくれません。
エラーです。
また本見てやっているんですが、僕の場合euc-jpではなく
UTF-8で表示されていて、それをeucにテーブルを変換して
やろうと思っているんですが入力の際にデータベースの言語がeuc-jpが最初から書いてあって
俺のはUTF8なんだが、
それを無理やり変換してEUCで入力しようとすると、
invalid byte sequence for encoding "EUC_JP"
のエラーがでます。
どうしたいいでしょうか?
よろしくお願いします。
790NAME IS NULL:2007/09/03(月) 07:27:00 ID:???
>>789
スレ違い。
PostgreSQLのスレに池。

【Windows】 PostgreSQL8 Part.1 【対応】
http://pc11.2ch.net/test/read.cgi/db/1102247223/l50
791778:2007/09/03(月) 09:39:53 ID:DLb/zQ6a
>>779さん
>>780さん

ありがとうございます。
さっそく調べてみます。
vbaは
Accessをつかってます。
792NAME IS NULL:2007/09/03(月) 14:34:00 ID:???
わざわざ別にテーブル用意して業種コード 例) 製造 seizou
それでメインテーブルに登録された業種コードseizouから
参照して製造って文字をひらいだすのは、なにかメリットがあるのでしょうか?
はじめからメインテーブルに製造って文字いれておけばいいんじゃない?
と思ったのですが、メリットがあるのなら教えてください。
793NAME IS NULL:2007/09/03(月) 14:52:54 ID:???
>>792
製造、製造業、製作....

頼むから正規化しろよ 第二正規形
http://pc11.2ch.net/test/read.cgi/db/1116097001/
794NAME IS NULL:2007/09/03(月) 14:58:35 ID:???
>>792
出力されるデータがログデータなら、リンクさせなくても良いんじゃない。

ただ、後からデータの修正が必要だったり、他のテーブルとの連携が
必要だったりする場合は、コードじゃないと色々と支障が出るだろう。
795NAME IS NULL:2007/09/04(火) 17:44:30 ID:???
SQL文の違いで質問です。

TO_NUMBER SQL文で検索時に関数を使ってオラクルデータを引っ張っています。

以下がその例です。
COL1はVarchar2(12)になっています。

SELECT * FROM A
WHERE TO_NUMBER(COL1) = 1

これと同じようなことをACCESSでしようと思うと関数は何を使えばいいのでしょうか?
暗黙型変換での比較をできるだけ行いたくない為お伺いしたいのですが。
ご教授お願いいたします。
796NAME IS NULL:2007/09/04(火) 17:54:21 ID:???
>>795
整数期待するならCLng(COL1)で良いんじゃないか?
何が入ってるか分からないならValの方が良いかもしれん。
797NAME IS NULL:2007/09/04(火) 18:49:37 ID:???
>>796

整数期待は問題ないのですが桁数の問題のほうがありおそらく9が12ケタきたらオーバーフローするんじゃないかと
なので聞いてみた次第です
Valで取りあえずやろうと思うんですが、本当は適切に12ケタの整数を処理できる型変換がおこなえたらいいなぁとか思っています。
798NAME IS NULL:2007/09/05(水) 22:11:51 ID:???
派生テーブルって毎回書かなければならないのでしょうか?
つまり、
SELECT * FROM (SELECT ほげほげ) AS T1, (SELECT count(*) FROM (SELECT ほげほげ) AS T2) AS T3
のように2回同じほげほげを書かなくてはならないのでしょうか?
799NAME IS NULL:2007/09/05(水) 22:16:28 ID:???
>>797
そこまで桁が行くのなら通貨型にしたほうが良いんでないか?
Ccur関数があるし。
800NAME IS NULL:2007/09/05(水) 22:36:10 ID:???
>>798
共通表式とかインラインビューとかでぐぐれ
801800:2007/09/05(水) 22:41:02 ID:???
違った。インラインビューはぐぐらなくていい。

×共通表式とかインラインビューとかでぐぐれ
○共通表式とかWITH句とかでぐぐれ
802NAME IS NULL:2007/09/06(木) 09:07:09 ID:???
>800-801
Thx. 残念ながら対応してなかったので地道に書くことにするよ。
803NAME IS NULL:2007/09/07(金) 21:24:58 ID:???
SQL2005だけど
with便利〜と思って使ってたんだけど
妙に遅いクエリがあって
試しにインラインビューで作ってみっかとやってみたら
パフォーマンスが10倍程度改善された事があった
804NAME IS NULL:2007/09/09(日) 13:01:39 ID:???
うちは重たいマスタ参照する副照会2回出てくるのをwith句に変更したらちゃんとメモリ上の一時テーブル見てくれて嬉しかったけど
805NAME IS NULL:2007/09/09(日) 21:24:06 ID:???
共通表式を使うと必ず一時表を作るんじゃない?
それが良い方向に働く場合もあるし悪い方向に働く場合もある、とか。知らんけど。
806NAME IS NULL:2007/09/09(日) 22:22:19 ID:8M0+Vljb
初心者ながら恐れ入ります。
実際、使う機会てそうないと思うのですが、如何か。
アクセスとかの利用者のみか?
807NAME IS NULL:2007/09/11(火) 11:29:21 ID:IJsUEx2O
注文テーブル
名前 注文番号
山本 1
高橋 2
佐藤 1
鈴木 1
山口 2

商品テーブル
商品記号 商品名
A    りんご
B    みかん

という2つのテーブルがあります。

山本 りんご
高橋 みかん
佐藤 りんご
鈴木 りんご
山口 みかん

という一覧を取得したいのですが、何かよい方法はないでしょうか。
(SQL1つで取得したい)

注文番号、商品番号などはSQL内で固定で記述してしまってもよいです。

SELECT A.名前,B.商品名 FROM 注文テーブル A,商品テーブル B
WHERE B.商品記号 =(A.注文テーブルが1のときA、2のときB)
のようなSQLを書きたいです。
808NAME IS NULL:2007/09/11(火) 11:33:37 ID:IJsUEx2O
ちなみに、それぞれのテーブル間で、キーを持つことはできない状況です。
(各テーブルは別会社管理で、「キー持たせよう」という案は片方の会社で
「やだ」と言われた為。)

ビューは作ってもよいと言われています。
809NAME IS NULL:2007/09/11(火) 11:46:39 ID:???
1とA、2とBを関連付けるのは何?
810NAME IS NULL:2007/09/11(火) 11:48:59 ID:???
SELECT A.名前,B.商品名
 FROM 注文テーブル A,商品テーブル B
WHERE A.注文番号 =(CASE WHEN B.商品記号 = A THEN 1
                        ELSE B.商品番号 = B THEN 2
                   END)
811NAME IS NULL:2007/09/11(火) 11:57:00 ID:???
2つでいいのか
812NAME IS NULL:2007/09/11(火) 11:57:29 ID:IJsUEx2O
>>809,>>810
ありがとうございます。

>>809
関連付けはSQL文でベタ書き(DBでは直接関連付けできない)
のつもりです。

>>810
ありがとうございます。
CASEとかWHENとかはOracleでも使えますか?
とりあえず調べてみます。
813NAME IS NULL:2007/09/11(火) 12:08:36 ID:???
>>812
そうじゃなくて、AとB以外無いのか、あるならその法則、を聞いたんだけどな
CASEは標準だよ
814NAME IS NULL:2007/09/11(火) 12:41:13 ID:???
古いオラクルでcase使えない場合はdecode
815NAME IS NULL:2007/09/11(火) 13:00:56 ID:???
Oracle 使ったことないんだけど、

A.注文番号 + 64 = ASC(B.商品番号)

でいいんかな。CASE 使わないだけ、こっちの方が速そう。
816NAME IS NULL:2007/09/11(火) 15:01:07 ID:+7Z4LZr/
X列      Y列
____________

か      !
村      の
の      バ
西      村
ー      か
バ      ー

X列に対し、Y列は次にくる文字を表しています。
PLSQLでない普通のSQLを用い、これを順番どおりに
並べ替えて出力する方法を教えてください。
817NAME IS NULL:2007/09/11(火) 15:58:10 ID:???
>>816
SQL99のWITH RECURSIVEを使う。
818NAME IS NULL:2007/09/13(木) 12:04:58 ID:???
MySQLを始めたばかりなのですが
TABLEを削除する際に
DELETEしないでDROPすると変なものが残ったりするのでしょうか?
819NAME IS NULL:2007/09/13(木) 12:27:45 ID:???
>>818
変なものって何だよwww
820NAME IS NULL:2007/09/13(木) 12:28:56 ID:???
>>816
OracleならJavaストアドで処理しろwww
821NAME IS NULL:2007/09/14(金) 02:09:18 ID:???
exists句が未だに理解できん・・・
使えるには使えるんだが理屈がな・・・

なんでこれでちゃんと動くんだ?って思う。
822NAME IS NULL:2007/09/14(金) 06:14:47 ID:???
>>821
exists や in は句じゃなくて述語。
823NAME IS NULL:2007/09/14(金) 06:29:30 ID:???
>>821
for文のネストだと思えばいいんじゃね?

select * from Table A
where exists (select * from Table B where AとBの比較)

だったら

for (rowA in Table) {
  for (rowB in Table) {
    if (rowAとrowBの比較) {
      print rowA
      break
    }
  }
}

とか。
実際にループして動いてるとは限らないけど
意味的にはそういうことかと。
824NAME IS NULL:2007/09/14(金) 18:22:19 ID:???
なんで、inで指定した順番に取り出すって方法が無いんだろう?
825NAME IS NULL:2007/09/14(金) 18:37:17 ID:???
日付を検索条件にしたselect文について質問です。(SQL Server 2000)

特定の日時のデータを検索するときに、
ヘルプにあるとおり下記のようなSQL文を使っています。
select * from abc where date like { ts '2007-09-10 06:10:00' }

日時はdate列に入っていて1分間毎に1件のデータがあります。
2007年9月中(日付は指定しない)の06:10の全てのデータを抜き出すには
どのようなSQLを書けばいいのでしょうか?

文字列を抽出するときのようにワイルドカードも使えないようで
どうやっていいのかわからない状況です。
よろしくお願いいたします
826NAME IS NULL:2007/09/14(金) 19:19:56 ID:???
>>825
YEAR(date) = 2007
and MONTH(date) = 9
and SUBSTRING(CONVERT(varchar, date, 120), 12, 8) = '06:10:00'

試してないので、微妙にずれてるかも。
827NAME IS NULL:2007/09/15(土) 06:18:32 ID:???
>>824
抽出結果をソートすれば事足りるからじゃね?
828NAME IS NULL:2007/09/15(土) 10:22:23 ID:???
>>826
ありがとうございます。
やはり1行のselect文ではできないんですね
convertなどを調べてみます。
829NAME IS NULL:2007/09/15(土) 17:34:06 ID:???
1行だろこれw
830NAME IS NULL:2007/09/16(日) 02:28:47 ID:???
ある条件で絞り込んでorder by idで下のようになっている場合
id, flag
========
 1,  0
 2,  0
10,  1
14,  1
18,  1
20,  0
flag(0か1のみ)が連続している数(連続記録)をカウントしたい
0が2連続のグループ、1が3連続のグループ、0が1(連続)のグループに
して、0が最大(2連続)と1が最大(3連続)を求めてたいのですが、どうやって
グルーピングして、結果を出力すればよいでしょうか?(自己参照か相関サブクエリで)
DBから引っ張ってきてプログラムで求めれば簡単なのですが・・・
831NAME IS NULL:2007/09/16(日) 04:41:05 ID:???
>>830
SELECT flag ,
max((SELECT count(*) FROM Table WHERE id BETWEEN T1.id AND (SELECT COALESCE(min(id),9999) FROM Table WHERE id>T1.id AND flag<>T1.flag) AND flag=T1.flag)) AS cnt FROM Table AS T1
GROUP BY flag;

COALESCE内の9999 は仮のid最大値
定数を用いたくないのなら定数(9999)の変わりに
(SELECT max(id)+1 FROM Table)
とすればいい。-- が、相関サブクエリ内のサブクエリにさらにサブクエリが...
832831:2007/09/16(日) 05:01:32 ID:???
どっちでもいいことなんだが、気になったもので訂正
> (SELECT max(id)+1 FROM Table)
の+1は無くてもよかった...orz
833NAME IS NULL:2007/09/16(日) 16:59:59 ID:???
>>831
スゲー。期待したものが取れました。書いてもらうとなるほどと
思うのですが。SQLってむずかしい。
834NAME IS NULL:2007/09/17(月) 11:00:47 ID:???
以下のような2つのテーブルがあるとします。

1.商品テーブル:
商品コードと商品名の列からなるテーブル。
前提として商品コードの数は少ないものとし(10個程度)、今後増えるとしても1年に1個増える程度と仮定します。

2.部材テーブル:
部材コードと部材名称の列からなるテーブル。データ数は数万件。

ここで部材毎にこの商品では使用可能、使用不可能という情報を定義するとなると、部材コード、商品コードを列に持つ別テーブルを作成し、そこにデータを作成するのが普通かと思います。

しかし、現在携わっているシステムでは、そのようにしないで、部材テーブルに商品コードを列名として追加し、その値をフラグとして使用可能、使用不可能を定義するという設計がされてました。


このようなテーブル設計になっている理由ですが、どうやら以下のようなことらしいです。

・部材テーブルを開くだけで、部材がどの商品で使用可能かが一目で確認出きる。

・最初に大量に部材をテーブルに登録する時に、EXCELで管理している一覧表からコピーペーストで簡単にデータを追加出きる。

部材一覧はお客様がEXCELで管理してます。フォーマットは部材が行方向に並び、列方向に商品コードがあって、セルのチェックのありなしで、部材がどの商品で使えるかどうかを管理してます。

・新しい部材コードを追加する時に、その部材がどの商品で利用可能かを同時にチェックしていくことでデータが作成出きる。

上記のような設計とか場合によってはありなのでしょうか?
メンテナンス上の理由だけであれば、テーブルは3つ使い、クロス集計のviewを作成して、それで管理するというのもありそうな気がしてますが。
835NAME IS NULL:2007/09/17(月) 15:19:32 ID:???
>>834
正規化という観点からなら、商品・部材・商品部材関連の3表に分けるのがセオリー。
ただしパフォーマンスや運用上の理由で(第一)正規形崩しをすることはある。
以下3つの条件がそろえば使うこともある。
部材から商品の問い合わせだけで商品からの問い合わせがない。
基本的に登録時に辞書的に使うもので基本的に結合はしない。
商品側のアイテムにほとんど変化がない。

客に入力してもらうためのフォームはデータを横に持ったほうがわかりやすいとしても
内部のテーブルをどう持つかは分けて考えるべき。
あとエクセルのデータと内部のテーブルはどちらが正でどちらが副かはしっかり決めておくこと。
836NAME IS NULL:2007/09/21(金) 23:16:04 ID:kSnyp4HK
user score
-------------
aho   10
boke 20
aho     5

user
------
aho
boke
kasu
から
user score
-------------
boke 20
aho   15
kasu   0
というのを得たいのですが、どのようにすればいいのでしょうか。
837NAME IS NULL:2007/09/22(土) 00:04:32 ID:???
>>836
上をTable1、下をTable2として、
SELECT t2.user, SUM(t1.score)
FROM Table1 t1
   RIGHT OUTER JOIN
   Table2 t2
   ON t1.user = t2.user
GROUP BY t2.user
838837:2007/09/22(土) 00:05:45 ID:???
ORDER BYつけ忘れた・・・
839NAME IS NULL:2007/09/22(土) 00:30:08 ID:???
>>837
それだとkasuのscoreが0にならずにnullになる。
840837:2007/09/22(土) 00:36:09 ID:???
>>839
まあそのへんは適当にCOALESCEなりCASEなりで。
841836:2007/09/22(土) 00:47:43 ID:???
>>837 (840)
caseを使えばよかったんですね。
ありがとうございます。
842NAME IS NULL:2007/09/22(土) 16:43:44 ID:gJY9Nx7q
day ID data
0922 1 あ
0922 2 い
0923 1 う
0923 2 え
0924 1 お
0924 2 か

上記のIDのルールは、必ず各日付で1から開始されるということです。
22日のID2から24日のID1までという指定で、「いうえお」という結果を得たいのです。
これって1度のクエリで取得することは可能なんでしょうか?
843NAME IS NULL:2007/09/22(土) 16:56:40 ID:???
>>842
day-IDで索引があるなら野暮ったいようで一番妥当なやり方。最適化も期待できる。
where day > '0922' and day < '0924 or day = '0922' and ID >='2' or day = '0924' and ID <= '1'
下記の場合索引がつかわれない可能性が大きい。
where day + ID >= '09222' and day + ID <= '092401'
(+ で文字列の連結が出来るとする)
844NAME IS NULL:2007/09/22(土) 16:58:51 ID:???
もしかして、where日付範囲 and not (22日でID2未満) and not (24日でIDが1より大)
という感じで、日付で選択してから両端を切り落とせばOK?
845842:2007/09/22(土) 17:10:43 ID:???
>>843
大変美しい解を、どうも有り難うございます。
一瞬、844を思いついたのですが、843様の方がスマートです。
どうも有り難うございました。
846NAME IS NULL:2007/09/24(月) 21:15:10 ID:2+Cwu/kw
ずいぶん初歩的な質問で悪いんですが合併律、分解律、擬推移律の成り立ちを証明したいんですが…
アームストロングの公理系調べても成り立つとしか書いてないもので…
だれか証明のプロセスを説明していただけないでしょうか?
847NAME IS NULL:2007/09/24(月) 22:09:07 ID:BEV9oSXR
それってSQL関係あんの?
848NAME IS NULL:2007/09/24(月) 22:31:48 ID:???
こっち(↓)向きの話題かな。

頼むから正規化しろよ 第二正規形
http://pc11.2ch.net/test/read.cgi/db/1116097001/
849NAME IS NULL:2007/09/24(月) 23:51:54 ID:2+Cwu/kw
あーそっちのほうがいいかもしれないです

そっちで聞いてもマルチ死ねって言われないですかね…?
850NAME IS NULL:2007/09/24(月) 23:54:16 ID:???
「向こうで聞きます」って言ってからにすれば普通はマルチだとは言われない
851NAME IS NULL:2007/09/25(火) 00:13:19 ID:???
では向こうで聞いてみます…
852NAME IS NULL:2007/09/26(水) 13:06:56 ID:xJgKrS79
ID TYPE COUNT
001 A 1
002 A 2
002 B 5
003 A 3
003 B 6
003 C 9

という表から

ID A B C
001 1 0 0
002 2 5 0
003 3 6 9

という結果を得たいのですが良い方法は無いでしょうか?
TYPE の数は取りあえず固定なのですが増えても大丈夫なようにしたいのです。
853NAME IS NULL:2007/09/26(水) 14:57:12 ID:???
テーブルA, Bがあって、AのキーはID、BのキーはIDと枝番です。

Bのテーブルの数量をID毎に集計し、それをAのテーブルにある単位数で割った
結果を、最後にAにupdateしてやりたいんですが、

UPDATE A
SET
A.基準数 = (SELECT SUM(B.数量) FROM B WHERE B.ID = A.ID) / A.単位数

というSQLは書けない訳で、、、、(by Oracle10g)


この意図に沿ったSQLの記述をご教示頂きたく。


854NAME IS NULL:2007/09/26(水) 15:08:06 ID:T24KY3Jz
>>852
SELECT ID,
    CASE WHEN TYPE='A' THEN COUNT ELSE 0 END AS A
    CASE WHEN TYPE='B' THEN COUNT ELSE 0 END AS B
    CASE WHEN TYPE='C' THEN COUNT ELSE 0 END AS C
FROM テーブル名
855NAME IS NULL:2007/09/26(水) 17:30:16 ID:???
>>853
Oracle使いじゃないからワカランのだけど、そのSQLが動いてもよさそうなもんだが...。
他には、
SET A.基準数 = (SELECT SUM(B.数量)/A.単位数 FROM B WHERE B.ID=A.ID)
とかでもダメなんかな。
856NAME IS NULL:2007/09/26(水) 17:31:11 ID:???
>854
レス、サンクスです。
でもダメでした。環境は PostgreSQL 8.1.9

create table idtest (id char(3),type char(1),count int);
insert into idtest values ('001', 'A', 1);
insert into idtest values ('002', 'A', 2);
insert into idtest values ('002', 'B', 5);
insert into idtest values ('003', 'A', 3);
insert into idtest values ('003', 'B', 6);
insert into idtest values ('003', 'C', 9);

SELECT ID,
CASE WHEN TYPE='A' THEN COUNT ELSE 0 END AS A,
CASE WHEN TYPE='B' THEN COUNT ELSE 0 END AS B,
CASE WHEN TYPE='C' THEN COUNT ELSE 0 END AS C
FROM IDTEST;

id | a | b | c
-----+---+---+---
001 | 1 | 0 | 0
002 | 2 | 0 | 0
002 | 0 | 5 | 0
003 | 3 | 0 | 0
003 | 0 | 6 | 0
003 | 0 | 0 | 9
(6 rows)
別々の行ででてしまいましたです…
857NAME IS NULL:2007/09/26(水) 17:38:32 ID:???
>>856
当たり前だろ。Group by しれ
858NAME IS NULL:2007/09/26(水) 18:06:26 ID:xJgKrS79
>857

IDでgroup by しようとして

SELECT ID,
CASE WHEN TYPE='A' THEN COUNT ELSE 0 END AS A,
CASE WHEN TYPE='B' THEN COUNT ELSE 0 END AS B,
CASE WHEN TYPE='C' THEN COUNT ELSE 0 END AS C
FROM IDTEST group by ID;

こうすると
ERROR: column "idtest.type" must appear in the GROUP BY clause or be used in an aggregate function
でおこられるのですよ。
type をgroup by に含めると相変わらず6行出て来てしまいますし…
859NAME IS NULL:2007/09/26(水) 18:21:00 ID:???
>>858
sumで括れ。
sum(CASE WHEN TYPE='A' THEN COUNT ELSE 0 END) AS A,
以下同じ
860NAME IS NULL:2007/09/26(水) 18:21:24 ID:???
>>853
update ... set ... = <subquery> は動くはずだから >>855 でいけるはず。

>>858
select ID, count(case when TYPE = 'A' then 1 else 0 end),(以下略)
861860:2007/09/26(水) 18:24:08 ID:???
ケコーンした上に間違えた・・・
>>859でいいです・・・
862NAME IS NULL:2007/09/26(水) 18:25:50 ID:???
>859
天才。
別に足すわけじゃなくても sum 使うんだ…
aggregate function 云々のエラーが出たからsumも考えたんだけど
sum(count)とかやったら相変わらずtypeをgroup by に含めろって言われるし。

これでうまくいきました。サンクス>859
SELECT ID,
sum(CASE WHEN TYPE='A' THEN COUNT ELSE 0 END) AS A,
sum(CASE WHEN TYPE='B' THEN COUNT ELSE 0 END) AS B,
sum(CASE WHEN TYPE='C' THEN COUNT ELSE 0 END) AS C
FROM IDTEST group by ID;
id | a | b | c
-----+---+---+---
003 | 3 | 6 | 9
001 | 1 | 0 | 0
002 | 2 | 5 | 0
(3 rows)
863NAME IS NULL:2007/09/26(水) 23:39:37 ID:DBQhsmg7
SQLとは話がずれてしまうのですが、質問させてください。

私が今入っている現場で、「デッドロックが起きるから」という理由で
ロックを使わずに、更新日時を持たせたカラムを使って排他制御をして
います。これって普通なんでしょうか?

ロックだけで排他制御をするのっておかしいんでしょうか?
864NAME IS NULL:2007/09/27(木) 00:18:21 ID:???
>>863
楽観的排他というよく使われる手法。
悲観的排他という言葉と一緒にググってみなされ。
865NAME IS NULL:2007/09/27(木) 00:44:20 ID:???
>>864
オプティミスティックロックでデッドロックは防げんと思うがな。

まぁ>>863の説明だけからじゃ、どっちなのか判断はつかんが。
本当にPMがアホだったという可能性もなくはないし。
866NAME IS NULL:2007/09/27(木) 01:10:55 ID:???
>>865
デットロックにはならないのと違うの?あっさり失敗するだけで。
867NAME IS NULL:2007/09/27(木) 14:05:47 ID:???
ttp://www.atmarkit.co.jp/fdotnet/entwebapp/entwebapp11/entwebapp11_02.html
↑でいう「業務排他制御」の事か?
868NAME IS NULL:2007/09/27(木) 22:18:48 ID:???
>>866
更新対象のリソースが一つだけの場合はそもそもデッドロックは発生しない。
更新対象のリソースが複数ある場合、基本的にオプティミスティックロックは使えない。

ただしこの手法がまったく使えないわけではなくて、例えば代表の一つのテーブルを
決めて、それを参照して全テーブルの更新の可否を判断するという形で用いられる
ことはある。
ところがそのような形にした場合、オプティミスティックロックだろうが通常のロック
だろうが、デッドロックを防ぐ上では同等。
要は、複数のリソースの獲得の競合がデッドロックなわけなんで、それを代表の
1リソース(mutex)を獲得したトランザクションが総獲りできるという形にすることが
この場合のデッドロック防止手法の本質なわけ。
869NAME IS NULL:2007/09/27(木) 22:39:45 ID:???
質問者が「デッドロック」という単語を
ただの「ロック待ち」と混同して使っている予感。

てか実際に混同されてるケースって多いと思う。
870863:2007/09/27(木) 23:42:25 ID:???
>>864-869
回答ありがとうございました。

教えていただいた通り、楽観的排他のことでした。
大変勉強になりました。
871NAME IS NULL:2007/09/28(金) 13:04:37 ID:???
code
------
'abcd'
''
NULL

上のような文字列値が入っているテーブルで
「NULLでない」かつ「1文字以上の値が入っている」行を抽出しようと

WHERE (code IS NOT NULL) AND (code <> '')

上記のSQLを実行したのですが、SQLServerでは期待通り'abcd'の行が帰ってきたのに
Oracle9iでは1行も該当しませんでした。

Oracleで同様の結果を得るためには条件式をどのようにすればいいのでしょうか?
872NAME IS NULL:2007/09/28(金) 18:04:51 ID:???
>>871
WHERE code IS NOT NULL
oracleだと '' と NULL の区別はないからこれでいい。
873871:2007/09/28(金) 19:37:32 ID:???
>>872
SQLServerをメインで使っているので知らなかったのですが
まさか''とNULLが区別されないとは思いもよりませんでした。

おかげで思ったとおりの動作ができそうです。ありがとうとざいました
874NAME IS NULL:2007/09/28(金) 19:48:47 ID:???
like '_%' なら DBMS 問わないんじゃね?
875NAME IS NULL:2007/09/30(日) 13:56:59 ID:???
内容
----------
123450
123459
345210
233442
323280

例えば↑のような数字の羅列が入ったテーブルがあったとして
↓のように下一桁が「0」のデータ内容だけ取りたいんですけど


内容
----------
123450
345210
323280

何かいいSQLはないでしょうか?
環境はoracle10gを使用しています。
876NAME IS NULL:2007/09/30(日) 14:16:11 ID:???
>875
mod(列名,10)=10
でいいんでわ?
877NAME IS NULL:2007/09/30(日) 14:55:09 ID:???
=0 でしょ。
878NAME IS NULL:2007/09/30(日) 19:08:56 ID:???
>>875-876
mod(列名,10)=0でいいのかな?
余りから導き出せばいいのですね。
ありがとうございます
879NAME IS NULL:2007/09/30(日) 22:53:43 ID:???
spool パス名 ファイル名

で、メモ帳に書いた命令を全部行うことができるとわかったのですが
なんどやっても成功せず・・・
パス名ってのを勘違いしてるのか、もしくは拡張子が.txtのままじゃあだめなのか・・・

どうすればよいでしょうか?
880NAME IS NULL:2007/09/30(日) 23:32:20 ID:???
>>879
それはSQLとは関係ないぞ、sqlplusのコマンドの質問はoracleスレへ。

建前はそれとして、spoolは結果の出力先をファイルにする命令じゃ無かった?
881NAME IS NULL:2007/10/01(月) 16:39:37 ID:???
"select id, num from tbl" で取得した結果が

id num
---------
1  3
1  4
1  5
2  1
2  2
3  2
3  3
3  4

となった場合に、numだけは1からの連番にしたいんですがSQLの書き方だけで
可能でしょうか。つまり、TBLに8行しかなくても、以下の様に11行返したい
んです。

id num
---------
1  1
1  2
1  3
1  4
1  5
2  1
2  2
3  1
3  2
3  3
3  4
882NAME IS NULL:2007/10/01(月) 17:28:21 ID:???
>>881
SQLでやらなきゃいかんような処理じゃないと思う。
select id, max(num) from t881 group by id
ここまでSQLであとはストアド使うかアプリでやったほうがまとも。
どうしてもSQLだけでやりたいなら別途
seq
---
1
2
3
:
99
といったレコードのテーブルを準備しておいてクロスジョイン。
select a.id, b.seq as num from
(select id, max(num) as maxnum from t881 group by id) a
cross join t881s b
where b.seq <= maxnum
883NAME IS NULL:2007/10/02(火) 19:19:44 ID:???

select t1.id,count(*) num
from tbl t1
cross join tbl t2
where t1.id=t2.id
and t2.num<=t1.id
group by t1.id

884NAME IS NULL:2007/10/04(木) 17:16:12 ID:???
>>883
????意味不明
885NAME IS NULL:2007/10/06(土) 09:37:10 ID:eMMtvj7o
すみません教えてください

Aテーブル
SYSCODE   NAME
1         山田太郎
2         田中花子
3         山本次郎

Bテーブル
SYSCODE   A_SYSCODE  NAIYO
1         2         2007/10/01 入室
2         2         2007/10/01 貸し出し
3         1         2007/10/01 入室
4         3         2007/10/01 入室
5         3         2007/10/01 退室

AテーブルのSYSCODEとBテーブルのA_SYSCODEをSQLでLEFTJOINして
SYSCODE   NAME    B_SYSCODE   NAIYO
1         山田太郎  3          2007/10/01
2         田中花子  1
2         田中花子
3         山本次郎
886885:2007/10/06(土) 09:59:40 ID:eMMtvj7o
書き込みミスった・・・OTL
すみません教えてください

Aテーブル(個人情報テーブル)(1000件)
SYSCODE   NAME
1         山田太郎
2         田中花子
3         山本次郎

Bテーブル(カードログテーブル)(100万件)
SYSCODE   A_SYSCODE  NAIYO
1         2         2007/10/01 入室
2         2         2007/10/01 貸し出し
3         1         2007/10/01 入室
4         3         2007/10/01 入室
5         3         2007/10/01 退室

AテーブルのSYSCODEとBテーブルのA_SYSCODEをSQLでLEFTJOINして
SYSCODE   NAME    B_SYSCODE   NAIYO
1         山田太郎  3          2007/10/01 入室
2         田中花子  1          2007/10/01 入室
2         田中花子  2          2007/10/01 貸し出し
3         山本次郎  4          2007/10/01 入室
3         山本次郎  5          2007/10/01 退室
と出しています。
Bテーブルの内容は個人の最新のカードログ情報だけを表示させて欲しいと
依頼がありメンテしていますが
BテーブルでSYSCODEの最大値(別名でBMAXCD)をA_SYSCODEでグループ化してaを作成。
(A_SYSCODEとBMAXCDのフィールド)
aのBMAXCDとBテーブルのSYSCODEをLEFTJOINしてNAIYOを結合させてbを作成。
(A_SYSCODEとBMAXCDとNAIYOのフィールド)
AテーブルのSYSCODEとbのA_SYSCODEをLEFTJOINして最新のログ番号と内容を結合させて
結果を表示するSQLを作り実行すると回答が返ってくるまでに20分近くかかります(下手したらタイムアウトする)
20分近くかかって表示される結果を速くすることはできないのでしょうか?
887NAME IS NULL:2007/10/06(土) 10:21:24 ID:???
>>886
Bテーブルに(SYSCODE, A_SYSCODE)と(SYSCODE, NAIYO)の
インデックスを張る。
DBMSによっては(SYSCODE, A_SYSCODE, NAIYO)のインデックスだけでも
いいかもしれない。
888NAME IS NULL:2007/10/06(土) 10:28:14 ID:???
>>886
どの処理に時間がかかっているか調べたら? たぶん
> BテーブルでSYSCODEの最大値(別名でBMAXCD)をA_SYSCODEでグループ化してaを作成。
に時間がかかっているかと。

BテーブルのA_SYSCODEにインデックスを張って、先に対象のA_SYSCODEを抜き出してmax(B.SYSCODE)をゲット。
そこから、B LEFT JON Aでいいんじゃね。

SELECT * FROM
(SELECT * FROM Btable WHERE SYSCODE = (SELECT max(SYSCODE) FROM Btable WHERE A_SYSCODE = ?)) AS b
JOIN Atable ON b.A_SYSCODE = Atable.SYSCODE;

DBによっては、

SELECT * FROM Btable JOIN Atable
ON Btable.SYSCODE = (SELECT max(SYSCODE) FROM Btable WHERE A_SYSCODE = ?)
AND Btable.A_SYSCODE = Atable.SYSCODE;

でもいいかな。
889NAME IS NULL:2007/10/06(土) 10:31:14 ID:???
っと、だらだら書いたらかぶった。
おまけに、A_SYSCODE=? じゃだめか、Atable.NAMEから引っ張り出さんと。
890NAME IS NULL:2007/10/06(土) 10:33:47 ID:???
>>886
A, BテーブルのSYSCODEに索引があるのは当然として、
Bテーブルに(A_SYSCODE, SYSCODE)の索引が必要なんじゃないかな。
これがないと
SELECT A_SYSCODE, MAX(SYSCODE) AS BMAXCD FROM Bテーブル GROUP BY A_SYSCODE
で実際の並び替えが発生する。
891885:2007/10/06(土) 14:16:11 ID:eMMtvj7o
ありがとうございます
ちなみに使用しているDBはSQL Server7.0です・・・
調べてみたらBテーブルでSYSCODEの最大値(別名でBMAXCD)をA_SYSCODEで
グループ化してaを作成でものすごく時間かかっていました。
よくしらべてみたA_SYSCODEのフィールドがNULLのものあった・・・
(カードや個人データない人の処理でA_SYSCODEに何も入れてない・・・OTL)
INDEXはSYSCODEのみでその他のINDEXは他の画面や処理で使っているので
今回の処理では使えないINDEXばかりです・・・・
やっぱBテーブルのSYSCODEとA_SYSCODEの組み合わせのINDEXも張らないと
いけないようですね・・・・
そうなるとBテーブルに(ログテーブル)にINDEXが20個になってしまい
張りすぎで他の処理に影響でないか不安ですが・・・
SELECT
A_SYSCODE, MAX(SYSCODE) AS BMAXCD
FROM Bテーブル
GROUP BY A_SYSCODE
でビューを作って
AのSYSCODEとビューのA_SYSCODEをJOIN
ビューのBMAXCDとB.SYSCODEでJOINしようと
おもったんですけど・・・どうなんでしょうか?
892NAME IS NULL:2007/10/06(土) 17:35:14 ID:???
>>891
BテーブルにA_SYSCODEのインデックスがすでにあり、
かつ、A_SYSCODEがNULLの割合が非常に高ければ(8割とかそのくらい)、
AテーブルとBテーブルを先にINNER JOINすると多少速くなるかもしれない。

そうでないなら(SYSCODE, A_SYSCODE)のインデックスを張っちゃうしかないと思う。
19個が20個になったところで今更どうってことないでしょ。

ちなみにビューでは解決にならないよ。
893NAME IS NULL:2007/10/06(土) 18:05:59 ID:???
B.A_SYSCODEごとのB.SYSCODEが最大のレコードを求めるという
問題ならさんざん既出だが。

ただ、今日の回答者連はろくなのがいないな。
894NAME IS NULL:2007/10/06(土) 18:15:49 ID:???
>>893
いや、やり方は分かった上でパフォーマンスのことを聞いているんだから
別に既出じゃないと思うが。

てか自分が「まともな回答」をしてやれよ。
895NAME IS NULL:2007/10/06(土) 20:55:44 ID:???
過去ログ嫁
896NAME IS NULL:2007/10/07(日) 19:36:49 ID:???
>891は素直に一時テーブルというものを調べてみるがヨロシ。
ちょっと複雑なSQLを書く場合には、SQL鯖の場合は1SQLでやらず、
一時テーブルが最強。
897NAME IS NULL:2007/10/07(日) 20:22:11 ID:???
>>896
インデックスのない100万件のテーブルから1000件程度を取り出すのに
一時テーブルを使ったらどう速くなるのかkwsk。
898NAME IS NULL:2007/10/09(火) 21:55:52 ID:???
>897
896だけど。
詳しくといわれても、詳しくは書けん。原理はおいらも知らん。
だって、それがSQL鯖クォリティであり、MSの企業秘密だから。

Oracleとかで一時テーブル使ってたら一生判らないことだから、
一度、使ってみて実感すればよいことなりよ。
899NAME IS NULL:2007/10/09(火) 22:20:38 ID:???
>>898
理屈のわからない動作というのは少なからずあるものだが、
そのときは再現性のあるコードなり条件なりをあげるべき。
そうでなければただの電波。
900NAME IS NULL:2007/10/09(火) 22:47:33 ID:???
一時テーブル+ストアドプロシージャで少しましになるケース。
A_SYSCODE、NAME, B_SYSCODE, NAIYO からなる一時テーブルを準備。
Aテーブルをもとに1000件のレコードを作る。
 B_SYSCODEはゼロ, NAIYOはNULLで初期化。
Bテーブルをカーソルで1件ずつ読み、
 一時テーブルのA_SYSCODEがマッチする場合は
  B_SYSCODEを比べて大きければ
    そのレコードのB_SYSCODE, NAIYOを置き換える。
これでBテーブルへのアクセスは全件読み取りだけでソートは発生しなくなる。

A_SYSCODEとB_SYSCODE(最終分のみ)のレコードをはじめから用意しておくのが、
この手の問題への一番の処方箋なのだけどね。
901NAME IS NULL:2007/10/10(水) 17:16:18 ID:sVDA5qMU
SQLSERVER2000

ビュー内でストアドプロシージャを呼び出す方法はありますか?

902NAME IS NULL:2007/10/10(水) 18:17:03 ID:???
>>901
Microsoft SQL Server 総合スレ 5
http://pc11.2ch.net/test/read.cgi/db/1175091880/l50
903NAME IS NULL:2007/10/10(水) 18:29:10 ID:???
ありがとうございます。そちらを探してみます。
904NAME IS NULL:2007/10/10(水) 18:29:22 ID:IgcJtG6a
Accessの集約関数にFirst()というのがあって、
並んだ列の一番最初の要素を返すというものなんですが、
Postgresで同じようなことをやる関数もしくは方法のアイデアはないでしょうか?

a| b
----
あ|0
い|0
う|1
え|2

の場合に、select distinct first(a), b from table group by b
とすると、あ, 0 と い, 1 と う, 2という風になります。
905NAME IS NULL:2007/10/10(水) 19:27:06 ID:???
>>904
あ=>0 う=>1 え=>2 の間違いじゃないのか?
それならDISTINCT ON が使えるが...
SELECT DISTINCT ON (b) b, a FROM Table ORDER BY b;

詳しくはマニュアルを、DISTINCT ONはPostgreSQL特有なので、続きがあれば
【Windows】 PostgreSQL8 Part.1 【対応】
http://pc11.2ch.net/test/read.cgi/db/1102247223/
906904:2007/10/10(水) 19:46:56 ID:???
>>905
ありがとうございます。
ばっちりいけました。
907NAME IS NULL:2007/10/11(木) 10:50:12 ID:???
WEBシステムで画像のバイナリーデータを放り込んで
画像の管理を簡素化したいのですが
実際にそのようなシステムで管理されている大手サイトなどあるのでしょうか?
DB管理にともなってDBへの負担があまりにも大きいようなら採用しないつもりです。

908NAME IS NULL:2007/10/11(木) 23:37:25 ID:???
>899
sigh....クレクレ君かい。

tblっていう10万件overぐらいのテーブル用意汁。

select * from tbl
union all
select * from tbl
union all
select * from tbl



insert into #tbl
select * from tbl

insert into #tbl
select * from tbl

insert into #tbl
select * from tbl

select * from #tbl

と、どっちが早いか試してみたらヨロシ。もちろんSQL鯖で。
909NAME IS NULL:2007/10/12(金) 00:27:36 ID:???
>>908
クエリアナライザだと出すぎるから、これはADOとかで空読みしたらいいの?
910NAME IS NULL:2007/10/12(金) 05:51:23 ID:???
>>908
899じゃないけど、なんか、メモリ上に読み込んでスワップが発生するから、
結局一時テーブルへ書き出した方が速いって感じか?
意外とDBの違いじゃなくて、OSに依存してて、他のDBでもWindows版なら
一時テーブルを使った方が速かったりして...。

にしても、元質の回答にあったインデックスを張って、必要なレコードだけ読み込んでから
集約させる方が、一時テーブルを使ったとしても100万件を読み込むより速い気がする。
まぁ、SQL鯖使いじゃないからどっちだっていいや。
911NAME IS NULL:2007/10/12(金) 07:01:05 ID:???
>>907
昔Oracle InterMediaで作った。
管理は普通のデータと同じだが、
データの取り出しやプロパティ検索がめんどくさかった。
912NAME IS NULL:2007/10/12(金) 12:00:37 ID:???
>>908
試してみたが一時テーブルを使った方が早いということは無かった。
ちょうどコピー分くらい余分に時間がかかっている。

使ったスクリプトはロダにあげた。
ttp://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/5053.txt
913NAME IS NULL:2007/10/13(土) 17:20:10 ID:jINrTab0
NO NAME FLAG
1 tanaka 0
1 tanaka 1
2 satou 0
3 hayasi 0
3 hayasi 1

上記のようなNO,FLAGでユニークなテーブルがあるのですが、
NO毎に

FLAG=1のレコードが存在すればそのレコード
FLAG=1のレコードが存在しなければFLAG=0のレコード

を取得したいのですが、SQLでやるとすればどういうSQLになるのでしょうか?
DBはoracleなのですが、こういう処理はプログラム側で対応すべきなのでしょうか?
914NAME IS NULL:2007/10/13(土) 18:12:04 ID:???
>913
とりあえずテーブル名をxとして、
select * from x where flag = 1 union select * from x where flag = 0 and not exists( select * from x as t where flag = 1 and t.no = x.no );
でどう?
915NAME IS NULL:2007/10/13(土) 18:15:30 ID:???
>>913
その例テーブルだけだと、
SELECT NO,max(NAME),max(FLAG) FROM Table GROUP BY NO;
でもよさそうだな。
916NAME IS NULL:2007/10/13(土) 19:25:30 ID:???
oracleならrank partitionでもいける。
917NAME IS NULL:2007/10/13(土) 23:18:47 ID:ATcEauDQ
質問があります
>>885と似たようなケースなんですが


ログデータ(1000万件)
ログNo ログ区分 顧客コード 内容1 内容2 内容3

このテーブルを顧客コード毎にあるログ区分でログNoの最大(最新)をとる。 (A)
(A)の結果とログデータを(A)の最新ログNoとログデータのログNoでLeftJoin
して内容1・内容2・内容3とってきて顧客コード 最新ログNo 内容1 内容2 内容3
とする(B)

この(B)を

顧客マスタ
顧客コード 顧客名 商品シリアルNo 商品コード

シリアルマスタ
シリアルNo 商品コード 製造日 業者コード

商品マスタ
商品コード 商品名

業者マスタ
業者コード 業者名 部門コード 担当コード

部門マスタ
部門コード 部門名

担当マスタ
担当コード 担当名

6つのテーブルでLeftJOINして

業者コード 業者名 部門コード 部門名 担当コード 担当名 商品コード 商品名 シリアルNo 顧客コード 顧客名で
(D)を作り

(D)の顧客コードと(B)の顧客コードをLeftJoinし
(D)の内容+最新ログNo 内容1 内容2 内容3を表示したいのですが
ものすごく時間がかかります。(20分〜30分)
(D)の状態だと1分くらいでデータは取れるのですが・・・
よい方法はないでしょうか?
918NAME IS NULL:2007/10/14(日) 00:16:52 ID:???
>>917
なんかよく分からんテーブル設計だな。

例えば「顧客コード」はひとつの顧客に対してひとつ振られるわけじゃなくて
ある顧客に出荷した商品ひとつに対してひとつ振られるわけ?

そうだとしたら、「顧客マスタ」(と言いながら実は出荷実績みたいなもの)に
あらかじめ商品名やら業者名やらを入れといちゃえばいいと思うけど。

この設計のままでどうにかしたいなら、
まずは(A)を作る時間、(B)を作る時間、(D)を作る時間を
それぞれ測ってみるところからだろ。
919NAME IS NULL:2007/10/14(日) 07:34:50 ID:???
回答が欲しいならキーの情報と投げたSQLは必要。
自分で何とかしたいならプランを調べる。
920NAME IS NULL:2007/10/15(月) 09:44:37 ID:Y520eQFI
一日ごとの東証一部の全株価の終値のデータがあります。
証券コード(INTEGER)
日付(DATE)
終値(FLOAT)
これが2年分あるのですが、これをDBに入れて、証券コードごとに
2年分を取り出せるようにしたいとおもってます。たとえば
トヨタ自動車だったら、証券コード(7203)を指定すると、2年分の
終値のデータが得られる、という感じです。
このとき、DBのテーブルはどのように設計したらいいですか?
どうかよろしくお願いします。
921NAME IS NULL:2007/10/15(月) 10:37:38 ID:???
>>914-916さん
ありがとうございます!

>>914
うーん・・非常にわかりやすいです
>>915
参考になります。MAXだとちょっと問題あるケースでした、説明不足ですみません
>>916
ちょっと難しそうなので勉強してきます

一応以下のSQLのviewを作ってなんとか出来たのですが、
>>914の方がすっきりしそうです。
SELECT
CASE WHEN y.NO IS NULL THEN x.NO ELSE y.NO END,
CASE WHEN y.NO IS NULL THEN x.NAME ELSE y.NAME END,
CASE WHEN y.NO IS NULL THEN x.FLAG ELSE y.FLAG END,
FROM
(
SELECT * FROM x WHERE FLAG = 0
LEFT OUTER JOIN
SELECT * FROM y WHERE FLAG = 1
)
922NAME IS NULL:2007/10/15(月) 16:22:32 ID:???
>>920
その3つでいいんじゃね?
923NAME IS NULL:2007/10/15(月) 19:41:31 ID:Y520eQFI
>>922
ありがとうございます。
でも、上記のようにすると、2000/01/20のトヨタのデータをinsertして
その後に2000/01/21のデータをinsertすると、重複扱いになってしまいます。
primary keyは証券コードにしました。
924NAME IS NULL:2007/10/15(月) 20:10:05 ID:???
>>923
PKは(証券コード, 日付)だろ。

ただし日付がDATE型だと同じ日の違う時間の値も入れられちゃうから
それがマズければもう少し工夫が必要。
925NAME IS NULL:2007/10/15(月) 20:21:37 ID:Y520eQFI
>>924
ありがとうございます!
結局以下のテーブルにしました。
いまデータをinsert中です。

create table owarine (
id integer,
date date,
close float not null,
primary key (id,date));
926NAME IS NULL:2007/10/15(月) 20:38:12 ID:???
>>920
個人的に作ってるものだけど、俺は

kabukaテーブル
銘柄コード 出来高年月日 始値 高値 安値 終値 出来高

primary key (銘柄コード、出来高年月日)にしてる。
(市場は考えない)

meigaraテーブル
銘柄コード 銘柄名 その他の情報〜

としてる
927NAME IS NULL:2007/10/15(月) 20:52:33 ID:Y520eQFI
>>926
ありがとうございます。
そっちの方がいいですねえ。でもそれをつかうとするとinsert またやり直しか。。。。
でもやりなおしてみます。
928NAME IS NULL:2007/10/16(火) 15:24:43 ID:???
nameとaddressのフィールドがあって、

address='○○県○○市〜'

と入力されているものとします。
このとき、県内、県外の順にソートしたい場合は
どのようなSQLを書けばよいのでしょうか?
929NAME IS NULL:2007/10/16(火) 15:39:04 ID:???
上の例をみてSQLいじっていたらできました。

select name,
case when address like '○○県%' then 1
else 2 end as odr from tblHoge
order by odr
とすればいいんですね。
930NAME IS NULL:2007/10/18(木) 01:23:37 ID:G1mBcPwT
oracle です。
テーブルAの各レコードのcolの値に対して
テーブルBからその値以下の最大値を得たいです。

【テーブル A】
col
10
20
30

【テーブル B】
col
5
15
18
25
30
40

【得たい結果】
5(Aは10。Bからこの値以下の最大値)
18(Aは20。Bからこの値以下の最大値)
30(Aは30。Bからこの値以下の最大値)


よろしくお願いします。
931NAME IS NULL:2007/10/18(木) 01:29:05 ID:???
>>930
Oracle で通るかどうかわからんけど

select (select max(col) from B where col < A.col)
from A
932NAME IS NULL:2007/10/18(木) 01:30:47 ID:???
>>930
いや、答えはすぐ書けるけど自分がどう考えたかぐらいは書こうぜ
933NAME IS NULL:2007/10/18(木) 11:20:44 ID:HHvByvdj
初歩的なことですが、、、。
DB2で抽出した数字を指定桁でのゼロ埋め(前ゼロ)で抽出する方法が
わかりません。。。

例えば、指定フィールドに「2」が入っていたときは
002 で抽出するというような方法です。

すいませんがよろしくお願いします。
934NAME IS NULL:2007/10/18(木) 14:00:05 ID:???
select '00' || 指定フィールド from なんか
935NAME IS NULL:2007/10/18(木) 14:30:26 ID:???
あと、桁数を指定して右から切り取ればOK。
Right() とか。
936NAME IS NULL:2007/10/18(木) 22:08:14 ID:???
>931
ありがとうございます
937NAME IS NULL:2007/10/19(金) 00:14:26 ID:dUbvn7+G
すみません。教えてください。

SUBSTR と LIKE ではどちらが処理速度が速いですか?

SELECT * FROM TBL WHERE SUBSTR(B,1,2) = '12'

SELECT * FROM TBL WHERE B LIKE '12%'
938NAME IS NULL:2007/10/19(金) 00:17:02 ID:???
ジブン デ タメセル ダロ ガ!!!!
939NAME IS NULL:2007/10/19(金) 12:41:53 ID:VIvt3Tqz
はじめまして。

いま定職がなくて、今度面接を受けるのですが、

SQLの知識が必要な仕事なのですけれど、

ぜんぜんSQLのこと理解していなくて。。。

一時間の面接でボロが出ない程度の知識をあと一日か二日で覚えようと思ってるのですが、

最低限どれくらいのことを知っていればいいのでしょうか。。。

どうかよろしくお願い致します><
940NAME IS NULL:2007/10/19(金) 13:05:31 ID:sjmFNeIx
質問させて下さい。

ACCESSでCOUNT関数内でDISTINCTが使えないので、
他に良い方法は無いか調べています。

| ID | SHOP | YYYYMM | DAY | PRICE |
 01    0001  200710   1     1000
 01    0002  200710   1      500
 02    0001  200710   2      800
 02    0002  200710   3      700

目的としては、上ようなテーブルで、
同一日に別なSHOPで買い物をしていないID(の人)で、
最大の単価(PRICEの合計)を求めたいのです。
(上の例だと3行目の800円が結果として欲しい)

SELECT MAX(total.hoge) as 最大の合計 FROM
 [SELECT SUM(PRICE) as total FROM tablename WHERE COUNT(DISTINCT SHOP) < 2
 GROUP BY ID, SHOP, YYYYMM, DAY;]. as hoge;

みたいな事でどうかな?と思ったのですが、ACCESSの制限で無理でした。
他にやりかたなどあれば教えて頂きたいのですが、如何でしょうか?
941NAME IS NULL:2007/10/19(金) 14:46:57 ID:???
>>939
http://pc11.2ch.net/test/read.cgi/db/1057289721/

ここのスレを1から全部読んで理解くらいになれば大丈夫だと思うお!
942NAME IS NULL:2007/10/19(金) 15:45:30 ID:???
>>940
そこはWHERE句じゃなくて、GROUP BY 句の後ろに
HAVING COUNT(DISTINCT SHOP) < 2
とすべきだと思うのだが、本当にCOUNT関数内にDISTINCTが使えないの?
943942:2007/10/19(金) 15:53:43 ID:???
ちょい補足。
HAVING count(DISTINCT SHOP)が使えるのなら、
GROUP BY句からSHOPは外せ。
944NAME IS NULL:2007/10/19(金) 18:11:12 ID:???
>>942
あーご回答ありがとうございます。
調べて回ったんですが、ACCESSではCOUNT内でのDISTINCTは
使えないんです。(ACCESS 2003)
その後調べていると、WHEREにCOUNTはダメっぽいですね、、、
HAVINGが良く分かってないので、使いどころが分かりませんでした(><)
修正します。ありがとうございます。
945940:2007/10/19(金) 19:29:00 ID:???
自己解決出来たので報告しておきます。
(もっとスマートなやりかたあるかも知れませんが、、、)

SELECT Max(total) AS 最大値
FROM [SELECT SUM(price) AS total FROM tablename as a
 WHERE NOT EXISTS (SELECT * FROM tablename as b
  WHERE a.id = b.id
  AND a.yyyymm = b.yyyymm
  AND a.day = b.day
  AND a.office <> b.office;)
 GROUP BY id, yyyymm, day, office;]. AS c;

で、一応940で求めている最大値=800が表示されました。
942さん、ありがとうございました。
946sage:2007/10/19(金) 23:38:32 ID:a5j8WAG3
>>941さん
ああ!どうもありがとうございます!!
これで受かる気がしてきました!!
わかりやすいですねー^^
947NAME IS NULL:2007/10/20(土) 16:32:47 ID:???
valueSQL使いたいんだが、繋ぎ方がわからん。
データソースって、何を入れればいいんだ?
948NAME IS NULL:2007/10/22(月) 05:26:32 ID:???
valueSQLって何かしらなかったんで調べてしまった。。
RDBMSは何使ってんの?
つーかスレ違いなんだが、汎用の質問スレ無かったっけ?
949NAME IS NULL:2007/10/23(火) 09:20:58 ID:???
>>946
まじかよw
950NAME IS NULL:2007/10/23(火) 13:35:37 ID:4X2HVnn9
SQLServer初心者です。
VB2005からSQLServer2005への接続について質問させて下さい。
同サーバーのプロジェクト名Test_dbにテスト接続はできるのですが、
データソース構成ウィザードで、テーブル、ビュー等の左側に「+」「−」
が無く、展開できません。 データソース、データセットとして実態を
取込めません。

ちなみにVB2005からAccessのテーブルをデータソース、データセットとして取込む事は
できました。

SQLServerから取込むにはどの様にするば良いでしょうか。
アドバイスお願いします。
951NAME IS NULL:2007/10/23(火) 17:03:06 ID:???
トランザクションの分離レベルのRepeatable Readって、
トランザクションAがRepeatable Readでトランザクション開始
->
トランザクションBが表AのレコードBをUpdate更新して、コミット
->
トランザクションAが同じ表AのレコードBをUpdateで更新

しようとしたらどうなる?
952NAME IS NULL:2007/10/23(火) 17:32:55 ID:???
>>950
ここはSQLServerのスレじゃないよ

Microsoft SQL Server 総合スレ 5
http://pc11.2ch.net/test/read.cgi/db/1175091880/
953NAME IS NULL:2007/10/23(火) 17:38:53 ID:???
>>951
共有ロック式の場合のRepeatable Readは、トランザクションが読み取ったレコード全部に
コミットまでの期間共有ロックをかけてゆくと考えればいい。
>トランザクションBが表AのレコードBをUpdate更新して、コミット
この前にトランザクションAがレコードAを読み取っていればトランザクションBの更新はロックされ待機状態になる。
この前にトランザクションAがレコードAを読み取っていなければ競合は起きない。

マルチバージョニングの場合はシリアライザブルと同じ動作になる実装が多いと思う。Oracleとか。
954NAME IS NULL:2007/10/23(火) 17:39:23 ID:4X2HVnn9
>952
失礼しました。 そちらに質問しました。
955NAME IS NULL:2007/10/23(火) 19:24:45 ID:???
なるほど。あなたは天才ですね。まぁ、言葉の定義の問題になっちゃうかも
しれまんせが、Repetable ReadはOracleとかのシリアラザブルのような動作が本来あるべき意味かなと
思いまして。よく、Repetable Readの説明で*実際にSELECT*文を同じ条件などで
検索させる説明がありますが、あくまで例で、本来はSELECT文を発行するかは関係なく、
Repeatable Readのトランザクションの*開始時点*の既に存在する行のみ
保証し、開始以降他によって追加された行(ファントム行)は保証しないのが、本来のRRなのかなと。
つまり、951の例では、トランザクショクンAの更新で、既にBによって更新され、
トランザクションの開始時点の行を保証できないから、エラーで落とす。
956NAME IS NULL:2007/10/23(火) 19:25:52 ID:???
それであれば、よく、Read Committedレベルの時に、日付のタイムスタンプ見てロスト
アップデート防いだりしますが、RRだと本来は共有ロックとか実装方式に関係なく、
ロストアップデートとか考える必要がない。

と、共有ロック方式のRRは偽RRじゃないかなと。まぁ、すっきりしました。
ありがとうございます。
957NAME IS NULL:2007/10/23(火) 20:27:42 ID:???
>>955
いや、ちょっと理解が違うような。

Repeatable Read と Serializable では、
あるトランザクションが一度読んだレコードが変更されないのはどちらも同じ。
(Read Committed では変更されることがありうる。
 そういう意味で>>956の理解は正しい。)

Repeatable Read と Serializable の違いは、
Repeatable Read ではあるトランザクションが最初にある条件で検索し、
後でもう一度同じ条件で検索したとき、レコードが増えていることが
ありうるのに対して、Serializable ではそれも許さない。
958NAME IS NULL:2007/10/23(火) 21:03:12 ID:???
>>957
あ、すみません。語弊がありました。
>Repetable ReadはOracleとかのシリアラザブルのような動作が本来あるべき意味
はOracleのシリアライザブルみたいに、シリアライズ不可能ですみたいな感じに951の
例で、「トランザクションAが同じ表AのレコードBをUpdateで更新 」の時に、
リピータブル不可能ですとエラーで落とすべきという意味です。おっしゃるとおり、Serializableはファント行も許さない、
つまり、トランザクション開始時のデータの完璧なスナップショットを保証することと思ってます。

ただ、共有ロック式のRRはトランザクション開始時に既に存在していた行を保証するのではなく、
開始後、SELECTして一度読んだ行だけしか保証しないので、こういうトランザクションの
振る舞いをRRって言わない方がいいのかなと思ってただけです。まぁ、言葉の問題ですが。えらい混乱しました。

959仕様書無しさん:2007/10/23(火) 21:41:35 ID:XcO2seYm
みなさんはSEなのかPGなのでしょうけど
具体的なビジョンはもってますか?
960NAME IS NULL:2007/10/23(火) 21:49:13 ID:???
>>958
951の例で言えば「トランザクションAが同じ表AのレコードBをUpdateで更新」は
Repeatable ReadでもSerializableでも許される。
(トランザクションBが更新する前にトランザクションAが読んでいなければ。)

つまり、問題は開始時点でどうたったかじゃなくて一度読んだかどうか。

その上で、Repeatable Readでは一度読んだ「レコード」に対してだけ
ロックがかかるのに対して、Serializableでは一度検索した「条件」に対しても
ロックがかかるというイメージ。
Serializableでは他のトランザクションが一度検索した条件に抵触するレコードは
更新できない。

ただ、この違いを実装しているDBMSがあるかどうかは知らない。
961NAME IS NULL:2007/10/23(火) 22:36:24 ID:BuF9yVzC
教えてください
列1,列2
A, AA
A, AB
B, BA
B, BB
B, BC
とある時に、列1でグルーピングされたROWNUMのような値を
得るにはどうしたらよいでしょうか?
つまり、このような結果が欲しいです。

列1,列2,欲しい値
A, AA, 1
A, AB, 2
B, BA, 1
B, BB, 2
B, BC, 3

DBはOracle10gです。
>>881と似ている気がするのですが、もう少しシンプルです。
962NAME IS NULL:2007/10/23(火) 22:47:31 ID:???
select 列1,列2, rank() over (partition by 列1 order by 列2) as ,欲しい値 
from xxxx order by 列1,列2
963NAME IS NULL:2007/10/23(火) 23:49:44 ID:BuF9yVzC
>>962
ありがとうございます。なるほど。

ついでに言うと、このような取り方もできますか?
列1,列2,欲しい値
A, AA, 1, 1
A, AB, 1, 2
B, BA, 2, 1
B, BB, 2, 2
B, BC, 2, 3

教えてもらった方法を参考に考えたのですが、
SELECT 列1, ROW_NUMBER() OVER(ORDER BY 列1)
GROUP BY 列1
の結果と、>>962で教えていただいた結果をJOINしようと思ったのですが、
もっと華麗な方法がありますか?
と、教えていただいた検索結果を結合しようと思ったのですが、
964NAME IS NULL:2007/10/24(水) 01:18:07 ID:???
あるテーブルに以下のデータが入ってるとします。
(テストの点数と氏名が入ってるテーブルです))

---------------------
name, tokuten
---------------------
satou, 60
nakata, 70
takahasi, 80
hukuda, 90
nakamura, 100

このテーブルからSQLで、以下の結果を導き出したいです。
---------------------
name, tokuten
---------------------
nakamura, 100
hukuda, 90
takahasi, 80
その他, 65
---------------------

上位三名のnameとtokutenを表示し、
四位以降は、"その他"でまとめて平均値をだします。
このようにするSQLはどのように書けばよろしいでしょうか?

MySQLを使っております。
よろしくお願い致します。
965NAME IS NULL:2007/10/24(水) 01:28:26 ID:???
cursor cur is
select * from A
union all
select * from B
for update

て書くとforうp句は書けネーヨって怒られるんだけど、もしかして ROWID を
セレクツするようにして、where current of cur って書いてるところを
where rowid = rec.rowid って書くと超いい感じじゃね?
やべ、スゲー発見しちゃったかも。
966NAME IS NULL:2007/10/24(水) 02:35:55 ID:???
>>964
SELECT CASE WHEN cnt=4 THEN 'その他' ELSE name END AS name,tokuten FROM (
  SELECT cnt , avg(tokuten) AS tokuten FROM (
   SELECT (SELECT CASE WHEN count(*)+1 < 4 THEN count(*)+1 ELSE 4 END FROM Table WHERE tokuten > T1.tokuten)AS cnt ,* FROM Table AS T1
  )AS T2 GROUP BY cnt
) AS T3 LEFT JOIN Table USING(tokuten) ORDER BY tokuten DESC;
967966:2007/10/24(水) 02:38:29 ID:???
見落としてた。
MySQLで動くかどうかは知らない。
968NAME IS NULL:2007/10/24(水) 04:50:05 ID:???
>>963
DENSE_RANK OVER(ORDER BY 列1)
969963:2007/10/24(水) 09:18:09 ID:qq2N0MNt
>>968
DENSE_RANK!!
列1の順位を同じ順位を飛ばさないように付与すればいいのか!思いつきませんでした。
結合しなくて済んで、すごくシンプルになりました。
ありがとうございます。

SELECT 列1,列2,
DENSE_RANK OVER(ORDER BY 列1) as G1
RANK() OVER (PARTITION BY 列1 ORDER BY 列2) as G2
FROM XXX ORDER BY 列1,列2
970NAME IS NULL:2007/10/24(水) 23:27:14 ID:j/8QV/sQ
テーブル名 d_tbl

YMD
20101010
20091010
20080808
20071010
20070928
20070303
20061220
20061014
20060907

上のようなデータが入ったテーブルから
2006年の10月だけを取り出すにはどうしたらいいのでしょう。
よろしくお願いします。
971NAME IS NULL:2007/10/25(木) 00:01:12 ID:???
>>970
select YMD from d_tbl where YMD like '200610*';
972NAME IS NULL:2007/10/25(木) 00:48:03 ID:???
>>971
%じゃね?
973970:2007/10/25(木) 08:05:06 ID:???
>>971
すみません間違いました。
何年かは関係なく、10月を取り出す場合はどうしたらいいのでしょうか。
974NAME IS NULL:2007/10/25(木) 08:42:15 ID:???
YMD like '____10%'
975NAME IS NULL:2007/10/25(木) 09:13:21 ID:???
substring(YMD, 5, 2) = '10'
976970:2007/10/25(木) 09:52:24 ID:arcZFewB
>>974-975
SUBSTRの場合も教えて頂き、ありがとうございます。
977NAME IS NULL:2007/10/25(木) 11:24:39 ID:???
どちらも9999年までしか使えないなw
978NAME IS NULL:2007/10/25(木) 11:46:39 ID:???
YMD like '%10__'
979NAME IS NULL:2007/10/26(金) 02:03:40 ID:EigH0966
すみません、SQLの第一、二、三正規系などが初心者向けに
解説されているサイトはないでしょうか?
意味がわからなく困っています・・・・参考書四でもさぱーりです。。。
因みに、やさしく学ぶ1SQLです
980NAME IS NULL:2007/10/26(金) 03:44:54 ID:???
つデータベースの教科書
981NAME IS NULL:2007/10/26(金) 07:12:20 ID:???
>>980
うざい
982NAME IS NULL:2007/10/26(金) 17:18:23 ID:BxaZnJ00
すいません。SQLを教えてください。

ID int
TYPE int
DATE datetime
からなるテーブルがありまして、以下のようにデータが入ってます。
| id | type | date |
| 1 | 1 | 2007-10-26 08:00:00 |
| 2 | 1 | 2007-10-26 09:00:00 |
| 3 | 1 | 2007-10-26 10:00:00 |
| 4 | 2 | 2007-10-26 11:00:00 |
| 5 | 2 | 2007-10-26 12:00:00 |
| 6 | 2 | 2007-10-26 13:00:00 |
| 7 | 3 | 2007-10-26 14:00:00 |
| 8 | 3 | 2007-10-26 15:00:00 |
| 9 | 3 | 2007-10-26 16:00:00 |

これをTYPE別にdateが最新の一件ずつで取りたいのですが、
どのようにしたら良いでしょうか?

上記の例の場合
| 3 | 1 | 2007-10-26 10:00:00 |
| 6 | 2 | 2007-10-26 13:00:00 |
| 9 | 3 | 2007-10-26 16:00:00 |
を取りたいと思います。

お手数おかけしますがご教授の程よろしくお願いします。
983NAME IS NULL:2007/10/26(金) 17:57:26 ID:???
typeをgroup化してdateでmaxを取る
984NAME IS NULL:2007/10/26(金) 19:55:11 ID:BxaZnJ00
>>983
レスありがとうございます。

select type,max(date) from table group by type;
これでtype別のdateは取れますが、
idが欲しい場合はどうしたらよいでしょうか?

select id,type,date
from table
where date in (
select max(date) date from table group by type
);
これだとダメですよね。
985NAME IS NULL:2007/10/26(金) 21:42:09 ID:???
>>984
ポカーン
>>980
986NAME IS NULL:2007/10/26(金) 22:18:04 ID:4m4QhRkA
すみません、質問させてください
aの重複値を無視して下のようにカウントしたいのですが
どのように書いたら良いのでしょうか?
ご教示お願いします

a b
------
1 1999
2 1999
3 2000
3 2000
4 2001
5 2001
5 2001

b  count(*)
--------
1999 2
2000 1
2001 2
987NAME IS NULL:2007/10/26(金) 22:21:41 ID:???
count(*) by b
988NAME IS NULL:2007/10/26(金) 22:22:25 ID:???
間違えたgroup by b
989NAME IS NULL:2007/10/26(金) 22:26:01 ID:???
>>986
SELECT b,count(*) FROM (SELECT a,b FROM Table GROUP BY a,b) AS T1 GROUP BY b;
990NAME IS NULL:2007/10/26(金) 22:35:37 ID:???
select b, count(*) from (select distinct a, b from Table) group by b;
991NAME IS NULL:2007/10/26(金) 22:48:40 ID:???
皆様ありがとうございます

>>988
その方法だと重複がカウントされてしまいました

>>989>>990
今MySQL 5.0.45で実験してるんですが、サブクエリが何故かエラーになってしまいました
ちょっと環境について調べてきます
992986:2007/10/26(金) 22:54:25 ID:???
すみません、完璧でしたテーブル名をタイポしてました
皆様ありがとうございます

サブクエリは必須みたいですね、勉強になりました
993NAME IS NULL:2007/10/27(土) 21:10:02 ID:???
994NAME IS NULL:2007/10/28(日) 22:51:58 ID:???
>>993

こっち埋めるか
995NAME IS NULL:2007/10/28(日) 22:53:24 ID:???
埋め
996NAME IS NULL:2007/10/28(日) 22:55:02 ID:???
ume
997NAME IS NULL:2007/10/28(日) 22:55:14 ID:???
998NAME IS NULL:2007/10/28(日) 22:57:37 ID:???
998
999NAME IS NULL:2007/10/28(日) 22:57:53 ID:???
1000
1000NAME IS NULL:2007/10/28(日) 22:58:25 ID:???
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。