1 :
NAME IS NULL :
2007/04/14(土) 21:19:55 ID:hWtCYSSP
で、全スレ>989宛。 995辺りので989〜992の機能は満たしとらんか? もしくは、意図が掴みかねる993のカキコ内容が要求仕様上重要なん?
3 :
989 :2007/04/14(土) 22:05:01 ID:vEBJlPWj
>>2 ああ、そうですね、それは無視してください。
4 :
989 :2007/04/15(日) 10:59:08 ID:???
>>995 とりあえず、これで試してみます。
ありがとうございました。
5 :
NAME 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; としているのですが、速度が悲惨に遅いです。 何かいい方法はないでしょうか?
6 :
NAME IS NULL :2007/04/15(日) 19:39:54 ID:8Gbsm4yF
mysqlについて質問です。 トランザクション可能なテーブルを利用した場合 通常のテーブルパフォーマンスとの差はどれくらいになるのでしょうか?
7 :
NAME 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=''」のように入れないといけないのでしょうか?
8 :
7 :2007/04/15(日) 20:14:46 ID:afmYW8Mb
my.iniの sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" をコメントアウトすることで解決しました。 ですが、これは何を意味しているのでしょうか?
>>7 エラーの内容をきちんと書いて質問するのはよい傾向。
あとはそのエラーをまず、よく読んで見ること。
> Field 'test_txt' doesn't have a default value
⇒ 分野'テスト_txt'には、デフォルト値がありません。
これでもわからないなら、まずデータベースについてもう少し
勉強することを薦める。
MySQLって専用スレないんだな
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書けずに困っています よろしくお願いします。
13 :
412 :2007/04/16(月) 16:20:57 ID:???
書き忘れですが、MySQL4,0xなので副問い合わせが出来ません・・・
あげさせてもらいます
SELECT COL3 FROM TABLE LIMIT 0,1 GROUP BY COL1, COL3 ORDER BY COL2 DESC
質問です。次のような表が二つあります。 表1 コード コード名 種類名 1 果物 区分コード 2 野菜 区分コード 10 あり 割引コード 20 なし 割引コード 表2 名前 区分コード 割引コード りんご 1 10 トマト 2 20 きゅうり 2 10 ぶどう 1 20 これを 名前 区分コード 種別 割引 割引有無 りんご 1 果物 10 あり トマト 2 野菜 20 なし きゅうり 2 野菜 10 あり ぶどう 1 果物 20 なし のような表にしたいのです。 UNIONを用いて式を書きたいのですがうまくいきません。 何か良い方法がないでしょうか?
訂正します 名前 区分コード 種別 割引コード 割引有無 りんご 1 果物 10 あり トマト 2 野菜 20 なし きゅうり 2 野菜 10 あり ぶどう 1 果物 20 なし
>>16 表1を二つに分ける。
既にその糞設計が所与のものならViewを使って別の表に見せかける。
>>16 select 名前,表2.区分コード,区分.コード名 as 種別,表2.割引コード,割引.コード名 as 割引有無
from 表2,
(select コード,コード名
from 表1
where 種類名='区分コード') as 区分,
(select コード,コード名
from 表1
where 種類名='割引コード') as 割引
where 表2.区分コード=区分.区分コード
and 表2.割引コード=割引.割引コード
20 :
16 :2007/04/17(火) 21:52:34 ID:???
>>19 ありがとうございました!
おかげで助かりました。
21 :
NAME 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
そのカウントはどこから出てきたんだ。
23 :
NAME IS NULL :2007/04/18(水) 17:50:43 ID:doDz5ry0
>>22 >キーごとに、過去の日付のレコード件数を取得したいのですが
これです。
4行目のカウント「2」は、キーが1で、
日付が2007/01/03未満のデータの件数(1行目と2行目)を数えています。
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なのかが分かりません。 このような場合には差集合は使えませんか。 また差集合を使わない場合、他に良い方法はありますか。
24です。 SQLが間違ってました。 select col2,col3 from TableA except select col1,col2 from TableB です。 よろしくお願いします。
>>24 01を持って来たいのか02を持って来たいのかはオマエが決めなきゃならん。
文字 a a a b c c ↓ 文字 個数 a 3 b 1 c 2 とするsql文を教えてください
count group by
>>24 スカラ副問合せが出来るDBMSなら
SELECT A.日付,A.キー
,(SELECT COUNT(*) FROM TBL B
WHERE B.キー = A.キー
AND B.日付 < A.日付
) カウント
FROM TBL A
ORDER BY A.日付,A.キー
>>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
)
33 :
21 :2007/04/19(木) 12:48:54 ID:???
>>33 01 AAAA 1
02 AAAA 1
のどっちか一件残すとなると>>.32だと両方消えるのでまずいのだが、
それでよかったのか?
ファンクションとプロシージャはどう使い分けるのですか? 違いがない様な気がして聞きました。
>>35 一般的にファンクションは更新が出来ない。
標準化は進んでないから例外はあると思うけどね。
37 :
NAME IS NULL :2007/04/19(木) 20:21:08 ID:iuRHnTpA
>>26 すいません。01、02はどちらが取れても構いません。
>>32 >>34 さんも指摘してくれているように
それだと01、02が両方消えるんですよね。
やっぱり、ストアドか何かでコントロールブレイクするしかないですかね。
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 よろしくお願いします
39 :
38 :2007/04/19(木) 22:27:27 ID:???
血を吐きそうになりながらも自己解決できました〜…… いやーSQLは奥が深い! よかったら オススメのSQL(mysql)の参考書・テクニック本とか教えてください
41 :
38 :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で無理やり消した みたいな…… まぁなんとか動けば 理解はあとからついてくるし
[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の平均を求めたいです
>>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でキーなの?なんか違和感が・・・。
sqlの問題を自宅のパソコンで勉強したいのですが、 初心者でも分かりやすく勉強できるサイトや無料ソフトは ないでしょうか?あれば教えてください。よろしくおねがいします。
>>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
>>24 select col1,col2,col3
from TableA
where (col2,col3)in(
select col2,col3
from TableA
minus
select col1,col2
from TableB
)
>>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
学校でSQLの勉強してて自宅でも学習したいけどSQL Serverっていくらぐらいなの?
ただ、のやつもあるだろ。
52 :
43 :2007/04/21(土) 15:24:26 ID:???
>>51 サンクスです
半年も無料で使えるんだ、だったらフリーにすればいいのにね
とりあえず、今のところは無料のソフト入れて勉強したいと思います
サンクスです
まともに運用する時のライセンス代が馬鹿高いから試用期間も長いんだろ
一方ORACLEは無料で期間無制限
56 :
NAME IS NULL :2007/04/22(日) 03:37:57 ID:p/CIzjLQ
質問させてください =の逆は!=ですがlikeの逆は何でしょうか? !likeだとエラーになりました…
not like
データベースのSQLの勉強初めて疑問があるけど、なんでACCSEとか入力するだけのソフト使わないの? わざわざ、言語で生成するメリットって自由性?自分の思ったような形にできること? まだ、初期段階で高度なことはしてないから気づかないだけかもしれないけど
日本語でおk
最初からツールを使うのと、基礎が分かった上で便利なツールを使うのとでは全く違うっしょ。 それに、何らかのプログラムからSQLを叩く時にAccessなんかは使えないし。
>>58 の言うACCESSとは、SQL*Plusやmysqlコマンドなんかも含むと予想
んで、「わざわざ、言語で生成する」とは、
>>60 でいう「何らかのプログラムからSQLを叩く」と予想
という意味でレスすると、SQL"だけ"勉強するのに「わざわざ、言語で生成する」メリットは特に無い
62 :
60 :2007/04/22(日) 14:25:42 ID:???
>61 自分は、SQL文の手打ち(コピペでもいいけどさ)のことだと認識した。
>>58 1.データベースの内容をある視点からみたいなー、と思う。
2.必要なSQLが頭に湧く。
3.「頭の中身を吐き出せるプラグが欲しい」と思いながら
ぺしぺしとテキストエディタへそのSQLを吐き出す。
4.カットアンドペーストでSQL*PlusやらCSEに貼り付けて実行。
・・・大概こんなもんで用が片付くから、わざわざテーブル間の関連付けが
どうとかACCESS使って定義するまでもないからでないかい?
そらユーザーの人に便利につかってもらう為、フォームやらなんやらもいると
なってくると話は違うけども。
> わざわざテーブル間の関連付けがどうとかACCESS使って定義するまでもないからでないかい? 意味わからん。 テーブル間の関連付けがどっかに定義されてるとでも思い込んでるのか? それても、制約条件のことを勘違いしているのか?
65 :
5 :2007/04/23(月) 00:24:30 ID:vffmtpA6
>>5 です。
どなたか教えていただけないでしょうか。
ググルにもググリようがありませんし、過去ログはdat落ちして見れません。
お願いします。
>>65 ソート済みのテーブルを別に作って定期的に更新すりゃいんじゃね?
ってSQL初学者が言ってますよ。
>>5 DBも書かないような奴はスルーされて当然
とあえて釣られてみる
69 :
5 :2007/04/23(月) 08:26:36 ID:vffmtpA6
>>5 です。
みなさんありがとうございます。
>>68 すみません、すっかり抜けていましたmysqlの4.12です。
>>66 テーブルを作ってみました。
驚くほど早くなりました!
>>67 インデックスを作ってみました。
こちらも驚くほど早くなりました!
取り急ぎ問題解決しましたが、
なんというか、SQL一発で解決できる問題ではなかったのでしょうか?
みなさんはどんな対処が一般的なのでしょうか。
>>69 つか、パフォーマンスチューニングのためには
何をしなきゃならんのか、もうちょっと勉強汁
>>58 自動でハナクソをほじる機械があれば一見便利そうに思うが
実際は自分の指でほじった方がずっといい。
それと同じ感覚。
>>64 いや、単に普段使うSQLが複数テーブルが絡む物ばかりなもんで、
テーブル1つだけの問い合わせについては失念しとった。
深読みさせてすまん。
>>72 余計意味わからん。
> 単に普段使うSQLが複数テーブルが絡む物ばかりなもんで、
そんな奴が
>>64 に書いてることを理解できないわけないと思うが...。
mysqlでランキングカラムを作るにはどうしたらいいですか?
>>73 すまん、そう返されると、そもそもの突っ込み意図が読み取れんとしか
言えん。
元々
>>63 では「テーブルのJOIN」位の意味合いでテーブル間の関連付けと
書いたんだ。要は複数テーブル使った問い合わせをACCESSで作るにしても、
テーブルやらクエリーやらの画面上の箱(正式名称忘れた)同士の列を線で
結んでやって、その結合一本一本にINNERやらLEFTやらの定義を付与するよな?。
その一連の作業を、ちまちまちまちまマウス操作でやるのは面倒なんじゃっ、
という事を言いたかっただけなんだ...。頭に完成形のSQLがある時は特に。
>>58 Access使うし便利だよ
でもJavaで作ったソフトが売れないと儲からないの
エディタでコピペとかするぐらいなら Access で SQL を直接入力すればいいだけだろ。 > 頭に完成形のSQLがある時は特に。
アクセスで使えるSQLなんてMySQLより制限されてるんだよ
>>77 直接SQL入力していいんなら、そもそもAccess使う意味薄くね?。
SQL内の予約語とか強調表示してくれんし。
というかこれまでの話は、大元
>>58 の
「データベースのSQLの勉強初めて疑問があるけど、なんでACCSEとか入力するだけのソフト使わないの?」
↓
「ツール生成によらないSQLのベタ書きがなんでいるの?」(俺解釈)
の質問に対しての「こんな理由(=うちには後者の方が楽)があるぞ」
レスだしな。
> データベースのSQLの勉強初めて疑問があるけど、なんでACCSEとか入力するだけのソフト使わないの? Accessの勉強ってならわかるが、SQLの勉強にはなっていないような気がする
>>78 Accessつ〜か、JETの方が
MySQLより柔軟なSQL書けるだろ。
バージョンによるだろ。 つーか、最新版ならどっちでもあまり不自由しないだろ。
84 :
NAME 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で一発で抽出する表記するのは無理があるんでしょうか?
distinctだとそれぞれの県名にどのIDが対応するのか分からないんじゃないの prefでGROUP BYしてMIN(ID)で降順にするとか
max(id)だろ
87 :
NAME 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
でいけるはず。汎用の方は実行速度が微妙かもだ。
あ゛、postgresql限定がまずい...。 SELECT * FROM ( SELECT DISTINCT ON (pref) pref,id FROM test1 ORDER BY pref,id DESC ) AS test2 ORDER BY id DESC
つーか汎用も SELECT * FROM ( SELECT pref, MAX(id) AS id FROM test1 GROUP BY pref ) AS test2 ORDER BY id DESC こんなんでいいよなぁ。ごたごた書いてスマン。
出題に回答するスレでもないんでしょ? いきなり答えまで書いちゃうよりも適当にヒントやるぐらいのがいいんでないの
スタンスもルールも個々人が好きなようにで良いだろ
92 :
NAME 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
>>89 select pref
from test1
group by pref
order by max(id) desc
/
>>92 >これを読み解けと言われたのですが、助けてもらえないでしょうか。
具体的に何を求めているのかが、見えてこないのですが、
SQL自体は、各テーブル名、カラム名を普通に解釈すると、
在庫数に対する売上げ個数の比率が多い上位3商品の情報を
求めるSQLかと思います。
>>92 とりあえず無駄なorder byがたくさんあるのは読み解いた。
意味があるのはrank() overの部分だけ。
サブクエリを全部Viewにしてみてひとつずつ何やってるか考えてみろ。
96 :
84です。 :2007/04/30(月) 13:29:07 ID:J6a1E/oV
みなさん、ありがとうでがんす。 とても勉強になりました。 来週、職場に戻りましたら、早速試したいと思います。
97 :
NAME IS NULL :2007/05/01(火) 12:25:11 ID:E0G15yAt
データベースの検索に関して、 A列とB列の値を加算して、その上で、少なくともA列の値が1以上である、 というような条件の下、最大の値をとるような行を求める場合には、 どのようなSQLを発行すればよろしいでしょうか? よろしくお願いします。
98 :
NAME IS NULL :2007/05/01(火) 12:29:41 ID:DXF7CsXb
>>97 何が最大?
A + BがMAXってことかいな?
だとしたら
SELECT MAX(A + B) FROM TABLE1 WHERE A >= 1;
でいいんじゃね?
>>98 返信ありがとうございます。
イメージとしては、
SELECT * FROM TABLE1 WHERE 先頭出現頻度 > 0 AND MAX(先頭出現頻度 + 隣接度)
といった感じで、
name p1 p2
hoge 1 2
hoke 2 4
といったデータがあったとき、 p1 と p2 を加算して最大のもので、
そのうち、少なくとも p1 が 1 以上である行の name を取得したいと考えています。
>>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;
なんてのでも取得可能だと思われ。
102 :
NAME 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 上では正しく実行されているように感じられるのですが、どこか誤っている箇所がありますでしょうか?
だからさぁ、エラーがでるって言うなら、そのエラーメッセージぐらい書けや、このカス・厨房
104 :
NAME IS NULL :2007/05/01(火) 20:57:59 ID:E0G15yAt
>>103 申し訳ありません。
エラーメッセージはデータベースを扱う環境に依存するものであると考えたため、
SQL の構文の正当性の確認には必要が無いと思い、添えておりませんでした。
エラーメッセージ(例外)は以下の通りです。
「1つ以上の必要なパラメータの値が設定されていません。」
(Visual Studio.NET2003, Access2003)
>>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;
>>104 俺の薄っぺらい知識で推測するに
>ORDER BY MAXVAL DESC;
を↓に変えろってことじゃないだろうか
ORDER BY MAX(WordRanking.BBB+俺.CCC) DESC;
そいつぁ薄すぎる
>>106 あ、昨日の晩の俺がいる。
便乗質問なんだが、例えばSQLイメージで
SELECT 血液型,count(*) AS 人数
FROM 日本人
GROUP BY 血液型
ORDER BY 人数
という構文(ORDER句に集約値につけた名前を直使用)は
大概のDBへの問い合わせに使えるのだろうか?
(
>>104 とは関係なく一般的な話として)
いや確かpostgresqlでは駄目だったんだこの構文。
>>109 確か7.2.1?(最後の桁が自信無い)
以前そういったことがあったんで、とりあえずGROUPとORDERを
SELECT * FROM(集約式)AS 結果 ORDER BY 人数
こんな風に分離して逃げた覚えがあるんだ。
7.xは今動作環境ないなあ 8.1.4ではとりあえず、それ使えてます
>>112 お、8.1.4ではいけると。なら俺の知識が古いだけか...。
7.4でもいける。 7.2でも使えてたような気がするんだがなぁ。
7.2以降とそれより前は大きく違うからな、7.1以前ならありうる気がしないでもない
115 :
NAME IS NULL :2007/05/02(水) 16:15:11 ID:M2WxE7YV
>>105 >>106 返信、どうもありがとうございます。
>>105 によって示されたコードに
>>106 が示した箇所を修正したところ、見事に動作しました。
とても助かりました。
どうもありがとうございました。
>>108 7.1.2があったから試してみたけど、いけたよ。
order by 2
も試したけど、これもちゃんとソートされた。
>>111 >>113 >>116 なら俺の記憶はなんか別の件をねじまげてしまったんだな。嘘言ってスマン。
連休明けに7.2.1(多分)の開発環境で自分でも試してみるよ。
今日の日付 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列に今日の日付の含まれる行」の次の行に該当するものを表示しようとしています。
すみません、自己解決しました。 IF( end >= now( ) AND start <= now( ) AND start <> '0000-00-00', DATE_FORMAT( now( ) , '%Y-%m-%d' ) , date ) AS bit ORDER BY bit
失礼・・・「"end列に今日の日付の含まれる行"の次の行に該当するものを表示」が出来ないorz
>>120 order by bit,end,start
ってすればいいんじゃにか?
>>121 なるほど。。ORDER BYで複数指定した際の考え方がいまいち分かっていませんでしたorz
その構文で期待通りの表が得られました。ありがとうございます。
123 :
NAME 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
>>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;
すんまそん。。 正規化して外部キーが沢山あるテーブルAにinsertする場合、 各情報をそれぞれの各テーブルにinsertしていき、そのidをテーブルAに外部キーとして 記録する、とゆー以外に なにか特殊なステートメントとかで、テーブルAに対するSQL一発で、全部済んじゃう なんていう虫のいい方法ってあるのでそうか。。 よろしくおながいします。m(_ _)m
ストアド
127 :
125 :2007/05/08(火) 16:05:56 ID:???
>>126 >ある表 (テーブル) の内容を編集して別の表に格納する大量データの更新処理などを
>データベースエンジン内部で処理プログラムを実行し、入出力 (I/O) のほとんどを
>データベース内部で完結することにより、クライアント側とのデータ通信による
>オーバヘッドを削減することでバッチ処理性能を向上させる「ストアドプロシージャ」が考え出された。
ttp://ja.wikipedia.org/wiki/SQL 定型処理を登録しておくっていう感じでしょうか。これなら出来そうですね。
でも、、、、SQLiteを使う予定なので、非対応でした。。orz
一応やりようはあるってことが分かってスッキリしますた。
どうもありがとーでしたー。
状況がよくわからないんだけど、トリガじゃだめなの?
トリガでストアドを実行することになるだろうね
ってSQLiteの話か。 DELETEやUPDATEのカスケードはできるだろうけど、INSERTはどうなる?
131 :
123 :2007/05/08(火) 18:53:56 ID:???
>>124 できました。
ありがとうございますた。
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
>>132 DUALを使ってるからOracleのtimestamp型かな?
計算結果がDATE型に化けてる感じだね。
TO_CHARで時分秒まで書式指定してみては。
>>133 ありがとうございます。
試してみます。
>>134 その問い合わせでVIEWを作ってみると
AはTIMESTAMP型になるが、BはDATE型になる。
>>133 の回答が正しいと思われ。
136 :
133 :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
>>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;
みたいにしなきゃならんと思われ。
138 :
133 :2007/05/10(木) 13:34:58 ID:???
>>137 たぶんそれです。
ありがとうございます。
早速試してみます。
ワキガ…それは、科学技術が発達した現代において、未だ解決手段を
見出せない不治の病…
ワキガ…それは、人と人を分かつ人種差別の根源。ワキガこそが
人々を争わせ、血と涙を流させる…
ワキガ…それは、夢ある若者を絶望させ、悪心を植えつける悪の源泉
ワキガ…それは、悪徳業者の儲け口。悪をのさばらせる恰好のエデン
ワキガは全てを破壊し、再生を妨害する。ワキガがある限り、この世は平和にならない。
こんにちまで、私達人間はワキガに対する対抗手段を持ち得なかった。
だが、2007年の五月。ついにワキガを撲滅するための手段が見つかった!
その名は「軽石療法」
軽石でワキを擦ることで、ワキガは消滅するのだ!なんと単純な治療法だろうか。
しかし疑ってはいけない。相対性理論も画期的だがシンプルだったではないか。
そう、画期的なものはシンプルなのだ。シンプルでなければいけないのだ。
つまり軽石療法こそが、ワキガを消滅させるための唯一の方法なのだ。
軽石療法について詳しく知りたければいますぐここへ行くことをお勧めする。
※わきが※ワキ擦り治療法※腋臭※
http://life8.2ch.net/test/read.cgi/diet/1172992888/ 君の人生に明るい光がさすことを約束しよう。さあ来たれ悩める民たちよ。
140 :
nobodyさん :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が書けません。 ご教授よろしくお願いいたします。
>>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
Webサービス(PHP)で使うユーザとグループをSQLで管理しようと考えています。 ユーザが複数のグループに所属できるようにしたいのですが、 ユーザとグループそれぞれのテーブルの良い関連づけの仕方が思いつきません。 ・ユーザのテーブルに所属グループを記す配列を付ける ・グループのテーブルに所属メンバーを記す配列を付ける 初めは以上の2通りのやり方を考えたのですが、SQLには配列が無いことに気付きました。 配列を実現するために、ユーザ(あるいはグループ)ごとに配列の代わりになるテーブルを作成するか、 カンマ区切りの数値を文字列として保存して配列のように使うか、 今はその二つの方法だけが思いつき、どちらが最適か悩んでいます。 SQLでの一般的な実現方法がありましたら、ご教授願います。
>>142 ユーザー表、グループ表、ユーザー・グループ対照表
144 :
nobodyさん :2007/05/11(金) 10:19:09 ID:5xTIeHlP
>>141 様
ありがとうございました。
ただ、mysqlだったのでto_numberは使えませんでした。
>>144 だったら最初からRDBMS名を挙げとけwww
MySQL4.1のリファレンス見ると
CASTかCONVERTが存在するから、それ使え。
>>144 あと、SUBSTRは、SUBSTRINGな。
お舞ら一般的な考え方を教えてください。 あるテーブルにUINTのフィールドがあったとします。 それはテーブルでユニークではなく、同じ値を複数のレコードがもちえるとします。 ここである操作に対して新しいレコードを作製しそのフィールドにそれまで使われてない値をいれたいんですが、この使われてない値を高速に持ってくる方法ってあるんでしょうか? インクリメントしていってもいいんですが、レコードが削除されて使われなくなった値とか出てきます。その値も無駄にすることなく使いたいのです。 ひとつ考えたのはインクリメントしていって上限までいったら歯抜けをつめなおして関連テーブルの値を更新するものです。 もしも使われてない値を高速に持ってくることができるならそうした処理をする必要がないので、何か手段があれば教えてくださいエロイ人(´・ω・`)
さんくすです。パフォーマンス見て検討してみます。
UINTって約43億?
設計上INSERTとDELETEが非常に多く繰り返されてしまうのかもしれないけど、
それでも実レコードが数百万とか数千万にまで膨れ上がると、
>>148 では遅くなるだろうな。(ハードも含めたシステムによるけど)
DBによるが、NOT IN より NOT EXISTSで相関クエリにした方が速そう。
でも結局、1度はテーブル全て読み込むことになってしまう。
ULONGを使うと事実上インクリメントしても一巡することはありえねぇーってなら
その方が速いんじゃね。
151 :
NAME IS NULL :2007/05/11(金) 23:54:19 ID:m7WrnMvu
DESC って何の略?ORDER BYで使うDESC。
152 :
NAME IS NULL :2007/05/12(土) 00:34:43 ID:o1KON6CY
descend
>>142 俺もあるシステム作ったときに同じようなことで迷った
結局、「ユーザーとグループの対照テーブル」に
「ユーザー列」+「所属するグループのキー」をカンマ区切りの文字列で格納して
JSPで分割しながら判定するようにしたけど、遅いし、無数に増えるグループだといつかカラムの容量超えるしで
結局所属できるグループ数と全体の最大グループ量に制限設けるしかなかったんだよな
よくありそうな話だし、DB設計者なら何かもっとよいDB設計がでてくるのかもね
「ユーザーとグループの対照テーブル」に ユーザーID, グループIDを追加していくだけじゃダメなんですか?
>>153 俺も、最初 DB 使い始めの頃は同じような考え方してたよ。
一般的な正解は
>>143 ,
>>154 の言う通りで
[ユーザ表]
id
名前
...
[グループ表]
id
名前
...
[ユーザ・グループ対照表]
ユーザid
グループid
のようにして、ユーザをグループに所属させる時は [ユーザ・グループ対照表] に
ユーザid と グループid の対を挿入していく。
ある名前のユーザが所属するグループ名一覧が欲しい時は、
SELECT "ユーザ表"."名前", "グループ表"."名前"
FROM "ユーザ・グループ対照表", "グループ表", "ユーザ表"
WHERE ( "ユーザ・グループ対照表"."グループid" = "グループ表"."id"
AND "ユーザ・グループ対照表"."ユーザid" = "ユーザ表"."id" )
AND ( ( "ユーザ表"."名前" = 'いいいい' ) )
のようにする。(OpenOffice.org の Base の例)
三つものテーブルにアクセスしないといけないし、[ユーザ・グループ対照表] は
結構行数も大きくなるので、なんか非効率な感じがするけど、インデックスとか
ちゃんと設定しておけば大丈夫。
凄くよくある話だし、データベースの基本だから「データベース 正規化」とかで
ぐぐって色々見てみるといい。わかってみるとそんなに難しい概念じゃないよ。
なるほど、そういうことか 何か意味もなく「ユーザ・グループ対照表」のユーザーIDもしくはグループIDを一意にしないとって考えにとらわれてた DB周りはあまり触らないのだけど、スッキリしたし勉強になったよ。ありがとう
157 :
NAME IS NULL :2007/05/13(日) 11:18:16 ID:CvhZCYzt
質問です。 データベースをとある条件で検索した多量の結果のうち、 項目の範囲を指定して、その範囲内だけのデータを取得するにはどうすれば良いのでしょうか? 例を挙げると、検索系のシステムで、最初の20件・・次の20件・・最後の20件、というアレです。 よくありそうな処理ですが、これの解説をされているサイト等、私には見つけることが出来ませんでした。 くだらない質問かもしれませんが、ご存知の方いらっしゃいましたらご教授くださいませ。
MySQL ならLimit SQLServerだったらTOP(だったか?) etc
>>157 limit offset構文が使えるなら、それで。
使えないなら別の方法でwww
多分にRDBMSの方言が出てくるから、
手前の使ってるDB名晒せ。
160 :
NAME 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を書けば宜しいでしょうか?教えて下さい。
dbms_output使っても経過情報を リアルタイムには出力できなかったと思うので、 SQLを実行するスクリプト側で1本目のSQL終了時に 標準出力にECHOさせるようにするしかない。
スクリプトの中に外部プロシージャー呼び出せばいいのでは。
>>158-159 標準のSQLではなく、データベースサーバによる拡張的に存在していたのですね!
使用しているのはMySQLなので、Limitを使ってみたいと思います。
これは非常に為になりました。どうもありがとうございました!
164 :
160 :2007/05/13(日) 11:59:43 ID:rmiwhMVe
更新情報をリアルタイム出力する必要はないです。
1個目のSQLが終わって2個目のSQLが開始されたことだけわかればOK。
ずっと放置して固まっていたというのが怖い。
>>161 >>162 それを調べるのにキーワードとなる単語はありますか?
もう少し詳しく教えて頂けると助かります。
>>164 「Oracle EXTPROC」
とか
「Oracle 外部プロシージャ」
とかだろうなwww
標準出力にECHOするだけの外部プロシージャなら、
CでもJavaでも簡単に書けるし。
>>162 外部プロシージャでECHOさせる発送はなかったわ、俺。
166 :
160 :2007/05/13(日) 14:06:49 ID:rmiwhMVe
何とかなりそうです。ありがとう。
167 :
162 :2007/05/13(日) 18:35:24 ID:???
>>165 ちなみにDB2/400とかだと経過情報をリアルタイムに見れるな。
普通(?)のDB2UDBがソレっぽい事できなくて驚いたので、
ちょろっと悩んだ時期があった。
最近は前もって「5分くらいかかるから気にスンナ」ってメッセージ最初に
出すようにしたけどな。w
168 :
NAME IS NULL :2007/05/14(月) 15:46:02 ID:o9PHUJbI
次のように社員番号と枝番で一意であるが、枝番がNullを許容する場合、 社員番号と枝番で一意であることをどのように示すのでしょうか? 主キーはなしで、社員番号と枝番を複合して、 ユニーク制約(ユニークインデックス)とすべきでしょうか? 社員番号 枝番 123 1 123 2 123 Null
>>168 枝番にNULLが来るなら
UNIQUE制約しかないと思うよ。
枝番0を新設するほうが簡単な気がする
俺もそう思う。
>>168 ふつう、nullにuniqueは効かないから(123,null)が複数エントリできてしまうよ。
MS-SQLServerは違うみたいだけど。
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 お知恵を拝借したいです。。よろしくおながいします。
>>173 >date(a_tb.date)
どのDBMSを使っているか知らないが、
date() というのが時分秒を切り捨てる関数なんじゃないのかい?
>>174 >どのDBMSを使っているか知らないが、
スマソ。SQLite 3でつ。
>date()�というのが時分秒を切り捨てる関数なんじゃないのかい?
yes。日付だけになるので、同じ日の同じURLの重複を排除すると言う感じになっておりますです。
そうしないと分秒が影響して、DISTINCTする意味が無くなってしまう気がするので。。
もしかして、、、ORDER BYで時間含めてソートしていても、
DISTINCTで日付だけでソートされた時に、ORDER BYのソートは全く関係なくなってしまうのでしょうか?
そんな気がしてきました。。
とすると、最新の5件に重複するURLが含まれないようにするには、SQLだけでは難しいのかな。。むー
もうちょと考えてきます。どうもありがとうございましたー。
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 こんなんじゃだめか?実行すらしていないが。 これじゃダメならサブクエリ使うといい
177 :
176 :2007/05/15(火) 17:19:50 ID:???
ごめ、忘れてくれ
178 :
147 :2007/05/15(火) 18:09:58 ID:???
たびたびすいません。 またIDのつけ方で悩んでるのですが、次のような方法はありですか? UINTなどをIDとする。 IDはオートもしくは手動でインクリメントさせる。 IDが上限まできたら、すでに削除されたレコードがあるとして0から連番になるように更新する。その際関連するテーブルのID値も更新する。 つめた後のIDの最大値+1を次のIDのシードとする。 ・・・こんな処理が必要なのか?だんだん疑問になってきた。皆さんID値ってどうされてるんでしょう?
>>178 普通にシーケンスつかって取得してるけどwww
>>178 > IDが上限まできたら
普通は、来ないようにする。
どの DBMS 使ってるのか知らんけど、最近の奴なら ID を 64bit にできるから、
よほど特殊なデータでない限りラップしたりしない。
>>178 32bitのIDを使い切る場合は、
1秒に10 IDずつ新規IDを発行すれば1日864000 IDで13年半ほどもつ。
64bit使い切ろうと思ったら、
1日4294967295(32bit相当分) IDを消費するために1秒49710 ID程度の新規発行が必要で
これでも11734883年ほどもつ。
まあなんだ頑張れ・・
182 :
NAME 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でいける書き方あったらお願いいたします。
183 :
182 :2007/05/16(水) 16:41:32 ID:???
ちなみにpostgreSQL8.1.8です
184 :
182 :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); でできました。(微妙にカラム名違うけど気にしないでください) お騒がせしました。
185 :
NAME 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"というテキストになって 計算に使うのが面倒なのですが、 秒数や何日、見たいな形で取得することはできないのでしょうか? お願いいたします。
186 :
185 :2007/05/17(木) 10:50:07 ID:EjOsYkVC
DBの種類書くの忘れました postgresqlです。
varcharの長さを短くしておくメリットって( ´Д`)なにか?あるんでしょうか? なければすべてvarchar(Max)とかしておけばいいのかと思ったのですが
>>185 extract(epoch from age(d))
とかでどうかなあ。
この辺よく変わるからバージョンによるかも。
>>187 その長さ以上の文字列が入っちゃだめなときとか。。
>>189 そういう制限ないときはMaxでいいとですか?
>>190 DBMSによるかのう。
無制限の可変長文字列はラージオブジェクト扱いだったりでいろいろ制限があるものが多い。
varchar(max)とか言ってるからMSSQL2005かな?
旧バージョンのtext型と違い制限は少なくなってるけどまだ何かあったはず。
>>191 いわれてるとおりMSSQL2005です。
なるほど。あえて8000文字までとMaxで分けてるからには実装で違いありそうですね。
通常のvarcharのサイズの長短でも影響あるのか調べて見ます。
193 :
NAME IS NULL :2007/05/17(木) 19:37:37 ID:wTPpdrT0
oracleで日本語の半角、全角を区別しないで検索する方法ってありますか?
>>187 ストアドプロシージャやユーザ定義関数内でvarchar(max)な変数が
使えなかった気がする。
なので、そういうので値いじろうとすると面倒になる。
【女性客拉致・強姦】 被害女性「男が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によって完全制圧される)
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}}
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')
>>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 を使ったような長い式を書く時に特にそう思う。
>>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;
んでも桶。まぁ、パーサが融通利かせれば如何様にでもなるんだろうけど。
200 :
196 :2007/05/21(月) 00:05:37 ID:???
>197 ありがとうございます countが0だと返らないのはなんかアレなんですが まぁプログラム側で処理すればいいですね >198 ただでさえ分かりにくいから できるだけ簡潔に書きたいですね >199 ホリデープログラマーは気にする必要なさそうですね ありがとうございました。またよろしくです
201 :
NAME 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 ??
>>201 何をもって「最後のレコード」とするのが不明だが、idが一番大きい物を選ぶなら、
WHERE id = (SELECT max(id) FROM Tbl_player);
サブクエリが使えないMySQLだったら、idで降順に並べ替えて1行目。
select name from Tbl_player order by id desc limit 1
MySQL 4.1 以降ならサブクエリ可。
だからサブクエリが使えないMySQLだったらって書いてるんだろ 使えるMySQLもあるからわざわざ書き足してる
>>202 ,
>>204 > サブクエリが使えないMySQLだったら
「全ての MySQL はサブクエリが使えない」と解釈することも可能。
特に
>>202 だけ読むと、サブクエリを使う例の後に書いてるので、
多くの人は「全ての MySQL はサブクエリが使えない (と
>>202 は
思っている)」と解釈すると思う。
「サブクエリの使えないバージョン (の MySQL) なら」と書けば
意図がより明確になる。
そもそも、
>>202 でわざわざサブクエリ使う意味がないし。
207 :
202 :2007/05/23(水) 23:16:06 ID:???
最初に断っとくが、
>>205 は俺じゃないからな。
>>206 確かに「バージョン」と書けばよかったが、
>>201 はMySQLを勉強...と断っているので、
「全てのMySQLはサブクエリが使えない」とはとらんだろう。少なくとも元質の人は。
個(最大値)を選択するのに、ベンダーに依存するLIMITクエリは、このスレ的に面白くないじゃん。
そもそもMySQLでサブクエリ使えるようになったって誰でも知ってることだろ……
うちの仕事先は3.23さ……orz
仕事で使ってるDBなんて、そう頻繁にバージョンアップするもんでもないけどな
>>210 運用してるDBはそうだな。
開発用ならあっちこっちにいろんなバージョンのDBが
あることの方が多いだろwww
212 :
NAME 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を考えたのですが、こういう書き方って普通でしょうか?
having c=max(c)
冠詞(The, A)を読み飛ばしてソートするSQL文をご教授くださいm(__)m データ The piano A doll the song songs 実行結果 A doll The piano the song songs
冠詞(The, A)を読み飛ばしてソートするSQL文をご教授くださいm(__)m table 'rooms' column 'object' songs The piano A doll the song 実行結果 A doll The piano the song songs
Replace みたいな関数があれば、それで消してからソート、で OK
>>207 > ベンダーに依存するLIMITクエリは、
>
>>201 はMySQLを勉強...と断っているので、
もしかして馬鹿?
終わった話題を蒸し返すバカ
あっ、悪い。 蒸し返されると困る人がまだいたんですね。
その二つは別問題だろうが、 行間を端折らずに全て説明しなきゃわかんないのかね。 ひょっとして生粋の日本人かな。
MySQLスレに行かずにわざわざここで聞いてるくらいだから
MySQLスレは初心者が質問できる雰囲気では無いからなあ。
>>220 > 行間を端折らずに全て説明しなきゃわかんないのかね。
へ〜、ちゃんと説明できるんだ。
じゃあ説明してみてよ。
なんかうるさいのがいるな。 ここは汎用のSQLの質疑応答がメインだから、 特定の処理系にこだわることはないし、方言に気を使う場所だ。 質問者がたまたま環境を指定したからって、それでしか使えない方法を 教えなくちゃいけないなんてことはない。
粘着しているのは一人だけだから放っておけよ。ただのキチガイみたいだし。
226 :
NAME 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のあるテーブルでバルクイン、アウトをやらないものなのでしょうか?) シーケンス番号に順序性等は必要ないのですが バルクイン、アウトを行うためだけに、このようなことをしようとしています。 定石等があれば教えてください。
そのDBMSには独立したsequenceオブジェクトはないのかい?普通はそれを使う。
>>224 > 質問者がたまたま環境を指定したからって、それでしか使えない方法を
> 教えなくちゃいけないなんてことはない。
いや、俺もそんなことは問題視してないよ。
ただサブクエリ云々の言い訳として「
>>201 はMySQLを勉強...と断っているので、」と
言う理由あげときながら、同じレスで「ベンダーに依存するLIMITクエリは」なんて書
く奴はアフォじゃね? って思っただけ。
見事に証明してくれてありがとう。(w
229 :
NAME IS NULL :2007/05/27(日) 16:08:41 ID:Hm1mP6ts
>>227 Identityでもsequenceでも同じことじゃん
違うだろ identity列はsequenceが自動採番される列のこと。
>>226 なんか矛盾してねぇ?
順序性等は必要ないのですが
バルクイン、アウトを行うためだけに、このようなことをしようとしています。
これによりシーケンス番号が変更されると聞いているため
Identityを使用できません
232 :
NAME IS NULL :2007/05/27(日) 18:08:58 ID:Hm1mP6ts
>>231 説明足らずでした
履歴を持つテーブルなのでプライマリーキー的にもうひとつ、かぶらない値が必要なのです。
通常履歴も管理するテーブルの場合、このように採番系のカラムをもつのは一般的ではないのでしょうか?
234 :
NAME IS NULL :2007/05/28(月) 02:17:14 ID:trwQ1/5+
インデックスについて質問 カラムA、カラムBの複合インデックスをもっている時 WHERE カラムA = ○○ で検索した場合、インデックスは使われる?
>>234 普通は使われるはずだが、心配ならプランを確認。
>>234 RDBMSのオプティマイザの実装に依存する。
RBOだと使われる可能性は高いと思うし、
SQLにオプティマイザヒントなんかを埋め込むことで、
特定のRDBMSならINDEXを使うようし向けることは出来る。
・・・が、すべてのRDBMSで必ず使われる保証は無いと思う。
CBOだったらいくら適切にINDEXが作成してあっても、
TABLE FULL SCANの方が低コストと判断されたら
全表走査することもある。
>>232 トランザクションがロールバックしようがコミットしようが、
単純に重複しなけりゃOKって用途であれば、
俺はOracleならシーケンス使う。
他のRDBMSで自動採番系の機能が有ればそっち優先で使う。
(SQL Server2005) 伝票の情報を保存するような以下のテーブルで (伝票コード , 得意先コード , 取引区分 , 金額) 取引区分が 1 , 2 , 3 , 4 しか入らない場合 インデックス(Non-Clusterd)をつけるのは無駄なのかな? select/Insertの比率9:1とします Insertする時にreal分割が発生すると取引区分=1 のレコード全部にロック(ラッチ)かかる? 1.ないよりマシ 2.選択性が低いので意味なし 3.さらにロック、ラッチの観点から逆効果
試しにやってみればいいじゃねーか。 不思議な質問だ。
めんどいじゃん。
答えるほうもめんどいわw
三択まで用意してやったんだぜ?サクッと答えられる奴いないの?
244 :
239 :2007/05/29(火) 18:38:08 ID:???
お前らどんだけだよ!にわかは氏ね!
試しにやってみればいいじゃねーか。 不思議な人だ。
>>239 「データが極端に少ない」 or 「データが大量にある」なら、
カーディナリティ低いINDEXにどれだけ意味がある?
実際は自分が想定するデータ件数で実験して判断しろよwww
>>226 >Identityとか使えればよいのですが
>パッチ作業が頻繁に発生し、バルクイン、アウトを行うのですが
>これによりシーケンス番号が変更されると聞いているため
>Identityを使用できません。
sql serverのことだったら
bcp in の時に -E オプションをつければシーケンス番号は変わらないぞよ。
通常タイムスタンプは同じ値でも幅があるから一意として使えない(1秒間に複数更新があった場合)。 けれど、SQLServerのTIMESTAMPは 行が更新されるたびに更新 される、データベース内で 一意なバイナリ形式の番号。 データを追加または変更 した日時とは関係ありま せん。 以下はTUMESTAMP の シノニムです。 ROWVERSION だそうだ。更新されれば自動的に値が変わる。 自明だけど、反復読み取りのチェックに使える。
>>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
あと履歴のレプリカ作って元表と全カラムjoinしてやれば、 たちまち履歴が更新削除禁止になるなんてこともできるぜ (連鎖更新、連鎖削除禁止)
>>248 SQL Server2005ですがTimestamp列で楽観的ロックをやってます
252 :
NAME 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値があるのでこういう場合は 切り分けて考えた方がいいのか悩んでいます。
いつもロムっていましたが質問させてください。 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
>>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つ目が入る
>>253 けっこう面倒そうだけど
合計売上額は先々月のデータとかあったら足していいのけ?
まずa表から月別の売上作ってみたら?
256 :
NAME 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表を結合するには(+)とか使えばいいのでしょうか。
よろしくお願いします。
>>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では使えないかもしれないから変えてね
表 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 とするにはどうすればいいですか?
replace(name_col,'name_','title_')
260 :
NAME IS NULL :2007/06/02(土) 18:52:09 ID:F7i5c8na
すんません GROUP BY と COUNT(*)を使ったクエリで COUNT(*)が 0 になる場合も 0 を出力してもらう方法ってありませんか?
col1 ---- A B D B っていうテーブルがあったとして、 col1 count(*) ---- -------- A 1 B 2 C 0 D 1 E 0 ・・・ Z 0 にして欲しいってこと? 無理だろ。
A-Zだけじゃないでしょ 全ての文字列の組み合わせで、0件の出力しなくちゃ
集計キーのマスタを用意すれば 外部結合とcoalesceで実現出来ると思う
>261 そうそう まぁ普通に無理っすね…… >263 別テーブルと結合って考えたんですけど めんどくさいっすね…… -- ありがとうございました
265 :
NAME 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'); ではダメですか?
>>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表.得意先コード
>>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表.得意先コード
最近の Oracle は GROUP BY の前に HAVING 使えるのか? まぁ普通に逆に書いてると予想。
>>269 ありがとうございます。
(1)と(2)を単独に実行しても正常に通りますが、
ご指摘のとおりHAVINGの使い方をGROUP BYの後に書くよう改めます。
(3)ですが3つの表から1つにまとめたいのですが、
皆さんならどのように書かれますか?
>>270 あんま読んでないけど
group by d表.得意先コード,b表.得意先名,c表.限度金額
じゃないのけ?
>>271 271様
お教えいただいたとおり修正しましたら動きました!!
ありがとうございました。
まだまだ勉強不足だと痛感しています…。
以下のようなテーブルがあって、ある指定された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 ・・・
274 :
NAME 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時間以上かかっております・・・。
>>274 それはもう実行計画見ろとしかいいようがないな
>>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
277 :
273 :2007/06/06(水) 00:56:27 ID:???
>>276 まだSQLに慣れてないので、別のやり方を挙げて頂けたのは勉強になり助かります。
ありがとうございました。
278 :
NAME 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 よろしくお願いします。
>>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 学年;
order by 学年 asc をつけといた方がいいかも。
281 :
NAME IS NULL :2007/06/08(金) 02:10:35 ID:oKxpcUps
SQLの勉強をしたいのですが無料で軽いフリーソフトがありましたら教えてください
byteaで画像データを格納したいとき、画像のパスを指定して保存、は可能ですか?
>>281 MySQL
SQL Server ExpressEdition
SQLite PostgreSQL
286 :
NAME IS NULL :2007/06/08(金) 13:49:30 ID:4l/ZZkFv
SQLプログラマーの先輩様に質問があります 現在私は日本電子専門学校(情報処理科1年)で先週初めてSQLServer の授業が行われたのですがプログラムを作る際考え方がわからなくて困っています(ノ_<。) 隣にいる同級生はスラスラ解いているのに自分は教科書見て探している間に時間が過ぎてる毎日です 俺はこんな風に勉強して上手くなった 式の組合せはこう考えればいいよってことがありましたら教えてください(^人^;)
DBに接続するアプリの作り方がわからないのか、SQLの書き方がわからないのかどっち?
>>286 何をどうして良いのか分からないんだったら、
目的の物を得るためには
どういう順番で何をしなければならないかを
考える癖をつけた方が良いよ。
やらなければならないことを
ナンバリングしながら箇条書きにしていくだけでも、
基本的なロジックは組み上がるからね。
あと、特に理由がなければ個人を特定されかねない情報は出すべきではないと思う。 エレクトロンの花とか言われるぞ。
>>282 可能だろ。
君が「指定されたパスから画像を読み込んで、データベースに食わせる」ことができるなら。
291 :
NAME 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です。
292 :
291 :2007/06/11(月) 14:53:30 ID:DdlgA2BI
あ、ごめんなさい。 自分でわかったSQLは 日付毎の合計を求めるだけなら SELECT DATE, COUNT(*) AS COUNT FROM TOUROKU GROUP BY DATE ; でした
>>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;
294 :
291 :2007/06/11(月) 15:18:34 ID:???
>>293 ありがとうございます、できました!
なるほどこれがサブクエリーってやつなんですね。
勉強になりました。ありがとうございました。
295 :
NAME IS NULL :2007/06/11(月) 19:49:09 ID:u6t10WUz
C#でOracleに接続してSQLの構文を書いてるのですが、ListBoxの選択されたアイテム をWhereで抽出したいのですが、どのように書いてみたらいいですかね?
>>279 できました。
ありがとうございました。
298 :
295 :2007/06/12(火) 16:12:20 ID:pwv6P776
inを使って構文を書いたのですが、上手くいかず・・・具体的にどんな感じに 書いたらいいでしょうか?
うまくいかなかった時のSQLを書いてよ WHERE xxx IN (1,2,3,4,5) とか
300 :
295 :2007/06/12(火) 17:10:51 ID:pwv6P776
WHERE xxx IN(' + listbox + ') このような形で書いたのですが、上手くいかず。。。
>>300 listboxの中身をちゃんと展開して、
>>299 みたいなカンマ区切りの文字列にしろよ。
302 :
295 :2007/06/12(火) 17:40:22 ID:pwv6P776
listboxの中身を展開ってどうやればいいんですか?
いや、最初っからSQLの話じゃなくてC#の話じゃねぇの。
聞くスレ間違っているよ。
SelectionModeがOneなら、
this.listBox1.SelectedItemで取り出せるんだから、
それをDbParameterかなにかで突っ込めばいいだろ。
マルチならthis.listBox1.SelectedItemsを展開連結なり何なりと。
>>300 のやり方を見ると
WHERE xxx = ’" + listBox1.SelectedItem.ToString() + "'";
としたいのか。それでもいいが、
普通はDbParameter経由で押し込むべきだろう。
なんにせ、板違いのスレ違い。
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
例えるのが難しいんだけれど、DBを作った掲示板のようなシステムを作ったとして、 あるスレッドのデータだけを取り出せるシステムを組みたい場合のテーブル設計として、 スレッド別にテーブルを新規作成してFROM句を変えるものと、 1つのテーブル内でスレッドID列みたいなものを作って、WHERE区で判別して抽出する方法がありますが、 どちらの方がいい、とかあるんでしょうか? ぽんぽんとテーブルを新規作成するのはマズイような気もするのですが、その根拠も分からないので迷っています。
リストのイメージ訂正 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 |
データマイニングって何か役に立ってるの?
>>305 スレッド別に扱うデータ項目が異ならない限りは、
スレッド別にテーブル作る設計なんてあり得ないだろ。
309 :
NAME IS NULL :2007/06/13(水) 18:34:40 ID:FlP9jY9L
>>305 スレッド死んだ時とか考えるのヤだなぁ、と思った俺は違うスレッドを想像していた模様なのはおいといて・・・
「効率いいだろうけど管理メンドクサイじゃん。テーブル10000ヶとか出てきたら俺逃げるぜ?」ってジレンマは
どうやら皆持ってたようで、SQL鯖2005では
「一つのテーブルだけどユーザ定義の関数に合わせて複数の実データ構造に分けて格納します。
クエリ次第では効率アップするかもよ?」
ってな不思議な仕組みが導入されています。勉強して使いこなしてください。正直、名前忘れたけど。
Oracleは不勉強につき勘弁。
>>304 膨れた結果から不要なものを除外する条件を追加すれ
311 :
305 :2007/06/14(木) 07:24:47 ID:???
>>309 FROM句を変えるだけの手軽さや、他のスレッドデータも1テーブル内に混在するという怖さばかり見てて、
「テーブル10000ヶとか出てきたら」というのを余り深く考えてませんでした。
確かに逃げたくなりますね・・・
それを考慮し、SQLサーバーなどが機能面でサポートしようとしていることも知れ、勉強になりました。
ありがとうございました。
>>309 Oracleならパーティショニングオプションと、
パラレルクエリーで、ってことになるだろうな。
10000どころか、2つだってありえない
カーソル定義で結合を行った場合でも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を更新出来るか教えて頂けませんか。
設計Phaseで試せる環境が無い ('A` Accessならあるんだけど。
>>316 OTNから試用版ダウンロードできるだろうに。
テーブル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)のレコードを取得したい。
>>319 AとBを結合して、CASE式で場合分け出来そうな希ガス。
多分Aを加工しBと同列でユニオンかな
Aの加工って?
>>322 システム日付でも固定値でも何でも良いから、
適用日の値を返すようなSQLで、
Aに対してSELECT書けば良いんだと思うが。
で、その結果とBのSELECTをUNIONして・・・
ってことだとオモ。
いや、そうやって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設計の話になっちゃうけど、こういうのって普通適用開始日と 終了日の両方持つのが一般的のような。
>>324 その場合どうなるべきか、ってのは
質問者の意図を推測するしかないが、
その例ではB表に7/1があるから、
指定日が6/25なら7/1のデータが
取得されないと不味いんじゃないか?
あるいはB表には6/25のデータがある、
ということなのかもしれん。
どっちにせよ、俺には
>>319 のデータ構造なら
A/Bの2表が有ること自体、変に思うんだが。
A表の履歴ログだ、ってことにしたって、
適用日が毎日ってならともかく、ある程度の間隔があるなら
お前さんの言うようにFrom〜Toで日付持たせてた方が
2次利用が楽なように思うしな。
326 :
325 :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)を取得 ってことだなぁ。 スマソ
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, --- と出るけどこういうことでよいのかな? >適用日以外の"キーが重複するレコードが複数"います ってのが意味わかんないので〜の所に何入ってるのかよくわからん。
>>327 推測だが、例えば会社マスタ_カレントと会社マスタ_予約があって
会社マスタ_カレント:
会社CD=01、会社名=▲▲▲▲▲
会社マスタ_予約:
会社CD=01、適用日=6/1、会社名=▽▽▽▽▽
会社CD=01、適用日=7/1、会社名=■■■■■
会社CD=01、適用日=9/4、会社名=○○○○○
てなってて、日付=6/20でマスタを取得すると、"▽▽▽▽▽" が欲しい、て
ことなんジャマイカ?
>>319 SELECT top 1 * FROM
(SELECT 名称 FROM TableA A
WHERE ID = 指定キー AND 適用年月日 <= 指定日
UNION ALL
SELECT 名称 FROM TableB B
WHERE ID = 指定キー
)
こんな感じか?
A ORDER BY 適用年月日 DESC ああしもた。いるなあ
>>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.適用年月日 )
ん?なんかおかしいところあった? 環境の違いによらずに安定したパフォーマンスが出るよう書いたつもりだけどね。
全然関係ないけどぉ、最近のOracleはSQLが拡張されまくってて便利つーか ワケワカランつーか、全然追いつけない。 >319 の質問も、例えば環境を最新のOracle(10G?)に限定すればなんか使える 独自機能ないかなぁとオモテ調べてみたけど2分で挫折
>>333 >>335 下のほうのBテーブルから取ってくるところの
existsの中が間違ってるだろ。
指定する日付がBテーブルに存在する全ての適応日より
大きいなら欲しい結果が返ってくるけどね。
>>336 あ、なるほど。
and B1.適用年月日<=指定日
が抜けてたってだけか。
329と331って、なんとなく感覚的に331のほうがコスト高い気がするけど。 top nはsqlserver?oracleだと329をさらにselectで括ってrownum=1で抽出 か。sqlserverがあればサックリコスト見れるんだけど。
あぁもう効率考えるの鬱陶しいから1時間に1回バッチ処理しちまえっ。お前ら10分間待てっ。 バッチ処理中の処理要請?そんなのキューに10分だけ溜めとけっ。 後でエラーは返送するから再入力よろしくっ。 …って、全部キューに溜め込んだ方が単純でいい? …あれ?それぐらいCOBOLで30年前からできてる? …え?FTPで都度転送するだけで仕様満たしちゃう? 嗚呼、汎用機万歳orz
まあ、unionとか使い出すとCOBOLやらRPGの方が性能出るだろうなぁ。
341 :
NAME 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] # 次の行 としているのですが、どう考えても無駄すぎるので、うまい方法があれば教えてください。
同じ値が無けりゃ、未満で最大とより大きい最小をもってくりゃいいな
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)側で処理させる方が楽っぽ。
345 :
NAME IS NULL :2007/06/19(火) 16:06:08 ID:nZn4pPC5
数値をカンマ区切りにしたいんですけど、できますか?
to_char(num, '999,999,999'); とかでどうか
347 :
NAME IS NULL :2007/06/19(火) 18:41:50 ID:JyFlQMM7
月の検索ってどうやったら良いですか? 「誕生日の近い人一覧」を表示したいのですが、 データベースに「1982-12-01」(データ型は日付)で入っていて、 年を無視して月のみで検索できずに悩んでます。
>>347 where Month(日付) = ?
Month()は日付から月だけを抜き出す関数の意味。標準じゃないから各DBMSのマニュアルで調べる。
ただし、この方法では日付に索引があってもつかわれないから、
頻繁にこの問い合わせをする必要があるなら、
別に月だけのフィールドをテーブルに追加して索引を作っておく。
where to_char(hiduke, 'MM') = '01'
とか。
>>348 も書いてるけどこのままじゃインデックスが使えないので
to_char(hiduke, 'MM') に対してインデックスを張るとか工夫が必要。
日付関係はDBMSで違っていてほとんど統一が取れてないから DBの種類は書いといたほうがいい。
「誕生日に近い人」なら月よりも、その年の通算日数の方がよくね? EXTRACT(DOY FROM 誕生日) 又は date_part('doy',誕生日); 月末基準で調べても、翌月初旬の日を出てくるし。 ex.) 誕生日が10日以内の人 SELECT * FROM Table WHERE EXTRACT(DOY FROM 誕生日) - EXTRACT(DOY FROM CURRENT_TIMESTAMP) BETWEEN 0 AND 10;
352 :
347 :2007/06/20(水) 11:01:23 ID:???
たくさんの回答に感謝です。
とても参考になりました。
ありがとうございます。
やり方もたくさんあるのですね。
決まった形が無いみたいで、自分みたいな初心者には、とても難しく感じますが、
がんばろうと思います。
お返事、遅れてしまい申し訳ありませんでした。
>>351 いわれて見るまで、気がつかなかったです。
そうですね。月末の事を考えると、この形式がベストみたい。
ありがとうございます。
>>350 DBは、postogresu使用です。
教えていただいたSQLが通ったので、よかったですが、
次回からはDBの種類も記入することにします。
ご指摘、ありがとうございます。
>>348 ,349
「インデックスを張る」ですか。
うーん。ちょっと難しそうなのと、
>>351 の方法で解決したので今回はなしで行きたいと思います。
インデックスについて、また調べてみますね。
勉強になりました。ありがとうございます。
353 :
351 :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;
とすれば、インデックスを使って抽出するようになる。
--元質の人はもう見てないだろうけどなぁ。
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文を正常に動作させたいのですが、なんとかならないものなのでしょうか? テーブル定義書も無い中、解答が得られるとは考えにくいのですがわかる方いらっしゃった らぜひお願いします。
355 :
NAME IS NULL :2007/06/21(木) 23:47:04 ID:T2K/E1DB
現在学校でSQL Server の勉強をやってるんですが自宅でも勉強したいのですが無料で軽いフリーソフトがありましたら教えてください
357 :
355の者です :2007/06/22(金) 00:14:12 ID:Jkf5KiTi
先週ヤフオクでSQLの参考書(やさしいSQL入門)というのを購入したんですが 内容がSQL Serverのことが全然書かれてなかったので別の参考書を購入しようかと検討中なんですがお勧めの参考書ってありませんか? 問題と説明が詳しく書かれているのがありましたら教えてください
>>357 普通にDBマガジンとかWEB+DBPRESSとか雑誌を買えよ。
>>357 技術本、参考書のたぐいは
自分に合う合わないが有るから
本屋で立ち読み汁。
>>358 そういう雑誌って初心者が見ても楽しめますかね?
むしろ初心者向け情報が中心という気もする。 初心者と言わないでも、DB屋さん以外のPGとかが本棚に置いとくくらいには。 あと、定期的(毎年3〜4月号あたりかな?)に、初心者向け特集をやる技術系雑誌は多いと思う。
>>361 ありがとうです。大学の図書館にあるか見てきますノシ
363 :
NAME 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なら考えられる原因を指摘してくれ 色々と初心者な上、オープンソースのプログラムを使ってるからよく分からんのじゃ
>原因不明のエラー こっちを詳しく
365 :
NAME 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にアクセスしているみたいなのだが
エラー出力がこれだけだとどうにも対応できず、ここに来てしまった
そういう時はコマンドラインでもGUIでもいいからそのDBで 手でSQLを実行してみればいい それはSQLの一部でしかないので、全体がわからんとあれだけど 前の行には出てないの? あとMySQLのバージョンも書いてくれ
>>363 Apache + MySQLとはいえ、
PHPで何かのスクリプトをApacheから動かしてるから
エラーがApacheのログに残ってるんだろ?
なんてスクリプトなのかもうちょっと詳しく。
エラーにある内容はWhere句の式としては
妥当である可能性は高いけれど。
368 :
NAME IS NULL :2007/06/22(金) 15:31:21 ID:H0pevYdj
>>366 全体は分からんけど、とりあえず探してみる。
一つのPHPファイルに記述されているのはそれくらいで
RequireやらIncludeで辿ると膨大な数のファイルでちょっと無理かもしれんが・・・
何度そのPHPを実行しても出てくるのはその一行だけ。
Mysqlのバージョンは6.0Alpha
369 :
NAME 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が怪しくなってきた・・・
これ消すだけで解決したらすまん。
370 :
NAME 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>"; } } 上下少し省いたけどこんな感じ
371 :
NAME IS NULL :2007/06/22(金) 15:49:12 ID:H0pevYdj
解決した 誰がどう見てもPHPにErrorを出力するスクリプトが書いてあっただけですね だめだ俺・・・早くなんとかしないと・・・ もう済んでしまったことはしょうがないので今後気をつけます スレ汚し失礼しますた
ハゲワロス
デバッグならcgiやphpやjspでSQLをstderrに出すのはよくやる。 残ってたって事か。しかしこのスレで延々とPHPのソース貼られても・・・
以下の様にUNIONの結果をソートすると劇的に速度低下してしまいます。 SELECT 商品名,値段,産地FROM 肉 UNION ALL SELECT 商品名,値段,産地 FROM 魚介 ORDER BY 値段 上記クエリは簡略例ですがUNION結果に対するORDER BYは必須です。 ORACLE9です。ヒントでもいいので情報ください。
SELECT 商品名,値段,産地FROM 肉 ORDER BY 値段 UNION ALL SELECT 商品名,値段,産地 FROM 魚介 ORDER BY 値段 ってすればいいんでね?
>>375 合わせた結果をソートしたものと、各々ソートしたものを合わせた
結果が同じとは限らんだろ。
そもそもそんな書き方できないし。
>>374 個々のテーブルのソートは早いの?
>> 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文を教えてください。
>>377 UNIONしたVIEWにINDEX張ればいいんでね?
9iはviewにインデックスなんて張れるんだっけか?
viewにindex張れるのってSQL Serverだけ?
>>378 クロス集計ですね。
select 年月,
sum(
case
when 予算項目 = 水道費 then 予算金額
else 0
end) as 水道費,
from 予算テーブル group by 年月;
384 :
378 :2007/06/24(日) 15:11:37 ID:+uq9wgbc
>>382 ,383
ご教授ありがとうございました。
参考にさせていただきます。
ご教授とは - 大辞林 第二版 (三省堂) からの引用 (1) (ア) 児童・生徒に知識・技能を与え、そこからさらに知識への興味を呼び起こすこと。(イ) 専門的な学問・技芸を教えること。「国文学を―する」「書道―」 (2) 大学などの高等教育機関において、専門の学問・技能を教え、また自らは研究に従事する人の職名。助教授・講師の上位。 ご教示とは - 大辞林 第二版 (三省堂) からの引用 (1) [「きょうし」とも] おしえしめすこと。示教。「御―を賜りたく」 (2) 実験・調査で、研究者の意図する行動を被験者にとらせるための指示。
>385 引用だけの文章は違法。
引用先が書いてあればOK 元は紙媒体のケースもあるし
さあ、通報した。
>>388 あーつまり、引用ってのは、利用する側の著作物が主、利用される側の著作物が従の関係のものを言う訳だ。
まとめると、
・385は引用では無い。
・386は間違っている(引用と言うからには利用される側の著作物が従であり、これは違法にならない)。
・388のリンク先ではモンタージュ写真の場合についてのみ語られている(385の場合ではどうなるかは正確には不明)。
・385は著作権違反に問われる可能性がある(素人考えだがモンタージュ写真だろうが辞書の内容だろうが俺は同じに思える)。
という事か。
後385は、辞書では無く↓(教授 教示でググって最初に出たサイト)のコピーに見える。
ttp://blogs.wankuma.com/jeanne/archive/2005/11/24/19566.aspx
皆様のお力をお貸しください。 下記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上で処理しますか? ご指導のほどよろしくお願いいたします。
>>391 製品マスタにプライマリキーのような物が見あたらね。
-- 複合で出せないわけではなさそうだが。
いったいマスタテーブルと他のテーブルとをどう関連付けりゃいいのやら。
出力例の1行目の数量が20になってのもイマイチ不明。
なんか、マスタの親品番を再帰的に掘っているようにも見えるが、再帰するときの条件も不明瞭。
設計からやり直した方がよだそうだな。
393 :
391 :2007/06/26(火) 04:03:22 ID:???
>>392 殿
先ほどは各テーブルの要点になりそうなところだけを抽出したため、こんな感じになってしまいました。
実際のテーブルは以下のとおりです。
[注文テーブル]注文番号(PK)/ 注文品番/受注数量/注残数量/...
└───┐
[引当基本情報テーブル]注文番号(PK)/引当番号(PK)/ 出荷予定品番/引当数量/...
│ │ └──────────┐
│ │ │
[引当詳細情報テーブル]注文番号(PK)/引当番号(PK)/明細行番号(PK)/製造日番/... │
┌─────────────────────┘ │
[進捗管理テーブル]製造日番(PK)/品番/工程管理コード/在庫数/良品数... │
│
┌───────────────────────────────-┘
[製品マスタ]製品名(PK)/生産親品番/製品タイプ/シリーズ/電圧記号/容量記号/特性1/特性2/特性3/サイズ記号/ユーザーコード/加工記号/社内管理識別記号/サイズ1/サイズ2/...
394 :
391 :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文を考えていたのですが、さっぱり考え付かず、ここに質問させていただいた次第です。
395 :
392 :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鯖で動くかどうかもワカラン。
396 :
392 :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) でもいいんだけど。 で、これ以上突っ込まれて聞かれても俺は答える気力ない。 と、先に断っておく、スマソ。
397 :
392 :2007/06/26(火) 07:35:56 ID:???
何度もスマソ。WHRER句のOR以下もおかしいな。一つにまとめて WHERE (T3.ptotal < T4.ntotal AND T3.ntotal > T4.ptotal) ORDER BY order_num; って一つじゃないか。もう、頭まわってね...orz まだ間違ってるかも。
SELECT * FROM テーブル WHERE フィールド1 = 条件文 OR フィールド2 = 条件文 OR フィールド3 = 条件文 で検索した結果で、何に引っかかって表示されているのか調べる方法はないですか? ずららーっと、結果は問題なく表示されてるけど、どの検索条件に一致しているのかを知りたい。
>>398 取得するカラムの1つをCASE式で評価して
適当なフラグ立てると良いんじゃね?
400 :
398 :2007/06/28(木) 17:41:46 ID:???
ありがとう。 やってみる!
401 :
NAME IS NULL :2007/06/29(金) 19:17:50 ID:0VuwylaN
住所 結婚 ------------- 埼玉 未婚 群馬 既婚 埼玉 未婚 山梨 既婚 東京 既婚 こんな感じのデータを ↓のようなデータに表にまとめたいのですが、どのようなSQL文を書けばよいですか? 住所 既婚 未婚 ---------------------- ・・・・ 群馬 3104 1202 埼玉 7937 3929 千葉 6113 3797 東京 9232 7088 山梨 2987 1022 ・・・・
select 住所 ,sum(case when 結婚='既婚' then 1 else 0 end) 既婚 ,sum(case when 結婚='未婚' then 1 else 0 end) 未婚 from テーブル group by 住所;
phpMyAdminでテーブルの作成日時と最終更新日が表示されていますが システム関数みたいなもので取得できるのでしょうか。
Enterprise Manager のクエリ実行で出てくる DERIVEDTBL とは一体なんなんでしょうか? ヘルプ見ても載っていないし、 検索しても海外のサイトばっかりで訳わかめです(;´Д`)
405 :
NAME 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」 の構文エラー:演算子がありません といったエラーが返されます。 どういった原因により構文エラーが発生しているのでしょうか。 よろしくお願いします。
あなた、何をしたいの?
>>403 show table status like 'テーブル名';
>>404 derived table (導出表?)
クエリから導き出されるテーブルとかそんな意味合いだったと思う
>>405 [1].ホゲホゲ
全部RDBMS依存なんで次からは適切なスレを探してね
408 :
403 :2007/07/03(火) 02:58:32 ID:???
>>407 さん
ありがとうございます、取得できました!
descぐらいしか思いつかなかった自分がお恥ずかしい。
409 :
NAME IS NULL :2007/07/03(火) 11:20:36 ID:kH14UgW7
Accessで質問です。 データで、「住所」フィールドから都道府県を抜き出したく思い Accessのフィールドに↓のように書きましたが、うまくいきません。 都道府県: Left([住所],InStr([住所],"都" Or "道" Or "府"Or "県")) どのようにしたらよいでしょうか? SQLでもその他の方法でもかまいません。 元データ 東京都新宿区 埼玉県秩父市 東京都杉並区 群馬県高崎市 京都府舞鶴市 ↓ 抜き出したいデータ 東京都 埼玉県 東京都 群馬県 京都府
>>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 住所;
でパフォーマンスは悪そうだけど、何とか取れるとは思うが。
411 :
NAME IS NULL :2007/07/03(火) 14:22:42 ID:DZCkMDG+
>>407 どうもありがとうございます。
おかげで作業を進めることができました。
412 :
NAME IS NULL :2007/07/03(火) 14:23:22 ID:DZCkMDG+
413 :
NAME 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)
SELECT count(name) FROM (SELECT name FROM list01 INTERSECT SELECT name FROM list02) SQLiteだとこれでいけたけど。 PostgreSQLだと後ろに名前つけないとならんかった
415 :
391 :2007/07/03(火) 19:57:35 ID:wpvZa8NM
>>392 殿
返事が遅くなりまして申し訳ございません。
教えていただいたSQL文を実際の環境に合わせて実装してみたいと思います。
ありがとうございました。
416 :
404 :2007/07/03(火) 20:28:57 ID:???
>>407 ご解答ありがとうございました。
少しすっきり致しました
417 :
NAME 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を使用しています。
4123って4種類限定なの? ORDER BY id = 4 desc, i とか使えるよ
最後、d が抜けた。 ORDER BY id = 4 DESC, id ASC ね
420 :
417 :2007/07/04(水) 10:16:13 ID:qkT/tPH1
>>418 ありがとうございます
実際には10種類ほどあります
id=[番号],で順番を指定できるんですね
421 :
413 :2007/07/04(水) 10:33:47 ID:???
>>414 ありがとう!その通りでいけました!FROMのところにサブクエリ使えるんだね・・・。
外部参照キーが自分自身のテーブルにあるカラムをさす場合について質問です。 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を書けばいいでしょうか。 あるいはヒントとなるキーワードを教えてください。
424 :
仕様書無しさん :2007/07/04(水) 13:32:00 ID:fg5TH2Y3
>>422 なんでnot Nullなん?null項目がでるわけない上に、そりゃぁ検索結果
がおかしいでしょ。
NOTはずすか、外部結合だな。
425 :
422 :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であるようなテーブルしか使ったことなかったので、今回の場合はどうしたらいいか分かりません。
426 :
422 :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
428 :
422 :2007/07/04(水) 17:02:05 ID:???
>>427 ありがとうございます。外部結合のleft joinが答えでした。
こんなの知らなかったよー。SQL入門じゃ教えてくれなかったから、中級以上の機能なのでしょう。
where t0.mgr_id = t1.mgr_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 ○○
とか続くのもあるから(というよりそんなのばっかり)、そうなると分からない。
432 :
422 :2007/07/04(水) 17:59:56 ID:???
>>430 丁寧な回答ありがとうございます。
SQLは宣言的だから中の仕組みががblackboxであり、そのためにチューニングで苦労しますよね。
Javaのチューニングだったら簡単なのに。
LEFT JOIN も知らなかったやつがチューニングの話をするなんて、 何かの冗談ですか
435 :
NAME 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; と書くしかないのでしょうか?
よくわからんが、 FROM xxx LEFT JOIN yyy ON 〜 LEFT JOIN zzz ON 〜 みたいに並べることはできる。
437 :
435 :2007/07/04(水) 18:44:01 ID:qkT/tPH1
>>436 ありがとうございます
並べて書いてみます
>>434 ネタだろwww
・・・と思いたいが、パフォーマンス云々の寝言言う前に
とりあえず実行計画確認してから来いと言いたい訳だがwww
439 :
NAME IS NULL :2007/07/05(木) 18:16:43 ID:XuEszA9P
インデックスのパフォーマンスに関する質問です。 性別のように、カーディナリティの低い(とりうる値の種類の少ない) フィールドはインデックスを使ったほうが遅くなる、 むしろテーブルスキャンのほうが速い、とよく聞きます。 しかし、 select count(gender) from mytable where gender = 1 のように、単純に件数をカウントする場合は、 参照数も少なくて速いように思われるのですが、 こういうクエリが多い場合でも、インデックスは 使用しない方がよいのでしょうか。
>>439 別にインデックス作っても良いんじゃね?
インデックス作っても良いけど(コストベースオプティマイザのDBMSでは) 使われないかもね。 とりあえず作ってみて実行計画と実際の処理時間を 調べてみるのが早いと思うけど。
>>439 別に作ったら作ったで検索は速くなると思うが、その分データの追加の時に
遅くなるからなぁ。
DB2とかは各カラムの統計情報を収集してオプティマイザが働くので、
まあ、性別みたいなのにはINDEXつけなくても、そこそこにスピードでるけど。
実際はRDBMSによって動作はまちまちなんで実行計画で確認汁。
>>439 DBによって違うかな?
PostgreSQLの場合はとインデックスが張られているフィールドでCountしても
必ずテーブル本体を読みに行くので、プランナが判断でインデックス検索を
必要としないと下すと、端からインデックスは使用されない。
Oracleはインデックス検索だけで、Countできるらしいので、その場合は有用かも。
-- 本当かどうか、この質問にも当てはまるかどうかも知らないが、どっかにTipsとして取り上げられてた。
一応PostgreSQLの場合はと限定すれば、
プランナの判断とINSERT時のインデックス構築を考えれば、
使われなさそうなインデックスは張らないほうが得策となる。
445 :
439 :2007/07/05(木) 21:54:11 ID:???
>>440-444 様
回答ありがとうございます。
総合すると、エンジンによって処理が異なるため
一概にどれが正解ということはない、
オプティマイザの結果と相談、ということですね。
さらに、更新時のパフォーマンスとのトレードオフも
考慮すべきと(これはインデックスの一般的な検討事項ですが)。
大変参考になりました。
446 :
NAME 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 の結果を集計をしました (スレ用に可読性を考慮して、わざと全角で記入してます)
>>446 突っ込みどころはいろいろあるけど、
SELECT *
FROM A
LEFT OUTER JOIN B
USING(列1)
WHERE A.列1 = 100
これで出てきた結果セット全てのsum()がとられていると言えば、
なぜおかしい結果になってるかを理解する一番早い方法かと。
基本的に、一意じゃない列同士をjoinすべきではない。
本当にm×nの総当りな結果セットが欲しいときくらい。
こんなん書くの恥ずかしいんですが。。。どなたかお力を。 普段マイナー言語で開発やってて、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しか結果に表示されなくて困ってます。 どなたかお手すきの方ご教授願えれば幸いです。
>>448 先頭レコードの定義は?
ORDER BY 項目3,項目4
の先頭でいいのかな?
450 :
NAME 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#' もしお判りになる方がいらっしゃいましたらご教授願えませんか?
451 :
448 :2007/07/06(金) 12:41:48 ID:???
>>449 失礼しました。
項目1と項目2が主キーです。
なので項目3と項目4の内容は問いません。
>>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」に書き換えるべし。
>>448 PostgreSQL限定(だと思う)でよければ、
SELECT DISTINCT ON (項目1, 項目2) 項目1,項目2,項目3,項目4 FROM テーブル ORDER BY 項目1,項目2,項目3,項目4
とかも使える
>>450 試してないけど、それでto_timestampでTIMESTAMP型にするなら
to_timestamp(YMD || ' ' || HMS ,'YYYYMMDD HH24MMSS')
じゃない?
455 :
454 :2007/07/06(金) 14:21:52 ID:???
ごめん、こうだな。 to_timestamp(YMD || ' ' || HMS ,'YYYYMMDD HH24MISS')
456 :
NAME IS NULL :2007/07/06(金) 14:44:14 ID:KwXXH4Ws
>>455 理想通りの動作が来ました
単純に+じゃなく || 、日付の指定形式を間違えていたんですね・・・・
ありがとうございました!
457 :
448 :2007/07/06(金) 16:29:39 ID:???
いまさらですがDB2です。すいません。 FETCHとか使うって事ですかね? アドバイス参考にやってみます。 ありがとうございます。
>>457 まぁ、カーソルへのfetchを扱えるというのなら、
それが一番スマートで確実なやり方だろうな。
>sql使う機会があまり無い
と言うから、できるだけ簡単な方法を提示してみたのだが。
ちなみにfetchは、ストアドでやるって意味だよな?
クライアントサイドから全件fetchやろうとしてるなら、
いずれパフォーマンスで泣きを見るぞ。
別解として、更新時の処理をいじる余地があるのならば、
項目1と項目2が複合主キーな別テーブルを用意して、
トリガで1件目のときだけそっちにinsertするという方法もある。
459 :
NAME 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 | +-------+------+------------+ なのですが、どうしたらこのような結果を取得できますか? すいませんがご指導よろしくお願いします。
>> 459
問題の性質は、
>>448 とほとんど同じだな。
解決法も似たようなものになる。
>>459 例に出してるデータに
| 1 | d | 2 |
というレコードが加わったらどう出したいんだ?
話はそれからだ。
462 :
459 :2007/07/06(金) 21:00:15 ID:EkGmqGMy
レスありがとうございます。
>>460 order by をかけて一番大きい値順に出すと言う事でしょうか?
>>461 bでもdでも良いので1レコードだけ出てほしいです。
maxとgroupを使えば最大値の含まれる行が出ると思っていたのですがそうではなかったんですね。
>>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なり付けるべし。
スレが伸びてると思ったら… われなべにとじぶたの品評会ですか?
465 :
456 :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
とする事で解決しました。
本当にどうもありがとうございます。
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
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で書けるかどうかはシラネ。
こんな感じの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
>>467 見たことのないコマンドがいきなり…
オラクルでしょうか? 似たようなのがSQLサーバやMSアクセスでないかどうか調べてみます。
ありがとうございました。
月曜日に早速試してみます。
見たことないコマンドって... おいおい... 同僚のためにクエリ書くのもいいけど、もう少し本とかマニュアルとか 読んだほうがいいと思うよ。
>>468 WITH RECURSIVE とか使うんだろうな。
でも俺は書いたことないから回答は書けない。
472 :
468 :2007/07/08(日) 11:36:50 ID:???
>>471 ご教示ありがとうございます。
WITH RECURSIVEをキーワードにググったところ、ヒントになりそうな情報
が見つかりました。
ちなみに、使用データベースは、postgresqlです。
おお、俺もはじめて知ったよ WITH 句
サンクス ⇒
>>471
PostgreSQLはRECURSIVEをまだサポートしてないだろ。 標準では入らないけど、用意されているconnectbyだったかを 加えればそれでできる。
475 :
468 :2007/07/08(日) 18:28:32 ID:???
>>474 再帰問い合わせは8.2でもできないとのことですが、CREATE FUNCITONを使って
同様のことができることを見つけたのですが、connectby(contrib/tablefunc
モジュール)の方法もわかりました。ご教示ありがとうございます。
476 :
NAME 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条件で指定できない状態です。
>>476 select * from table_name where cast('2007-07-09' as date)
between StartDay and EndDay order by ID limit 1
478 :
NAME 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,
を抽出できるということです。
そんな条件、
>>476 のどこにも見えないが・・・
GROUP BY IDと、MAX(date) でこの2つが出ると思うが、
それを元にSELECTしては。同じ値があったときどうするかとか
書いて無いので、このくらいしか書けないけど。
PostgreSQL依存だが SELECT DISTINCT ON (ID) * FROM Table ORDER BY ID,EndDay DESC ;
481 :
NAME 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 のデータは出力されるようになりました。
全然理由がわかりませんが、なぜなんでしょうか?
482 :
NAME 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');
>>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の組合せで一意になるという前提だが。
>>482 まず
SELECT
dt,
DAY(dt)
AS d
FROM TEST
GROUP BY d;
だけを実行してみなよ。
その結果にhavingの条件が適用されることを考えれば、
なぜそうなるのかわかるはず。
485 :
NAME IS NULL :2007/07/09(月) 18:53:50 ID:WLR34h5u
>>479 ,
>>480 ,
>>483 レス遅くなってすみません。
あれから夢中になっていろいろ試してみてました
どうも
>>483 さんの方法でできそうな気がします。
ちょっとこれから試してみようかと。
下手糞な質問の仕方でご迷惑をおかけしました。
>>484 ありがとうございます。
そうか、日だけでGROUP BYしてたから、6月と7月で同じ日の
データがグループ化されてしまっていたんですね。
ありがとうございました。
>>486 そもそもGROUP BYの使い方を間違ってるような。
単にWHERE句で日付範囲を指定すればいいだけでは?
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文より速度が出る書き方はありませんでしょうか。
>>488 新しいという意味が最大値ということでいいのなら、
select
type,value,max(time) as mt
from test
group by type
order by mt desc;
>>489 スマンvalueが、、、
select * from test where time in
(select max(time) from test group by type)
でとりあえずとれるけど、あんまり速くないか、、
>>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;
>>489 さん
ありがとうございます。実環境で計測したところ3倍程高速になりましたヽ( ´¬`)ノ
もし、typeとtimeを複合インデックスにしてなかったら alter table test add index(type, time); analyze table test; した後の計測結果を教えてほすぃ もちろん無理だったらいいです
スレ違いかもしれんが、SQL実装時の効率のためにということで質問させて ください。というか、この手のスレが閑散としているので。 [Company] - ID - Name - Address のような表があったとして、その会社の役割を表すのに、 - CustomerFlag - VendorFlag のような属性を[Company]に追加するか? [Customer] -CompanyID (FK) [Vendor] -CompanyID (FK) のようにラッパー表を作るか? のどちらがいいでしょうか? 簡単な問い合わせは前者の方が楽ですが、例えば、Customer固有の属性を追加 するときなどは後者の方がきれいにできるかと思います。 ご教示いただければ、ありがたく思います。よろしくお願いします。
>>494 固有属性がたくさんあるなら後者だろうが、
最終的にはパフォーマンスと相談じゃないか?
>>494 自分で答え書いてる気が...
> 簡単な問い合わせは前者
> Customer固有の属性を追加するときなどは後者
どっちのケースがどれぐらいあるかは君にしかわからないよ。
497 :
NAME 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.論文番号
>>497 本当にちゃんと回答してもらいたいなら、使用してるDBMS書こうぜ・・・
見た感じ、Accessだろうと推測できるが、その前提ならば、
Accessのjoin句はややクセがあって、他のDBMSのように
複数の結合対象テーブルを並列に記述できない。
サブクエリでネストする感じで書くしかない。
SQLというよりはAccessの方言の問題だから、Accessを使って
3つ以上のテーブルをjoinしてるSQLのサンプルを探してみな。
499 :
497 :2007/07/11(水) 17:16:59 ID:tW1Thc0z
すみません.お察しの通りDBはAccessです. ちょっと調べてみます.
select A,B from hogeTable where ・・・ って文をSQLExecDirectで実行した結果取得できた行数を、 取得するVCの関数or方法ってありませんか? SQLRowCount関数を試したところ、 全結果セットをSQLFetchした後にしか正しい値が帰ってきません。 whereのあとに続く条件が多いため select count(A) from hogeTable where ・・・ という同じようなSQL文を2回も発行したくないんですよね。 ちなみに何がしたいかっていうと、実行したSQLで取れるレコード数の 領域を確保して、結果セットを全てメモリに入れたいのです。
>>500 たぶんSQLRowCountの仕様じゃないかな。
その要求を聞くに、ADOで言うところのGetRows()が最も適切なんだろうけど、
これに相当するODBC APIが何なのか、あるいはあるのかはわからん。
あと、レコード数わからなくても、メモリを動的に確保する方法はあると思うが。
C++なら、STLのコンテナクラス使ってレコードなくなるまでpushとか。
Cだったら・・・自作listとかでガンガれ。
SQL SERVERを使用しているのですが、 数値データを取得する時に書式を指定するには どうすれば良いのでしょうか?
>>502 3桁ごとのコンマの付与なら、money型をconvert(case)するときに
styleに1を指定することでできるっぽいが、
アプリケーション側で変換した方がいいと思うけどなあ。
>>503 なるほど、ありがとう!
試してみます。
2005で.NET使ってるならアプリ側でやるよりCLR関数作ったほうがいいんじゃね? 2〜3パターンならめんどうだけどT-SQL関数でも作れない事はないし 実際そうしてる
506 :
506 :2007/07/12(木) 23:48:01 ID:???
>>505 俺がアプリ側の方が好ましいと言ったのは、
例えば「カンマ編集するかどうかを出力オプションで設定できる」みたいな
要求が出てきたときに、柔軟に対応できる余地を残したいからだったんだけどね。
まーその辺のバランス加減は質問者に委ねるよ。
507 :
503 :2007/07/12(木) 23:49:59 ID:???
sqlについて質問です。 selectの結果セットに固定のデータを潜りこませたい場合 ( select "aaa", "bbb" ) union ( select f1, f2 from t1 ) こんな感じで考えて実際に動作はしているようですが もう少しスマートな書き方はありますでしょうか。 環境はmysql5を使用しております。
>>508 そんなスマートじゃない要求にスマートに応える方法などないと思うが。
蛇足ながらUNIONよりはUNION ALLのほうが多少速いかもね。
>selectの結果セットに固定のデータを潜りこませたい場合 この時点ですでに泥臭いとオモ
やはり無いですか マスタテーブルを作って、そこに固定データを置いてjoinするのが正しいとは思うんですけどね
それこそ泥臭い
513 :
492 :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
514 :
NAME 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つだけレコードを抜き出してくる方法がわからない。
>>514 select min(id), type
from table1
group by type
month, id, scoreの3つのカラムがあるテーブルがあります。 month毎にscoreが最大になる行をselectしたいのですが、 いい方法はないですか。idがいらなければgroup byとmaxで いけるんですが、それだとidがわからなくなっちゃうの ですよね。monthとmax(score)でもういちど探すのもなんか 馬鹿みたいだし...
>>517 同一monthで最大scoreのidが複数存在するときの扱いは?
postgresに関する質問です。 connectbyで階層問い合わせを実行すると、階層がカンマ区切りで表示されます。 ------------ 親キー ans ------------ 1 1,2,3,4 これを次のようにカンマ区切りで複数行に分割するにはどうすればいいですか? ------------ 親キー ans ------------ 1 1 1 2 1 3 1 4
>>518 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
>>521 副問い合わせで見かけ上はひとつのselectになってるとはいえ、結局のところ
monthとmax(score)でもう一度ひきなおすしかないんですね。SQLっていまいち
だなぁ... それとも超高度なオプティマイザが全部解析してmaxもとめたときの
行をおぼえて内部的には余計なqueryはせずに返してたりするんだろうか?
>>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回にはならなかった。
>>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も同じレコードがあったら両方出ちゃうけどね。
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に分解するつもりですが ループのところはどのような記述をすればいいのでしょうか?
>>525 その質問内容では、どこでつまづいているのか理解できる人は少ないと思う。
ファンクションからファンクションを呼ぶ方法がわからんのか、
終了条件の分岐のロジックがわからないのか、そもそも再帰の概念自体わからないのか。
528 :
NAME 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を使用しています。
>>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;
530 :
NAME IS NULL :2007/07/20(金) 15:19:55 ID:5xOFcdu1
>>529 そのツンデレぶりにはたいへん驚かされましたが…
なるほど!
FROM のテーブルをサブクエリで一意に取ってきたデータに置き換えるんですね
で、名前はそのキーから取得すると・・・
目から鱗です!
ありがとうございました
531 :
NAME 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を変換しようとしています よろしくお願いします。
どういう環境かよくわからんが、 クライアントの文字コードにあわせて、set client_encoding TO 'UTF-8'; とかやってみそ つーか、PostgreSQLのスレで聞いたほうがいいと思うぞ
以下のような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
>>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は要らないけどな。
535 :
533 :2007/07/21(土) 04:43:46 ID:???
>>534 おお、ありがとうございます!
たしかに期待通りの結果になりました。結構びっくりです。
ところで、解釈上やや複雑そうに見えるのですが、
この方法はDB内部でうまく最適化されてくれるのでしょうか?
カテゴリごとに分けてSELECTを呼ぶ場合より時間がかかったりしなければ問題はないのですが。
(カテゴリの数は10程度として)
何にせよありがとうございます。COUNTを使うというのは、目から鱗です。
536 :
525 :2007/07/21(土) 19:57:22 ID:???
事故解決しますた
文法ミスでした
>>526 すんません、切羽詰ってて説明不足でした
PL/SQLの文法解説してるサイトってあまりないですね
Oracleのマニュアルが凄い充実してることに驚いたのですが
初級者には全体的に理解し難い感じです
これを読みやすくしたような書籍無いでしょうか?
使用例も多いと助かります
>>527 再帰は知ってたけど、文法がわからんかったのです
なんかDB2で仕事しているとOracleの書籍の多さには羨ましい限りなのだが・・・。 しかし回答者はエスパーじゃないんだからテメエで本屋逝って探せよ。
538 :
sage :2007/07/22(日) 21:13:07 ID:FhbbgWhN
SQLでプログラム言語でいうところのif文の命令あるの? 例えば、もしAというカラムの値が1なら0を出力する。 もしAというカラムの値が2なら1を出力する。。みたいな
541 :
NAME 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
select 氏名, 科目, case 科目 when '化学' then 化学 else null end as 化学, case 科目 when '生物' then 生物 else null end as 生物 from 表 order by 氏名; typo あったらすまん。
543 :
538 :2007/07/22(日) 23:18:33 ID:FhbbgWhN
>>542 group by しないと無理じゃね?
取扱商品 品番 品名 売価 ---- 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 ↑のテーブルから商演算を用いて、全種類の商品を売った店舗番号を抽出したいのですが 旨くいきません・・・・どなたかご教授お願いします。 代数演算は分かりづらい。。
select 店舗番号 from (select 店舗番号, 品番 group by 店舗番号, 品番) group by 店舗番号 having count(店舗番号) = (select count(*) from 取扱商品)
俺の場合商演算はNOT EXISTSのネストでやってるなぁ。 select distinct 店舗番号 from 売上 AS 売上A where not exists( select * from 取扱商品 where not exists (select * from 売上 where 店舗番号=売上A.店舗番号 AND 品番=取扱商品.品番) )
>>546 ,547
ありがとうございます。
教科書もNOT EXISTS を使ってるみたいなんですけど
どうも分かりづらいです。。。
何か作り方の手順があればやりやすいのに・・
549 :
541 :2007/07/23(月) 12:06:02 ID:RqjUNL36
>>542 さん
>>544 さん遅くなりまして申し訳ございません
CASE〜でできました。ありがとうございました。
550 :
533 :2007/07/24(火) 04:58:39 ID:???
>>534-535 について続報。
速度テストしてみましたが、
レコード1万ぐらい入れて、カテゴリあたりのレコードが十分多い状況だと、
実行に10秒程度かかるようです。(MySQL5.0 ノートPC)
一応インデックスはちゃんと張ってるつもり。
多分内部処理でレコードごとにループしちゃってる?
#もし同じ事を行う高速な手法(外部でループする以外)があれば教えてください・・・
いずれにしても参考になりました。ありがとうございましたm(_ _)m
>>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
とか。
脳内で書き方変えただけで、テストしてないけど。
row_number partition が使える処理系なら効率よく処理できるのだが、 そうじゃない処理系でデータ数が多いなら、シーケンシャルに全件順に読んで ユーザープログラムで読み飛ばしたほうが速いケースもある。
553 :
533 :2007/07/24(火) 15:31:17 ID:???
>>551 ありがとうございます。
例の1万件でテストしてみますと、ほぼ
>>534 と同等の結果でした。
MySQLの内部処理的には似た感じなのかも。
>>552 この処理を1回で高速に処理するにはMySQLの機能不足という感じでしょうか。
DBにはできるだけ負荷をかけたくない処理ですので、
今のところ カテゴリ抽出→カテゴリごとにORDER BY&LIMIT とかでなんとかしようと思っています。
>>553 念のため確認だが、
>一応インデックスはちゃんと張ってるつもり。
とのことだけど、(category, tm)の複合インデックスだよね?
このインデックスがあれば、1万レコードでも10秒てのは
遅すぎるような気がするのだが。
ちなみにDBMSによっては、(category, tm, id)でさらにselectが速くなる場合もあるけど
ほとんどの場合は大差ないかな。
555 :
533 :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件です。
>>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
557 :
533 :2007/07/24(火) 18:35:33 ID:???
>>556 なんかすごいのきた^^;
後で読み解いてみます。
ありがとうございますm(_ _)m
558 :
NAME 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を使った方法でやりたいのですが分からなかったので申し訳ありませんがご教授お願いいたします。
559 :
558 :2007/07/25(水) 22:37:51 ID:oJzPaskR
SQL言語はOracleです。
>>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関数。
561 :
558 :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
>>561 推測したとおりで大丈夫だったってことかな。
なら、
>>560 でいけると思うんだが。
unionを絶対に使わないといけないわけじゃないんでしょ?
563 :
558 :2007/07/25(水) 23:36:24 ID:oJzPaskR
>>562 多分大丈夫だと思います。明日さっそく試してみます。
それと申し訳ないのですがunionを使った方法も教えていただけないでしょうか?
>>563 出したい結果を考えると、unionを使う意味、というか使う余地はないのだが。
2006年と2007年を縦に並べるなら使うこともできるだろうけど。
横に並べたいのなら、サブクエリやファンクションで実現するのが一般的。
565 :
558 :2007/07/26(木) 07:12:29 ID:sS8BKlCY
>>564 上司に昨日尋ねたらunionで出来るという事なので参考までに聞いたのですが横だと意味がないんですね。
勉強になります。
教えていただき助かりました。ありがとうございました。
566 :
NAME IS NULL :2007/07/26(木) 12:15:13 ID:XmvrlBD0
テーブルAの項目をテーブルBの項目でUpdateしたいのですがどうすればいいのでしょうか。 AとBはジョインできますが両テーブル共に複数レコード存在します。
568 :
566 :2007/07/26(木) 14:34:42 ID:???
>>567 できました。
ありがとうございました。
項目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は同テーブルでサブクエリーを使用し出力しています。 申し訳ありませんがどなたが力をお貸しください。
>>569 元のクエリも書いた方がレスが付きやすそうだが
手元に元のクエリが無いので記憶的で簡単なものになりますが 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 大方このようなクエリだったと思います。
>>571 テーブル2と3が、joinしてるのに結果に使われていないのは謎。
まぁ、「キーが存在することが条件」てのならわかるけど。
でrollupについてだが、それをどう直せばいい、というよりは、まず
[項目No1 項目No2 金額1 金額2]
の結果を出力するクエリを作ってみることをお勧めする。
つまり、項目名1,項目名2を考えずにってことな。
なんかrollupがごちゃごちゃしてるのがまずいと思うんだ。
これがうまくいってから、項目名1,項目名2をもってくることを考えようぜ。
>>572 さっそくありがとうございます。
実際は項目1と項目2の部分に該当した名前が入るんですけど分かりやすいようにコードとして表記させていただきました。
>>571 それじゃあfrom句の中の一個目のselectでの「金額1」と
二個目のselectでの「金額2」が同じじゃん。
>>569 の結果を出したいときのテーブル1のデータ内容はどんなん?
>>574 Where句の条件が足りなかったですね。
上のWhere句に
a.toshi = 2006
下のWhere句に
a.toshi = 2007
という感じです。
金額1には前年度、金額2には今年度という感じです。
テーブル1としては
項目No 項目2No 年 金額
必要なフィールドだけを取り出すと上記の形になります。
>>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
577 :
NAME 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をどのように書いたらいいでしょうか? お願いします
578 :
NAME IS NULL :2007/07/27(金) 18:00:40 ID:SeTyNiJf
あ、MAXもってくればいいのか。
ハヤ!
580 :
NAME IS NULL :2007/07/28(土) 09:22:39 ID:eFtPhvG6
MySQLを利用しています。gidごとに値を積算して積算順にソートを 掛けたいのですが、下記だとgidごとにソートかかかってしまいます。 descと組み合わせるとエラーになるし、どうすればいいんでしょう。 select sum(data),gid from user_tp group by gid;
>>580 select sum(data),gid from user_tp group by gid order by sum(data) desc;
>>581 アドバイスありがとうございます。
ただ、上記実行してみましたが
ERROR 1111 (HY000): Invalid use of group function
となってしまいます。もしかして、MySQLのバージョンが古い!?(T.T)
ちなみにバージョンは、4.1.20です。
>>581 解決しました!
select sum(data) as sum,gid from user_tp group by gid order by sum desc;
で関数値にエイリアスを切ったら解決でした!
本当にありがとうございました。助かりました。感謝です!
585 :
NAME IS NULLPO :2007/07/28(土) 17:38:07 ID:crv3ux+p
オラクルを利用しています。質問があります。 以下の通り実行する場合にテーブルをロック、アンロックする方法を教えて下さい。 1.テーブルAをロック 2.テーブルBを更新(UPDATE) 3.テーブルAにSELECT文を実施 4.テーブルAのロックを解除。
>>585 テーブルロックは LOCK TABLE 文。
アンロックは COMMIT または ROLLBACK。
しかしテーブル全体をロックしなければならないっていう設計はちょっとどうかと。
せめて 1. の代わりに SELECT 〜 FOR UPDATE ぐらいにしたほうがマシかも。
まあ詳しい要件が分からんので何とも言えんけど。
SP実行開始時には、更新を行うテーブルは必ずテーブルロックを行う事。 という共通規約が存在する漏れのプロジェクト・・・
>>587 かかわりたくない池沼なプロジェクトだな。
あまり優秀じゃないプログラマを何人も使うようなプロジェクトじゃよくあること。
それはあまり優秀どころか、ロックの存在をしらなくて、バッチ処理しか経験のない 元COBOLerの素人集団では・・・。
>>587 のところがそうなのかは知らないが、デッドロックを防ぐために
トランザクションの最初に特定の順序でテーブルロックするのは
普通だろ。
>>591 「必ずテーブルロックを行う事」っていう前提があればそうするかもしれないけど
その前提がそもそもバッチ志向から抜け出せていないっていう話では?
>>592 なぜここでバッチが出てくるのかわからないが、テーブルロックでなければならない
理由は、単にリソースのロック獲得順を明示的に制御できるのがテーブル単位だからだろ。
>>593 Oracleとかなら行単位でもロックできるけどね。
てかスレ違いだな。
ここで言ってるストアドプロシージャが、全件カーソルをまわして 1件ずつ更新して行くようなバッチ処理を想定してるのだろうな。 こういう処理が頻発するようならシステムの基本設計に問題があるとしかいえないな。
あー、なんか根本的に理解されていないみたいだけど、そういう理屈を全員に 教え込むのは大変だから、「更新するテーブルは最初にこの順番でロックすること。 これが決まりだ。」ってなるわけよ。
>>596 いや、それは分かるよ。
でも、そんなルールを作らなければならないようなプロジェクトには
できれば関わりたくないよね、と。
あ、
>>596 は
>>594 宛ね。
この場合、明示的行ロックの機能があるかどうかってのは関係ないわけなんで、
そういうセリフが出てくるということは、まさにそういうプロジェクトで想定している
人材なのではないかと。
>>598 えと、俺は
>>592 =
>>594 =
>>597 なんだけど、
このスレにも「そういう人」がいることが分かって、
かと言ってこのスレ違いな議論をこれ以上続けるのもどうかと思って、
やや強引に議論を終わらせようとしただけなんだ。
MySQL4.1を利用しています。教えてください。 ある問題の過去問で Q: 月間の残業時間が75時間以上の社員の社員コードと氏名を求めるSQLを実行したところ、 エラーで返された。 なぜエラーになったのか、20文字以内で記せ。 入力SQL文: select 社員コード,氏名 from 社員テーブル where 社員コード = (select 社員コード from 勤務実績テーブル group by 社員コード having sum(残業時間) >=75); なお、社員テーブルには 社員コード,氏名,課コード 勤務実績テーブルには 社員コード,年月日,所定労働時間,残業時間であり 各社員の1日ごとの所定労働時間,残業時間が1レコードとして1か月分入っている。 課テーブルには 課コード,課名 が入っている。 *** このとき、正しいSQL文はどうなるのでしょうか? お願いします。
>>600 = を in に変えればとりあえず動くには動くだろうな。
>>600 =をINにする。理由くらい自分で調べろ。
すいません。 顧客情報管理のDBを作成していて、 文字列の結合でつまってしまいました。。 Name Hobby -------------------- aaaa 読書 aaaa 映画 bbbb 水泳 -------------------- 上記のようなDBが有った場合に、 Name Hobby -------------------- aaaa 読書、映画 bbbb 水泳 -------------------- と、表示させるSQLを教えてください。 異なるレコードの文字列結合が、うまく出来ない・・・
>>603 普通にName別にHobbyの内容を取得した後、
アプリケーション側で処理した方が楽だと思われ。
つ〜か、Nameが同一のレコードが1億件存在したら、
それだけ繋ぐ、って事だろ?正気の沙汰じゃないwww
俺なら
aaaa 読書
bbbb 水泳
が既存データとして存在していて、
そこに
aaaa 映画
を追加する必要が生じたら、
aaaa 読書、映画
となるように最初からデータ操作するが。
>>604 おっしゃる事は、ごもっともなのですが、
どうやら仕様上そういう風にSQLを練らないといけないようで。。。
(HOBBYを個々に扱う場所も有るから、まとめて登録も不可のようです)
CONCATをうまく使って、レコード間の結合なんて出来ないかしら?と、思って
調べているのですが、自分の技術力ではサッパリです。
ご回答、ありがとうございます。
group_concat(Hobby separator '、')
607 :
606 :2007/07/30(月) 13:13:46 ID:???
ゴメン、MySQLスレと勘違いしてた group_concatとRDBMS名でググればヒントあるかも
>>606 調べてみました。
残念ながら、当方、postgresなので使えない様子。
DBの種類は最初に書くべきでした。
申し訳ないです。
ひきつづき、調べます。
ヒント、ありがとうございます。
PostgreSQLでは複数行の文字列連結はなかったはず。 PL/pgSQLなどで関数自作するしかないな。
610 :
NAME 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回目をもっと簡潔に書く方法は
やっぱりないんでしょうか?
>>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;
あ、うそ。T1.ITVってないな。 ゴメソ。
>>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 ... )
>>610 システム内でその演算の出現頻度が高いなら、ファンクション化。
615 :
NAME IS NULL :2007/07/31(火) 12:22:42 ID:JPI88QGA
SQL文に現在時刻を使う場合、 アプリ側かSQL側(CURRENT_DATEなど)、どちらで取るほうがよいでしょうか? ちなみに私の環境は、アプリ側はPHP5、MYSQL5で、 WEB、DBとサーバーが別です。 私の環境において、一般的に、どちらでも構いません。 理由をつけてご回答頂けると幸いです。 よろしくお願いします。
>>615 おれはサーバー側で取るようにしてる。理由は、クライアントの時間が信用できないから。
ま、Web サーバーがひとつだけなら大丈夫なんだろうけど。
>>615 何を重視するかによるかな。
DBに対してアクセスするクライアントが複数ある場合は、
DBの時刻関数を使うことで一貫性が保てる。
逆にアプリで時刻を取得した方がいいケースとしては、
複数のクエリを発行するときにその中で現在時刻が要求され、
それぞれが同じである必要がある場合など。
動的に時刻を取得すると、毎回違う時刻になっちゃうからな。
Oracle10gです。 カーソル定義の際に 複数テーブル(5つ位)をJOINで結合させたカーソルに対 して "FOR UPDATE" 句を使用し、カーソル内で CURRENT行 に対する UPDATEを 行いたいんですが。 UPDATE出来るテーブル、出来ないテーブルの違いは何でしょうか。 例えばこれが2つのテーブルA・Bで、結合結果がA:1対B:多となるような場合に テーブルAに対して CURRENT OF cur でUPDATE出来ないのは分かるんですが。 単純に「UPDATEしたら複数行が更新されそう」なTBLはUPDATE不可、と考えて 大丈夫でしょうか?
619 :
615 :2007/07/31(火) 17:18:25 ID:???
>>616 ,617
ありがとうございます。
環境により使い分けるってことですね。ごもっともです。
私の場合、特にMYSQLのNOW()や型のTIMESTAMPなどは便利なので、
何とかSQL側で使ってやりたいというのが本音ですが、
逆にログに出したときに分かりにくい、保守性も少し下がるというのが
懸念点です。
>逆にログに出したときに分かりにくい、保守性も少し下がるというのが kwsk
621 :
615 :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はほとんど基本だけ押さえてそれ以上は勉強しない人が多いようですし。
ちょっと断定するほどの理由にはなりませんね、申し訳ないです。
622 :
NAME 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行が更新されないのは仕方ありませんが、他の行まで更新されないので困っています。 なにか良い方法は無いでしょうか?
> UPDATE テーブル名 SET result = lhs / rhs; where rhs <> 0 でいいやん
624 :
NAME IS NULL :2007/07/31(火) 20:19:56 ID:NYEBxcjn
access2000のMDBファイルにCreate文を投げて10進型のカラムを10桁&小数点3で作成したいのですが decimal という型はないようなのです numericだとどうもDoubleになっているようだし・・・ すみませんがご存知の方お教え願えませんか?
>>624 10進型なら、Currency になるはず。桁数の指定はできないよ。
627 :
624 :2007/07/31(火) 20:48:47 ID:NYEBxcjn
>>625 レスありがとうございます。
やってみたんですが、どうも通貨型になっているようです。
説明の方法が悪かったような気がするのですが
10進型というのはACCESSのデザインでいうところの
数値型のカラムでフィールドサイズが10進型ということなのです・・・
説明悪くてごめんなさい
すいません。 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がユニークであるため コピーして更新が出来ません・・・。 どうしたら良いのでしょうか?
>>628 dateがDATE型かどうかわかんらが、こういうことかな?
INSERT INTO Table SELECT date+ interval'1 day' FROM Table WHERE date=(SELECT max(date) FROM Table);
628です。ごめんなさい。書いた後にすぐ落ちてました(汗 ふーむ、やっぱり、1つのコマンドで足りるんですね。 ありがとうございました。参考にさせて頂きます。
631 :
NAME 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のカウントを求めたいだけなんですけど。 以上、宜しく御願いします。
delete from の後ろに消したいテーブル名入れて、その後ろに条件入れる あと、count(*) はgroup by itmcnt でどうか
こんな感じで。 delete AAAA where rowid in ( select rowid from ( select rowid from AAAA order by update_time desc ) where rownum <=3); 後者はcounr(*)以外に何かはいってませんか? グループ関数のみの場合はgroup by指定しないでもいけたとおもうんだけど。
634 :
NAME IS NULL :2007/08/06(月) 04:46:21 ID:HzzUCyP6
とりあえずMySQLです。 あるフィールドが「NULLではなく、かつ 1 以上」だったら〜 という条件式は、比較的色んなところで使いそうな気がするのですが、 これをさくっと記述する方法はありませんか? 素直にANDで2つ書くしかないでしょうか。
>>634 単純に column >= 1 だけでいいんじゃないの?
IS NOT NULLは書かなくてもNULLは弾かれるだろうし。
636 :
634 :2007/08/06(月) 05:21:22 ID:???
ごめん。超ごめん。寝ボケてた。 NULLもしくは0のフィールドです。全くもって逆です。吊ってきます。 (column >= 1)=0 とかでイケるかな?とか思ったけどダメだった。
>>636 MySQLでは無理かもしれんが、それに近いのに
(column >= 0) IS NOT TRUE
がある。さくっと記述できるかどうかはナニだが。
他には COALESCE(column,0) = 0 とか。
638 :
634 :2007/08/06(月) 06:12:07 ID:???
>635>637 2人ともこんな時間にありがとう。色々試してみることにします。そして寝る。
補足。 (column >= 0) IS NOT TRUE と COALESCE(column,0) = 0 両方とも インデックスが効かない可能性がある。その辺りはDBに依存するだろうけど、 現実的にはCOALESCEで関数インデックスかな。使えればの話だけど。
NULLをインデックスで引けるDBMSなんて存在するの?
>>640 あ、言われてみればそうだなw。
MS-SQL鯖なら引きそうな気もするが。
確かSQLServer ただ、UNIQUEでNULLは1レコードのみって理解に苦しむ仕様だったような。
643 :
NAME IS NULL :2007/08/06(月) 07:46:10 ID:zdKH8zBk
JOINってカッコで囲わなくても問題無いのは、もしかして常識? 今までずっと ((A JOIN B USING 〜) JOIN C USING 〜) JOIN D USING 〜 て書くのが当たり前だと思ってなんですが、ふと思って A JOIN B USING 〜 JOIN C USING 〜 JOIN D USING 〜 て書いてもなんらエラーにならなかったんで。これでいくつテーブルを 繋げてもそれなりに見やすいSQLになるかな
>>644 たぶんみんな知ってる。
でも、Accessだけは、ネストして書かないと通らない。
646 :
NAME IS NULL :2007/08/09(木) 22:44:24 ID:xEU1tKZW
minus これはなんて読むんでしょう?
647 :
NAME IS NULL :2007/08/09(木) 22:45:07 ID:xEU1tKZW
マイナス?
マイナス。
649 :
NAME IS NULL :2007/08/09(木) 22:53:00 ID:xEU1tKZW
>>648 マイナスで合ってます?UNIONは読めたのですが、
こちらは一瞬わからなかったです(^▽^;)
ありがとうございました。
650 :
NAME 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が早いでしょうか? アドバイスがありましたら、よろしくお願いいたします。
>>650 直感的にはNOT EXISTSだと思うけど
実データに近い形で実行計画とってみないと何とも。
652 :
NAME 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の知識があまりないもので、、
質問ばかりになってしまいましたが、お力をお貸し下さい。。
653 :
NAME IS NULL :2007/08/09(木) 23:20:45 ID:xEU1tKZW
>>651 やはりNOT EXISTの方が若干はやいでしょうか?
それとも、そんなに変わらなければ、気にしなくても良いのかななんて(^▽^;)
>>653 数百〜数千レコードの規模のデータ量なら、どれも大して変わらなそう。
パフォーマンスを気にするのは、その上のオーダーからかな。
1か2で選ぶなら、俺なら2の方。
極限のパフォーマンスを目指すなら、
- 一時テーブルDを作成
- Cにインデックス付与
- A-CをDにinsert
- B-CをDにinsert
- Cのインデックス除去
- Dにインデックス付与
- DのdistinctをCにinsert
- Dをdrop
でもここまでやる必要があるのは、数百万件クラスのバッチ処理くらいかと。
655 :
NAME IS NULL :2007/08/10(金) 13:50:15 ID:nDGcrBFR
>>654 処理レコードは数千レコードあって1万レコード
ですので、それほど意識しなくてもよさげですね
アドバイスありがとうございました。
>>654 それ何回 full scan かかるんだぁ?
簡単に極限とか言っちゃダメだよ プラチナムより上のクラス(計測不能)の人がここ覗いてるんだからさ
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秒以内) 、なにかアドバイスをいただけませんか。
659 :
658 :2007/08/16(木) 03:34:26 ID:???
というかすいません、一分半で御の字のような気がしてきました。 それぞれの検索結果の取得でも何分もかかるわけですし。 むしろスケールアウトするような構成を考えなければならないような。 もう寝るべきですね。スレを汚してすいません。
>>658 書いた内容だと、やりたい事が完全に理解しきれない。
まず、search_queryは何に使うのか。
それと、LOAD DATAはエンドユーザからの検索に対して
毎度行われるのか、それともLOAD DATAがされた後に
そのデータが使いまわされて、それを高速にしたいのか。
後者の場合なら、search_result_1の内容をsearch_result_2に
存在するresultのものだけ残すようにすればレコード数は格段に減る。
メモリが潤沢なら、type=heapでのcreate tableも試してみたら?
>>660 すまん、ENGINE=MEMORYって書いてあるから、type=heapと
同じことは既に試してるんだね。この記述は無視して。
>>658-659 > 一分半で御の字のような気がしてきました。
> それぞれの検索結果の取得でも何分もかかるわけですし。
自分で答え書いてんじゃん。
それはともかく、検索エンジンからとってきた結果を一回しか使わないなら
そもそもDBに入れる意味が薄い。
DBに入れるオーバヘッドが余計にかかるだけ。
スケールアウトするって言ってもそのためのオーバヘッドもかかるし。
それよりはファイルに落としてsortしてcommしたほうが速いんじゃないの?
それか、ハッシュテーブル作るプログラムを自前で書くとか。
俺ならresult2のqid=1なresultでハッシュ作っておき、result1を 読みつつハッシュひいてあれば出力みたいにすると思う。result2は 8文字の文書IDが1万件までって条件だからハッシュはメモリに置いて 全く問題ない量だろ。これだけのことのためにDB使うのは無駄だな。
664 :
NAME 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文にしたらいいのか?
IDをどうやって生成するのかわからんけど INSERT INTO の VALUES 以降を SELECT文にできるよ
insert into Table(名前1, 名前2) select 名前1, 名前2 from Table where ID = 1
667 :
NAME IS NULL :2007/08/16(木) 15:50:36 ID:rMjnc/Rn
>>665-666 やってみたんだが、IDがプライマリキーなのかもしれないが、
キーが重複している…というようなエラーがでてしまった。
原因はわかる?
>>667 666でやるならIDはIndentity属性(自動採番)になってる必要がある。
insert into table select * from tabel where なんてやってたら重複するのは当然。
新規IDはmax+1でも何とかなるが実務で使うのはやめとけ。
>>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
>>664 の通りにやるなら
INSERT INTO table (ID,名前1, 名前2) SELECT 3, 名前1, 名前2 FROM table WHERE ID = 1
でいいけどなー
671 :
NAME IS NULL :2007/08/16(木) 16:25:02 ID:rMjnc/Rn
>>670 確かに。これだったらID「1」の情報がコピーされて
ID「3」として新規作成される。
でも、テーブルに今使えるIDがわからなかったとしたらどうだろうか?
MAX(ID)を試しに、SELECT文後のIDの所に入れてみたが
GROUP BY句…のようなエラーがでた。
>>671 単純にMAX(ID)と書けないから、結果的に
>>669 のような書き方にならざるを得ない。
答えが書いてあるのに、なぜ試さない?
673 :
NAME IS NULL :2007/08/16(木) 16:37:06 ID:rMjnc/Rn
674 :
NAME IS NULL :2007/08/16(木) 16:53:48 ID:rMjnc/Rn
>>673 です。
>>672 >>669 やってみた。確かにきれいにテーブルに反映される。
答えてくれてありがとう。
しかし、自分はまだまだSQL初心者。
聞きたいことがあるんだが、
A・Bとか、あれはなんだろうか?
解説が聞きたい。意味も知らずに使いたくはないので
ご教授願いたい。
>>674 それは別名(Alias)で直前の括弧の中のSELECT分の結果をAという名前のテーブルに見立て、
外側のSQLからその名前で参照する。
>ご教授願いたい。
普通に教えてくれとなぜ言わない。使い慣れない敬語使わんほうがいい。
そこかしこで見るから最近は 「か、漢だ…!」系ネタに見える <ご教授ください
677 :
NAME IS NULL :2007/08/16(木) 17:37:52 ID:rMjnc/Rn
>>675 教えてくれてありがとう。
なんとなくだがわかった。
また何かあったら頼む。
678 :
NAME IS NULL :2007/08/16(木) 18:42:37 ID:ANt5VVpQ
やり方があったら教えてください。 上位10件を取得するとき、Oracleだと WHERE ROWNUM <= 10 .... SQL Serverだと SELECT TOP 10 ... と書きますが、 Derbyだとどのように書けばいいのでしょうか。 調べた限りだとそのような物は準備されていないので、 そのやり方を教えてください。お願いします。
>>679 ありがとうございます。やっぱり無理そうですね。
素直にカーソルまわします。
DerbyはまだLIMIT OFFSET対応して無いのか・・
682 :
NAME 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が拒否リストであるようなイメージです。 検索キーワードだけでも結構ですので、よろしくお願いします
ぱっと思いつくのはこんなんかな。 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)
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 とかやってみましたが、スマートな感じがしません 何か良い方法はないでしょうか
685 :
684 :2007/08/17(金) 14:57:38 ID:???
書き忘れていました 対象は SQL Server 2000 Enterprise Edition (SP4) です 同じようなテーブルが100以上あり、それぞれ百万件単位のデータが日々入れ替わるので、できるだけ処理を軽くしたいです SQLの自体はどんなに長くても構わないので、処理の速さを求めています。。。
CASEよりCOALESCEの方がちょっぴり短くなる。 >スマートな感じがしません >処理の速さを求めています どっちを優先したいのよw
入力日、入力者、入力時刻、金額のフィールドーが有る仮定で、そのテーブル から 日々の合計金額 一日の中で最後に入力された時刻 その時刻に入力した入力者 を取得したいんですが、SQL1発で取得する良い方法はありませんか? サブクエリでmax(入力時刻)を求めた上で、その値に一致する行の入力者を求 める、という方法なら普通に分かるのですが、折角のOracle10gなんで partition by?last?みたいな関数を使えばもしかするとすっきり書いたり 出来るんでしょうか?
>>686 情報ありがとございます、BOL見てみます
> どっちを優先したいのよw
自分で書いたのが無駄に長く遅いような感じがして、スマートじゃないと表現してしまいました
目的はあくまでも処理の速さです
>>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以上あり
ネタだと思うが、マジなら設計を見直した方がいいと思う。
>>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
691 :
NAME 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 になってしまいます。
693 :
691 :2007/08/17(金) 17:40:27 ID:???
>>692 どうもです。
111 の場合、日付のみで、時間が入らないようです。
>>693 じゃ、120でやってREPLACE()で。
695 :
691 :2007/08/17(金) 17:58:28 ID:???
>>694 出来ました!
ありがとう御座います。
うーん、しかし、グリッドへの表示に置換までする価値が
あるのか自分の中で悩む。
表記は統一したいけど、余計な負荷が掛からない様にしたい。。
(まあ、3000件程度では、体感で何も変わりは無かったですが。)
>>691-695 convert(char(10), 日時, 111) + ' ' + convert(char(8), 日時 , 8) とかは?
697 :
684 :2007/08/17(金) 22:28:51 ID:???
>>689 情報ありがとうございます
686さんの情報を元に同じクエリを作ったところでした
>ネタだと思うが、マジなら設計を見直した方がいいと思う
ネタではなく本当なのです。。。
世界中の拠点からデータを集約しているのですが、各国で求められる情報が違い、設計当時(SQL Server 6.5の頃)はハードやインフラも貧弱で、論理的な対応ではなく物理的な対応でこなした名残だそうです
今は SQL Server 2008 を目指したリプレースの計画をしていて、1つのテーブルと、複数の変換パッケージで収まるようにするらしいです
>>690 そんな書き方もあるんですね
今回はもうテストに回してしまいましたが、個人的にチェックしてみようと思います
情報ありがとうございました
MySQL4で SELECT COUNT(*) AS count したものを WHERE count > 5 のように指定できないのですが仕様ということでいいですか? 他に同じことをする方法はありませんか?
>>698 MySQLに限らず仕様。
SELECTリストでの別名をWHERE句やHAVING句では使えない。
そもそもそこは、HAVING句じゃね。
SELECT c1,count(*) AS count FROM Table GROUP BY c1 HAVING count(*)>5;
>>699 で、できましたーーーーー!
ありがとうございます。
未だにWHEREとHAVINGの違いがわかってないようです
テーブル名:Table 番号 年月 ----------------- 1 19230411 1 19990621 1 20071211 ★ 2 20011103 2 20060211 ★ 3 20070222 3 20070413 3 20070802 ★ となっているとき ★マークのついた、各番号の最新の年月だけ抽出するには どうすればよいでしょうか。よろしくお願いします><
>>701 過去スレをみればなんども出てくる質問だぞよ
さすがに初歩的すぎてレスつかないね。 select 番号, max(年月) from Table group by 番号
703じゃないけど、何が駄目なの?
706 :
704 :2007/08/20(月) 15:12:19 ID:???
は?なに言っているんだよ。
と、思いましたが、すみません。
再度
>>701 を読み返したら、自分が勘違いしていました。
>>703 であっています。
過去スレ、レスで何度も出てくるのは
カラムがそれより多いケースだよなw
>>701 のはあまりにも基本的過ぎる
ここは「宿題は自力でやれ」ってレスすべきだったんじゃないのか?
まあ、それじゃあんまりだから、「group by と max を調べてみな。」ぐらいでどうか。
710 :
NAME IS NULL :2007/08/21(火) 07:51:49 ID:hZSddUM6
カラムにHTML形式のデータ100行ぐらい分まるごと放り込むって バカな仕様でしょうか? カラムに放り込むデータが大きすぎるとパフォーマンスは落ちますか?
それが必要ならそうすればいいと思うよ
>>710 経験的には、そういうシステムは何度か見てきた。
ファイルで保持するケースとで、一長一短だよ。
それぞれで実装した場合を見比べて、これから作ろうとしてる
システムではどっちが後々困らないか検討すべし。
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でこういった事が実現できたらと思いまして…。
>>713 カラム名で指定する場合は、クォーテーションで囲む必要なし。
715 :
713 :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とか入れてキャストしてみようかと。
716 :
713 :2007/08/21(火) 21:20:05 ID:???
型キャストもどうにもダメで下記で解決しました
SELECT substr(日付,0,8) as date from テーブルA
SQLは色んな表現の仕方があっておもしろいです。
実行速度も計ってみたいんで引き続き
>>713 >>715 のような表現の正しい表記を教えて頂きたいです。
717 :
710 :2007/08/21(火) 22:18:56 ID:???
>>711 >>712 ありがとうございます。
HTML放り込みという使用もありなのですね。
ファイルで保持させようとも考えていたのですが
ページごとに必要でファイル数が5000を軽く超えてしまいそうなので・・
参考になりました。どうもありがとうございました。
718 :
714 :2007/08/21(火) 22:37:47 ID:???
>>715 あ、timestamp'...' が余計なんだよ。
SELECT EXTRACT(MONTH FROM 日付) AS date FROM TableA;
これでいけるはず。
719 :
714 :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型になっているのかと。
720 :
713 :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
お詫びに実行速度を…。
721 :
713 :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()を使うのが一番コスト的には悪いようでした。 ケアレスミスでごめんなさい、ありがとうございました
ADO経由でAccessのmdbをいじってます 顧客テーブル 顧客ID 顧客名 地域ID 地域テーブル 地域ID 地域名 購入テーブル 購入ID 顧客ID 購入額 払込テーブル 払込ID 顧客ID 払込額 こんなテーブル達があります (購入額計)-(払込額計)が0以上の顧客数を地域別に勘定したいときは、どのようにすればいいでしょう?
>>722 購入テーブルから 顧客ID, sum(購入額) を求める。
払込テーブルから 顧客ID, sum(払込額) を求める。
上記2つの結果と顧客テーブルを全て顧客IDでJOINし、
where句にsum(購入額)-sum(払込額)>=0をつけた上で
地域IDでグループ化してcount(*)する。
(地域名が必要なら地域テーブルもJOINする。)
ってのを、SQLで書けばいいんじゃね?
724 :
FOX :2007/08/22(水) 15:39:39 ID:h8h7Zigl
2つのテーブルで同じ連番のレコードを一括削除したいのですがうまくいきません。 どなたかご教授よろしくお願いします。
>>724 質問に対する質問しかレスされなそうな質問だな。
726 :
FOX :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テーブルしか削除できませんでした。
>>726 x: [Aテーブル][Bテーブル]
o: [Aテーブル], [Bテーブル]
というオチでは。
728 :
FOX :2007/08/22(水) 16:01:59 ID:h8h7Zigl
727さんありがとうございました。 ,入れてみましたが実行できませんでした。
どのRDBMS?バージョンも
730 :
FOX :2007/08/22(水) 16:20:57 ID:h8h7Zigl
RDBMSはSQL Serverになります。
DELETE文の一般的な構文は DELETE FROM テーブル名 [WHERE句] だと思うけど。 てかそもそもDELETE文で複数テーブルを対象にできるの? 外部キーでCASCADEにでもしてなきゃ無理じゃね? それかSQL Serverではできるとか? 知らんならレスするなって? はい、すみません。
一部のDBMSはできるみたい。 SQLServerは無理なんじゃかなー、知らんけど。 ビュー作ってトリガで消すかCASCADEにするのが自然か。
mysqlでは可能。 SQL Serverは、Books OnlineでDELETEのBNF見た限りでは サポートされてないようだ(2000しか見てないが)。
734 :
NAME IS NULL :2007/08/23(木) 09:57:44 ID:1Mq4cvM8
インデックスってWHERE句で指定する条件が単一でない場合に作成すると 高速効果が期待できますよね? WHERE句で指定する条件が単一の場合インデックス作成する意味はないですよね?
735 :
734 :2007/08/23(木) 10:45:37 ID:1Mq4cvM8
あぁなんか完全に勘違いしてますね。。 レコードが多く、更新度が低く、抽出結果・重複が少ない 場合に有効なのですね。 ユニークに設定してあると自動でインデックスされているんですよね?
>>735 ユニーク制約だけでは、本来はインデックスが作成されることは保証されない。
だが、内部的にユニークインデックスを作成してるDBMSはあると思う。
心配なら、使ってるDBMSのマニュアル読んでみれば書いてあるはず。
737 :
734 :2007/08/23(木) 11:36:25 ID:1Mq4cvM8
発言テーブル.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です。
ORDER BY AA.datetime, BB.datetime でいいのかな?
>>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
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 でいけるんじゃね?
ちょっと誤解を生みそうだ。突っ込まれる前に訂正。 ×BB.datetimeがAA.datetimeより古い場合は存在しない。 ○「BB.datetimeがAA.datetimeより古い」という状況は存在しない。
>>742 返信有難う御座いました!
そして、その記述で望む動作を得ることが出来ました。
成程、条件で見る値を切り替えるのですね…
本当に有難う御座いました。
>>738 の例が意味不明だと思ったが、そういう意味だったのか・・・
日のアクセス2万ほどなのですが、現在ファイルでアクセスカウントしています。 現在TOPページのみでカウントしています。 全てのページにおいてカウントさせたくてpostgreSQLで管理しようと思うのですけど やめておいた方がいいように言われました。(人伝いに) どういった理由が考えられますか? DBを使ってのアクセスカウントってあまり向いてないのでしょうか? ページ数は1000ページほどです。
WebPageの話か? Web鯖がapacheだとしたら、apacheのログを解析するだけで済むと思うのに、 なぜにRDBで管理なんてヘンテコな事考えるんだ? しかもたかが1000明細(ページ)の為に。 そんなのExcelやAccessで十分過ぎるだろ。
747 :
745 :2007/08/26(日) 12:55:20 ID:???
ありがとうございます、 そうです、Webです。 すいません抜けてました。 ページごとにアクセス表示させたいのです。
>>747 > アクセス表示
って何を指してるんやら?
とりあえず、ページ毎にアクセスログをDBに記録して、
1. ページ毎にアクセスカウンタを埋め込む?(普通の閲覧者がカウンタを見れる)。
2. アクセス解析用(管理人しか見ない)
のどっちか? まぁ、2の場合だったら悩むほどのもんでもないだろうけど、
1ならトリガで...って書きかけたけど、1は単なる管理人の自慰行為だよね。
まぁ、DBにアクセスログを入れておけば、SQLだけでいろんな解析ができるだろうから、
俺的にはありだが。
749 :
748 :2007/08/26(日) 13:56:31 ID:???
にょ、途中で送ってしまった。 俺的にはありだが、httpdのアクセスログから1日分をバッチ処理して DBに落としてからで十分だよね。
750 :
745 :2007/08/26(日) 15:54:15 ID:???
ありがとうございます。 1です。ページにアクセス数表示させるためです。 自慰行為でもなくて、そのページのアクセス数をリアルタイムで 知りたい人も尋ねてくるページなのです。 なのでそのページでその都度アクセス数を表示させておく必要がありまして。。 ファイルでカウントさせておくほうが良いでしょうか? DBでアクセスカウントさせるとなるとリソース食いますか?
どうしてもその機能が必要なら喪前の好きな方法でいいのでは? perlでもJavaでもいいからサ。 ただ「そのページのアクセス数をリアルタイムで 知りたい人も尋ねてくるページなのです。」 なんてのは意味ない行為って教えてやればいいと思うが。 リアルタイムのアクセスレポートの機能の為に 高性能の鯖を買ってくれるお客ならやればいいと思うんだが、 リソースとか気にするならヤめとけ、としか言いようが無い。
752 :
748 :2007/08/26(日) 17:48:54 ID:???
カウンタだけならログをとる必要もないし、 SELECT FOR UPDATE でロックして、 後にインクリメントさせるだけでいいのかな? いいんじゃね、やってみれば。 カウンタのためだけにDB使うってなら、躊躇してしまうところだが、 永続化やpgpoolなどを使えば、それほど気になるものでもないかも。 俺的には「そんなこと止めれ」とは言わない。 それはそうと、ちょっとスレ違いなネタなんだよな。
753 :
NAME IS NULL :2007/08/27(月) 20:39:46 ID:xlZ83oxI
PL/SQLの質問です ファンクションで 変数に2000文字以上の文字列を入れる処理があるのですが VARCHAR2型だと大きさが足りなかったので CLOBに変えたのですが エラーが発生します 変数の宣言のところで hoge clob; にしました CLOBは制限が多いとリファレンスに書いてましたが 適例が無く、読み解けませんでした 何か他の設定?が必要なのでしょうか?
CLOBはあんまり使わない方がいいよ 使わない方向で改修無理なの?
755 :
NAME 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を条件にいれた場合、 同じようなスピードになるのでしょうか?(何十万件単位) もしかしたらとんちんかんな質問かもしれませんが 宜しくお願いします。
1)検索条件がcol1, col2 両方の場合、上はindex1が使用され、下はindex1かindex2のどちらかが使用される。 2)検索条件がcol1だけの場合、上はindex1が使用され、下はindex1が使用される。 3)検索条件がcol2だけの場合、下はindex2が使用されるが、上は使用されない。 1のケースでは上の方が検索スピードが速くなる可能性が高い。 (col1だけで十分件数を絞りlこめている場合はその限りではない。)
>>755 基本的には
>>756 の言うとおりだが、DBMSによっては、col2だけの条件でも
DBMSによっては(col1, col2)のインデックスが使われる場合もある。
col1のカーディナリティが低い場合は、効果が期待できることがあるため
(col1が1種類の値しか取らない場合を考えるとわかりやすい)。
とはいえ、(col2)のインデックスより勝るということはないが。
>>757 OracleのCompress索引でしたっけ?
あれは第一キーのカーディナルがほんとに低いときしか効果が無いからなぁ。
759 :
757 :2007/08/28(火) 17:19:25 ID:???
>>758 そうそう、Oracleだったっけ。どれで実装されていたか確信がなかった。
補足してくれてありがとう。
760 :
755 :2007/08/28(火) 18:01:21 ID:naFGM+aI
756-759 皆様丁寧な説明ありがとうございます。 すごい勉強になりました!!
761 :
NAME 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の行追加の頻度は高くありません。(既存行の更新はなし。) テーブルロック以外にいい方法がありましたら、ご教授ください。 よろしくお願いします。
>>761 そもそもトランザクションはロックのおかげで一貫性を保っているようなもんだから、
ロックせずにできないかと言われてもな。
質問内容からは、トランザクションで何を実現したいのかも見えてこないし。
- エラー時にrollbackしたいのが目的?
- Bへの更新者が複数いるからその競合の回避が目的?
- commitするまで更新中のBのデータが参照されないようにするのが目的?
>>761 テーブルA,Bは同一キーで1:1の関連だからテーブルを分ける意味があまりない。
a1, a2, b1, a,3 ... でいいのでは?(もとろん分けてもいいが)
IDENTITY制約列(オートナンバー)がサポートされているなら
b1(PK)IDENTITYのテーブルを作りそこで生成される番号を使用する。
サポートされてないなら採番用のテーブルまたはレコードを準備する。
これについてはいくつか方法がある。
764 :
NAME IS NULL :2007/08/29(水) 15:33:10 ID:2iUsCkc+
765 :
NAME 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もできない場合がある。 そんときゃ、出来るまでループという手もあるけど。
766 :
NAME 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はないのですが・・・。
>>766 質問の要領が悪いな。思い込みが激しい上に複数のことをごちゃ混ぜに考えてるように思える。
要はシーケンスのように、特定のレコードに紐つかないID値が欲しいわけだ。
その方法はひとつではないのでいくつか分類してあげてみる。
以下、グループ化してbレコードにレコードを追加する処理を主処理。
新規IDを発行する発番処理と呼ぶことにする。
発番処理を主処理のトランザクションに含む。
主処理が済むまで次の発番および次の主処理はブロックしておくか
IDが競合するようなら失敗または(自動または手動で)再処理させる必要がある。
ブロックさせるのがお前さんが考えてる方法。
>>765 のやってるのは再実行の例で
ブロックの必要はないが他の主処理と競合したら再実行になる。
発番処理を主処理のトランザクションに含まない。
シーケンスを使う。
または、主処理のトランザクションの前に発番処理済ませておく。
または、主処理とは独立した接続で発番処理を行う。
同時実行性は高いが主処理がロールバックした場合に空き番号が発生する可能性がある。
IDENTITY制約をもつ発番テーブルを使う。
発番処理を主処理のトランザクションに含むことになるが
それぞれ別のレコードになるため競合はなくブロックする必要はない。
発行した番号はレコードとして残る。ただしID成後すぐにレコードを削除しても良い。
主処理がロールバックした場合はそのIDのレコードは残らない。
同時実行性は高いが主処理がロールバックした場合に空き番号が発生する可能性がある。
>>765 の意味は俺も分からん。
not exists (select * from テーブルB b where b.b1 = 入れようとしている番号)
なら分かるけど。
テーブル1と2があって 1はA、B、C、D、Eとカラムがあって 2はF,Gとカラムがあるんだけど 1は単独で利用する場合があって 2と1を結合して利用する場合もある。 それで 2と1結合して利用する場合に2パターンあって 完全に2と1のデータ利用する場合と 2と1のEカラムだけ利用する場合があるのね。 そういう場合データ重複するけどテーブル2にもEカラムのデータおいたほうがいいのかな?
>>769 参照時のパフォーマンス重視ならいいんじゃないかな。
更新と整合性管理のコストがかかるけど。
「インデックス付きビュー」、「マテリアライズド・ビュー」も参照されたし。
>768 765だけど、そういうこと
772 :
NAME 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したいのですがどのようにすればよいでしょうか? そもそもうまく説明ができないのですが。。
>>772 flgというのはA、B、Cそれぞれにあるの?
774 :
NAME IS NULL :2007/08/31(金) 12:28:36 ID:YdfX5avM
775 :
769 :2007/08/31(金) 13:21:37 ID:49luVNYp
>>770 参考になりました、ありがとうございました。
>>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);
こんな感じでできない?
レコード数多くて重いようだったら、もうちょい工夫する必要はあるが。
777 :
NAME IS NULL :2007/08/31(金) 13:48:18 ID:YdfX5avM
>>776 inですか。なるほど。
できそうな気がします。
レコード数はそれほどでもないので大丈夫です。
どうもありがとうございました!
778 :
NAME 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ヶ月で初心者です。 どなた様かお力を分けてください。
>>778 VBAなら「ADOX テーブル作成」とかでググった方が早い。
SQLでどうこうするよりADOXでの操作は面倒だけどな。
でも、テーブル作成して実データを毎回突っ込むよりは、
多少複雑でもADOXでVIEWを作るだけに留めた方が良くないか?
>>778 VBAといってるけど、MS-ACCESS?その辺の情報を出せば何か方法が出るかもしれないよ。
勝敗の表示 自分 相手 勝敗 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とサブクエリあたり使うと思うけど・・・
>>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 自分,相手;
もっと楽にできそうな気もするが...
783 :
782 :2007/09/02(日) 02:25:10 ID:???
あ、resultは勝敗のことね。count(*)も AS 合計を付け忘れちゃった。
勝率は出してないけど、勝ち/合計で出せる。
SQLでするなら
SELECT * ,勝ち/合計 FROM (
>>782 のクエリ) AS T2
とさらに包んだ方がいいかな。
784 :
782 :2007/09/02(日) 02:28:40 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って初めて使いました。
ありがとうございます。
786 :
782 :2007/09/02(日) 04:21:12 ID:???
そうか、勝敗はCASE内に出てきてもSUMで集約されるから、 わざわざサブクエリにする必要なかったか。こりゃ失礼。
787 :
NAME 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 にあります。
ぜひ教えてください。
789 :
NAME 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" のエラーがでます。 どうしたいいでしょうか? よろしくお願いします。
791 :
778 :2007/09/03(月) 09:39:53 ID:DLb/zQ6a
>>779 さん
>>780 さん
ありがとうございます。
さっそく調べてみます。
vbaは
Accessをつかってます。
わざわざ別にテーブル用意して業種コード 例) 製造 seizou それでメインテーブルに登録された業種コードseizouから 参照して製造って文字をひらいだすのは、なにかメリットがあるのでしょうか? はじめからメインテーブルに製造って文字いれておけばいいんじゃない? と思ったのですが、メリットがあるのなら教えてください。
>>792 出力されるデータがログデータなら、リンクさせなくても良いんじゃない。
ただ、後からデータの修正が必要だったり、他のテーブルとの連携が
必要だったりする場合は、コードじゃないと色々と支障が出るだろう。
SQL文の違いで質問です。 TO_NUMBER SQL文で検索時に関数を使ってオラクルデータを引っ張っています。 以下がその例です。 COL1はVarchar2(12)になっています。 SELECT * FROM A WHERE TO_NUMBER(COL1) = 1 これと同じようなことをACCESSでしようと思うと関数は何を使えばいいのでしょうか? 暗黙型変換での比較をできるだけ行いたくない為お伺いしたいのですが。 ご教授お願いいたします。
>>795 整数期待するならCLng(COL1)で良いんじゃないか?
何が入ってるか分からないならValの方が良いかもしれん。
>>796 整数期待は問題ないのですが桁数の問題のほうがありおそらく9が12ケタきたらオーバーフローするんじゃないかと
なので聞いてみた次第です
Valで取りあえずやろうと思うんですが、本当は適切に12ケタの整数を処理できる型変換がおこなえたらいいなぁとか思っています。
派生テーブルって毎回書かなければならないのでしょうか? つまり、 SELECT * FROM (SELECT ほげほげ) AS T1, (SELECT count(*) FROM (SELECT ほげほげ) AS T2) AS T3 のように2回同じほげほげを書かなくてはならないのでしょうか?
>>797 そこまで桁が行くのなら通貨型にしたほうが良いんでないか?
Ccur関数があるし。
>>798 共通表式とかインラインビューとかでぐぐれ
801 :
800 :2007/09/05(水) 22:41:02 ID:???
違った。インラインビューはぐぐらなくていい。 ×共通表式とかインラインビューとかでぐぐれ ○共通表式とかWITH句とかでぐぐれ
>800-801 Thx. 残念ながら対応してなかったので地道に書くことにするよ。
SQL2005だけど with便利〜と思って使ってたんだけど 妙に遅いクエリがあって 試しにインラインビューで作ってみっかとやってみたら パフォーマンスが10倍程度改善された事があった
うちは重たいマスタ参照する副照会2回出てくるのをwith句に変更したらちゃんとメモリ上の一時テーブル見てくれて嬉しかったけど
共通表式を使うと必ず一時表を作るんじゃない? それが良い方向に働く場合もあるし悪い方向に働く場合もある、とか。知らんけど。
806 :
NAME IS NULL :2007/09/09(日) 22:22:19 ID:8M0+Vljb
初心者ながら恐れ入ります。 実際、使う機会てそうないと思うのですが、如何か。 アクセスとかの利用者のみか?
807 :
NAME 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を書きたいです。
808 :
NAME IS NULL :2007/09/11(火) 11:33:37 ID:IJsUEx2O
ちなみに、それぞれのテーブル間で、キーを持つことはできない状況です。 (各テーブルは別会社管理で、「キー持たせよう」という案は片方の会社で 「やだ」と言われた為。) ビューは作ってもよいと言われています。
1とA、2とBを関連付けるのは何?
SELECT A.名前,B.商品名 FROM 注文テーブル A,商品テーブル B WHERE A.注文番号 =(CASE WHEN B.商品記号 = A THEN 1 ELSE B.商品番号 = B THEN 2 END)
2つでいいのか
812 :
NAME IS NULL :2007/09/11(火) 11:57:29 ID:IJsUEx2O
>>809 ,
>>810 ありがとうございます。
>>809 関連付けはSQL文でベタ書き(DBでは直接関連付けできない)
のつもりです。
>>810 ありがとうございます。
CASEとかWHENとかはOracleでも使えますか?
とりあえず調べてみます。
>>812 そうじゃなくて、AとB以外無いのか、あるならその法則、を聞いたんだけどな
CASEは標準だよ
古いオラクルでcase使えない場合はdecode
Oracle 使ったことないんだけど、 A.注文番号 + 64 = ASC(B.商品番号) でいいんかな。CASE 使わないだけ、こっちの方が速そう。
816 :
NAME IS NULL :2007/09/11(火) 15:01:07 ID:+7Z4LZr/
X列 Y列 ____________ か ! 村 の の バ 西 村 ー か バ ー X列に対し、Y列は次にくる文字を表しています。 PLSQLでない普通のSQLを用い、これを順番どおりに 並べ替えて出力する方法を教えてください。
>>816 SQL99のWITH RECURSIVEを使う。
MySQLを始めたばかりなのですが TABLEを削除する際に DELETEしないでDROPすると変なものが残ったりするのでしょうか?
>>816 OracleならJavaストアドで処理しろwww
exists句が未だに理解できん・・・ 使えるには使えるんだが理屈がな・・・ なんでこれでちゃんと動くんだ?って思う。
>>821 exists や in は句じゃなくて述語。
>>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
}
}
}
とか。
実際にループして動いてるとは限らないけど
意味的にはそういうことかと。
なんで、inで指定した順番に取り出すって方法が無いんだろう?
日付を検索条件にした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を書けばいいのでしょうか? 文字列を抽出するときのようにワイルドカードも使えないようで どうやっていいのかわからない状況です。 よろしくお願いいたします
>>825 YEAR(date) = 2007
and MONTH(date) = 9
and SUBSTRING(CONVERT(varchar, date, 120), 12, 8) = '06:10:00'
試してないので、微妙にずれてるかも。
>>824 抽出結果をソートすれば事足りるからじゃね?
>>826 ありがとうございます。
やはり1行のselect文ではできないんですね
convertなどを調べてみます。
1行だろこれw
ある条件で絞り込んで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から引っ張ってきてプログラムで求めれば簡単なのですが・・・
>>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)
とすればいい。-- が、相関サブクエリ内のサブクエリにさらにサブクエリが...
832 :
831 :2007/09/16(日) 05:01:32 ID:???
どっちでもいいことなんだが、気になったもので訂正 > (SELECT max(id)+1 FROM Table) の+1は無くてもよかった...orz
>>831 スゲー。期待したものが取れました。書いてもらうとなるほどと
思うのですが。SQLってむずかしい。
以下のような2つのテーブルがあるとします。 1.商品テーブル: 商品コードと商品名の列からなるテーブル。 前提として商品コードの数は少ないものとし(10個程度)、今後増えるとしても1年に1個増える程度と仮定します。 2.部材テーブル: 部材コードと部材名称の列からなるテーブル。データ数は数万件。 ここで部材毎にこの商品では使用可能、使用不可能という情報を定義するとなると、部材コード、商品コードを列に持つ別テーブルを作成し、そこにデータを作成するのが普通かと思います。 しかし、現在携わっているシステムでは、そのようにしないで、部材テーブルに商品コードを列名として追加し、その値をフラグとして使用可能、使用不可能を定義するという設計がされてました。 このようなテーブル設計になっている理由ですが、どうやら以下のようなことらしいです。 ・部材テーブルを開くだけで、部材がどの商品で使用可能かが一目で確認出きる。 ・最初に大量に部材をテーブルに登録する時に、EXCELで管理している一覧表からコピーペーストで簡単にデータを追加出きる。 部材一覧はお客様がEXCELで管理してます。フォーマットは部材が行方向に並び、列方向に商品コードがあって、セルのチェックのありなしで、部材がどの商品で使えるかどうかを管理してます。 ・新しい部材コードを追加する時に、その部材がどの商品で利用可能かを同時にチェックしていくことでデータが作成出きる。 上記のような設計とか場合によってはありなのでしょうか? メンテナンス上の理由だけであれば、テーブルは3つ使い、クロス集計のviewを作成して、それで管理するというのもありそうな気がしてますが。
>>834 正規化という観点からなら、商品・部材・商品部材関連の3表に分けるのがセオリー。
ただしパフォーマンスや運用上の理由で(第一)正規形崩しをすることはある。
以下3つの条件がそろえば使うこともある。
部材から商品の問い合わせだけで商品からの問い合わせがない。
基本的に登録時に辞書的に使うもので基本的に結合はしない。
商品側のアイテムにほとんど変化がない。
客に入力してもらうためのフォームはデータを横に持ったほうがわかりやすいとしても
内部のテーブルをどう持つかは分けて考えるべき。
あとエクセルのデータと内部のテーブルはどちらが正でどちらが副かはしっかり決めておくこと。
836 :
NAME 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 というのを得たいのですが、どのようにすればいいのでしょうか。
>>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
838 :
837 :2007/09/22(土) 00:05:45 ID:???
ORDER BYつけ忘れた・・・
>>837 それだとkasuのscoreが0にならずにnullになる。
840 :
837 :2007/09/22(土) 00:36:09 ID:???
>>839 まあそのへんは適当にCOALESCEなりCASEなりで。
841 :
836 :2007/09/22(土) 00:47:43 ID:???
>>837 (840)
caseを使えばよかったんですね。
ありがとうございます。
842 :
NAME 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度のクエリで取得することは可能なんでしょうか?
>>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'
(+ で文字列の連結が出来るとする)
もしかして、where日付範囲 and not (22日でID2未満) and not (24日でIDが1より大) という感じで、日付で選択してから両端を切り落とせばOK?
845 :
842 :2007/09/22(土) 17:10:43 ID:???
>>843 大変美しい解を、どうも有り難うございます。
一瞬、844を思いついたのですが、843様の方がスマートです。
どうも有り難うございました。
846 :
NAME IS NULL :2007/09/24(月) 21:15:10 ID:2+Cwu/kw
ずいぶん初歩的な質問で悪いんですが合併律、分解律、擬推移律の成り立ちを証明したいんですが… アームストロングの公理系調べても成り立つとしか書いてないもので… だれか証明のプロセスを説明していただけないでしょうか?
847 :
NAME IS NULL :2007/09/24(月) 22:09:07 ID:BEV9oSXR
それってSQL関係あんの?
849 :
NAME IS NULL :2007/09/24(月) 23:51:54 ID:2+Cwu/kw
あーそっちのほうがいいかもしれないです そっちで聞いてもマルチ死ねって言われないですかね…?
「向こうで聞きます」って言ってからにすれば普通はマルチだとは言われない
では向こうで聞いてみます…
852 :
NAME 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 の数は取りあえず固定なのですが増えても大丈夫なようにしたいのです。
テーブル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の記述をご教示頂きたく。
854 :
NAME 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 テーブル名
>>853 Oracle使いじゃないからワカランのだけど、そのSQLが動いてもよさそうなもんだが...。
他には、
SET A.基準数 = (SELECT SUM(B.数量)/A.単位数 FROM B WHERE B.ID=A.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) 別々の行ででてしまいましたです…
858 :
NAME 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行出て来てしまいますし…
>>858 sumで括れ。
sum(CASE WHEN TYPE='A' THEN COUNT ELSE 0 END) AS A,
以下同じ
>>853 update ... set ... = <subquery> は動くはずだから
>>855 でいけるはず。
>>858 select ID, count(case when TYPE = 'A' then 1 else 0 end),(以下略)
861 :
860 :2007/09/26(水) 18:24:08 ID:???
ケコーンした上に間違えた・・・
>>859 でいいです・・・
>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)
863 :
NAME IS NULL :2007/09/26(水) 23:39:37 ID:DBQhsmg7
SQLとは話がずれてしまうのですが、質問させてください。 私が今入っている現場で、「デッドロックが起きるから」という理由で ロックを使わずに、更新日時を持たせたカラムを使って排他制御をして います。これって普通なんでしょうか? ロックだけで排他制御をするのっておかしいんでしょうか?
>>863 楽観的排他というよく使われる手法。
悲観的排他という言葉と一緒にググってみなされ。
>>864 オプティミスティックロックでデッドロックは防げんと思うがな。
まぁ
>>863 の説明だけからじゃ、どっちなのか判断はつかんが。
本当にPMがアホだったという可能性もなくはないし。
>>865 デットロックにはならないのと違うの?あっさり失敗するだけで。
>>866 更新対象のリソースが一つだけの場合はそもそもデッドロックは発生しない。
更新対象のリソースが複数ある場合、基本的にオプティミスティックロックは使えない。
ただしこの手法がまったく使えないわけではなくて、例えば代表の一つのテーブルを
決めて、それを参照して全テーブルの更新の可否を判断するという形で用いられる
ことはある。
ところがそのような形にした場合、オプティミスティックロックだろうが通常のロック
だろうが、デッドロックを防ぐ上では同等。
要は、複数のリソースの獲得の競合がデッドロックなわけなんで、それを代表の
1リソース(mutex)を獲得したトランザクションが総獲りできるという形にすることが
この場合のデッドロック防止手法の本質なわけ。
質問者が「デッドロック」という単語を ただの「ロック待ち」と混同して使っている予感。 てか実際に混同されてるケースって多いと思う。
870 :
863 :2007/09/27(木) 23:42:25 ID:???
>>864-869 回答ありがとうございました。
教えていただいた通り、楽観的排他のことでした。
大変勉強になりました。
code ------ 'abcd' '' NULL 上のような文字列値が入っているテーブルで 「NULLでない」かつ「1文字以上の値が入っている」行を抽出しようと WHERE (code IS NOT NULL) AND (code <> '') 上記のSQLを実行したのですが、SQLServerでは期待通り'abcd'の行が帰ってきたのに Oracle9iでは1行も該当しませんでした。 Oracleで同様の結果を得るためには条件式をどのようにすればいいのでしょうか?
>>871 WHERE code IS NOT NULL
oracleだと '' と NULL の区別はないからこれでいい。
873 :
871 :2007/09/28(金) 19:37:32 ID:???
>>872 SQLServerをメインで使っているので知らなかったのですが
まさか''とNULLが区別されないとは思いもよりませんでした。
おかげで思ったとおりの動作ができそうです。ありがとうとざいました
like '_%' なら DBMS 問わないんじゃね?
内容 ---------- 123450 123459 345210 233442 323280 例えば↑のような数字の羅列が入ったテーブルがあったとして ↓のように下一桁が「0」のデータ内容だけ取りたいんですけど 内容 ---------- 123450 345210 323280 何かいいSQLはないでしょうか? 環境はoracle10gを使用しています。
>875 mod(列名,10)=10 でいいんでわ?
=0 でしょ。
>>875-876 mod(列名,10)=0でいいのかな?
余りから導き出せばいいのですね。
ありがとうございます
spool パス名 ファイル名 で、メモ帳に書いた命令を全部行うことができるとわかったのですが なんどやっても成功せず・・・ パス名ってのを勘違いしてるのか、もしくは拡張子が.txtのままじゃあだめなのか・・・ どうすればよいでしょうか?
>>879 それはSQLとは関係ないぞ、sqlplusのコマンドの質問はoracleスレへ。
建前はそれとして、spoolは結果の出力先をファイルにする命令じゃ無かった?
"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
>>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
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
885 :
NAME 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 山本次郎
886 :
885 :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分近くかかって表示される結果を速くすることはできないのでしょうか?
>>886 Bテーブルに(SYSCODE, A_SYSCODE)と(SYSCODE, NAIYO)の
インデックスを張る。
DBMSによっては(SYSCODE, A_SYSCODE, NAIYO)のインデックスだけでも
いいかもしれない。
>>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;
でもいいかな。
っと、だらだら書いたらかぶった。 おまけに、A_SYSCODE=? じゃだめか、Atable.NAMEから引っ張り出さんと。
>>886 A, BテーブルのSYSCODEに索引があるのは当然として、
Bテーブルに(A_SYSCODE, SYSCODE)の索引が必要なんじゃないかな。
これがないと
SELECT A_SYSCODE, MAX(SYSCODE) AS BMAXCD FROM Bテーブル GROUP BY A_SYSCODE
で実際の並び替えが発生する。
891 :
885 :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しようと おもったんですけど・・・どうなんでしょうか?
>>891 BテーブルにA_SYSCODEのインデックスがすでにあり、
かつ、A_SYSCODEがNULLの割合が非常に高ければ(8割とかそのくらい)、
AテーブルとBテーブルを先にINNER JOINすると多少速くなるかもしれない。
そうでないなら(SYSCODE, A_SYSCODE)のインデックスを張っちゃうしかないと思う。
19個が20個になったところで今更どうってことないでしょ。
ちなみにビューでは解決にならないよ。
B.A_SYSCODEごとのB.SYSCODEが最大のレコードを求めるという 問題ならさんざん既出だが。 ただ、今日の回答者連はろくなのがいないな。
>>893 いや、やり方は分かった上でパフォーマンスのことを聞いているんだから
別に既出じゃないと思うが。
てか自分が「まともな回答」をしてやれよ。
過去ログ嫁
>891は素直に一時テーブルというものを調べてみるがヨロシ。 ちょっと複雑なSQLを書く場合には、SQL鯖の場合は1SQLでやらず、 一時テーブルが最強。
>>896 インデックスのない100万件のテーブルから1000件程度を取り出すのに
一時テーブルを使ったらどう速くなるのかkwsk。
>897 896だけど。 詳しくといわれても、詳しくは書けん。原理はおいらも知らん。 だって、それがSQL鯖クォリティであり、MSの企業秘密だから。 Oracleとかで一時テーブル使ってたら一生判らないことだから、 一度、使ってみて実感すればよいことなりよ。
>>898 理屈のわからない動作というのは少なからずあるものだが、
そのときは再現性のあるコードなり条件なりをあげるべき。
そうでなければただの電波。
一時テーブル+ストアドプロシージャで少しましになるケース。 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(最終分のみ)のレコードをはじめから用意しておくのが、 この手の問題への一番の処方箋なのだけどね。
901 :
NAME IS NULL :2007/10/10(水) 17:16:18 ID:sVDA5qMU
SQLSERVER2000 ビュー内でストアドプロシージャを呼び出す方法はありますか?
ありがとうございます。そちらを探してみます。
904 :
NAME 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という風になります。
906 :
904 :2007/10/10(水) 19:46:56 ID:???
>>905 ありがとうございます。
ばっちりいけました。
WEBシステムで画像のバイナリーデータを放り込んで 画像の管理を簡素化したいのですが 実際にそのようなシステムで管理されている大手サイトなどあるのでしょうか? DB管理にともなってDBへの負担があまりにも大きいようなら採用しないつもりです。
>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鯖で。
>>908 クエリアナライザだと出すぎるから、これはADOとかで空読みしたらいいの?
>>908 899じゃないけど、なんか、メモリ上に読み込んでスワップが発生するから、
結局一時テーブルへ書き出した方が速いって感じか?
意外とDBの違いじゃなくて、OSに依存してて、他のDBでもWindows版なら
一時テーブルを使った方が速かったりして...。
にしても、元質の回答にあったインデックスを張って、必要なレコードだけ読み込んでから
集約させる方が、一時テーブルを使ったとしても100万件を読み込むより速い気がする。
まぁ、SQL鯖使いじゃないからどっちだっていいや。
>>907 昔Oracle InterMediaで作った。
管理は普通のデータと同じだが、
データの取り出しやプロパティ検索がめんどくさかった。
913 :
NAME 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なのですが、こういう処理はプログラム側で対応すべきなのでしょうか?
>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 ); でどう?
>>913 その例テーブルだけだと、
SELECT NO,max(NAME),max(FLAG) FROM Table GROUP BY NO;
でもよさそうだな。
oracleならrank partitionでもいける。
917 :
NAME 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分くらいでデータは取れるのですが・・・
よい方法はないでしょうか?
>>917 なんかよく分からんテーブル設計だな。
例えば「顧客コード」はひとつの顧客に対してひとつ振られるわけじゃなくて
ある顧客に出荷した商品ひとつに対してひとつ振られるわけ?
そうだとしたら、「顧客マスタ」(と言いながら実は出荷実績みたいなもの)に
あらかじめ商品名やら業者名やらを入れといちゃえばいいと思うけど。
この設計のままでどうにかしたいなら、
まずは(A)を作る時間、(B)を作る時間、(D)を作る時間を
それぞれ測ってみるところからだろ。
回答が欲しいならキーの情報と投げたSQLは必要。 自分で何とかしたいならプランを調べる。
920 :
NAME IS NULL :2007/10/15(月) 09:44:37 ID:Y520eQFI
一日ごとの東証一部の全株価の終値のデータがあります。 証券コード(INTEGER) 日付(DATE) 終値(FLOAT) これが2年分あるのですが、これをDBに入れて、証券コードごとに 2年分を取り出せるようにしたいとおもってます。たとえば トヨタ自動車だったら、証券コード(7203)を指定すると、2年分の 終値のデータが得られる、という感じです。 このとき、DBのテーブルはどのように設計したらいいですか? どうかよろしくお願いします。
>>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
)
923 :
NAME IS NULL :2007/10/15(月) 19:41:31 ID:Y520eQFI
>>922 ありがとうございます。
でも、上記のようにすると、2000/01/20のトヨタのデータをinsertして
その後に2000/01/21のデータをinsertすると、重複扱いになってしまいます。
primary keyは証券コードにしました。
>>923 PKは(証券コード, 日付)だろ。
ただし日付がDATE型だと同じ日の違う時間の値も入れられちゃうから
それがマズければもう少し工夫が必要。
925 :
NAME 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));
>>920 個人的に作ってるものだけど、俺は
kabukaテーブル
銘柄コード 出来高年月日 始値 高値 安値 終値 出来高
primary key (銘柄コード、出来高年月日)にしてる。
(市場は考えない)
meigaraテーブル
銘柄コード 銘柄名 その他の情報〜
としてる
927 :
NAME IS NULL :2007/10/15(月) 20:52:33 ID:Y520eQFI
>>926 ありがとうございます。
そっちの方がいいですねえ。でもそれをつかうとするとinsert またやり直しか。。。。
でもやりなおしてみます。
nameとaddressのフィールドがあって、 address='○○県○○市〜' と入力されているものとします。 このとき、県内、県外の順にソートしたい場合は どのようなSQLを書けばよいのでしょうか?
上の例をみてSQLいじっていたらできました。 select name, case when address like '○○県%' then 1 else 2 end as odr from tblHoge order by odr とすればいいんですね。
930 :
NAME 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からこの値以下の最大値) よろしくお願いします。
>>930 Oracle で通るかどうかわからんけど
select (select max(col) from B where col < A.col)
from A
>>930 いや、答えはすぐ書けるけど自分がどう考えたかぐらいは書こうぜ
933 :
NAME IS NULL :2007/10/18(木) 11:20:44 ID:HHvByvdj
初歩的なことですが、、、。 DB2で抽出した数字を指定桁でのゼロ埋め(前ゼロ)で抽出する方法が わかりません。。。 例えば、指定フィールドに「2」が入っていたときは 002 で抽出するというような方法です。 すいませんがよろしくお願いします。
select '00' || 指定フィールド from なんか
あと、桁数を指定して右から切り取ればOK。 Right() とか。
>931 ありがとうございます
937 :
NAME 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%'
ジブン デ タメセル ダロ ガ!!!!
939 :
NAME IS NULL :2007/10/19(金) 12:41:53 ID:VIvt3Tqz
はじめまして。 いま定職がなくて、今度面接を受けるのですが、 SQLの知識が必要な仕事なのですけれど、 ぜんぜんSQLのこと理解していなくて。。。 一時間の面接でボロが出ない程度の知識をあと一日か二日で覚えようと思ってるのですが、 最低限どれくらいのことを知っていればいいのでしょうか。。。 どうかよろしくお願い致します><
940 :
NAME 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の制限で無理でした。 他にやりかたなどあれば教えて頂きたいのですが、如何でしょうか?
>>940 そこはWHERE句じゃなくて、GROUP BY 句の後ろに
HAVING COUNT(DISTINCT SHOP) < 2
とすべきだと思うのだが、本当にCOUNT関数内にDISTINCTが使えないの?
943 :
942 :2007/10/19(金) 15:53:43 ID:???
ちょい補足。 HAVING count(DISTINCT SHOP)が使えるのなら、 GROUP BY句からSHOPは外せ。
>>942 あーご回答ありがとうございます。
調べて回ったんですが、ACCESSではCOUNT内でのDISTINCTは
使えないんです。(ACCESS 2003)
その後調べていると、WHEREにCOUNTはダメっぽいですね、、、
HAVINGが良く分かってないので、使いどころが分かりませんでした(><)
修正します。ありがとうございます。
945 :
940 :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さん、ありがとうございました。
946 :
sage :2007/10/19(金) 23:38:32 ID:a5j8WAG3
>>941 さん
ああ!どうもありがとうございます!!
これで受かる気がしてきました!!
わかりやすいですねー^^
valueSQL使いたいんだが、繋ぎ方がわからん。 データソースって、何を入れればいいんだ?
valueSQLって何かしらなかったんで調べてしまった。。 RDBMSは何使ってんの? つーかスレ違いなんだが、汎用の質問スレ無かったっけ?
950 :
NAME IS NULL :2007/10/23(火) 13:35:37 ID:4X2HVnn9
SQLServer初心者です。 VB2005からSQLServer2005への接続について質問させて下さい。 同サーバーのプロジェクト名Test_dbにテスト接続はできるのですが、 データソース構成ウィザードで、テーブル、ビュー等の左側に「+」「−」 が無く、展開できません。 データソース、データセットとして実態を 取込めません。 ちなみにVB2005からAccessのテーブルをデータソース、データセットとして取込む事は できました。 SQLServerから取込むにはどの様にするば良いでしょうか。 アドバイスお願いします。
トランザクションの分離レベルのRepeatable Readって、 トランザクションAがRepeatable Readでトランザクション開始 -> トランザクションBが表AのレコードBをUpdate更新して、コミット -> トランザクションAが同じ表AのレコードBをUpdateで更新 しようとしたらどうなる?
>>951 共有ロック式の場合のRepeatable Readは、トランザクションが読み取ったレコード全部に
コミットまでの期間共有ロックをかけてゆくと考えればいい。
>トランザクションBが表AのレコードBをUpdate更新して、コミット
この前にトランザクションAがレコードAを読み取っていればトランザクションBの更新はロックされ待機状態になる。
この前にトランザクションAがレコードAを読み取っていなければ競合は起きない。
マルチバージョニングの場合はシリアライザブルと同じ動作になる実装が多いと思う。Oracleとか。
954 :
NAME IS NULL :2007/10/23(火) 17:39:23 ID:4X2HVnn9
>952 失礼しました。 そちらに質問しました。
なるほど。あなたは天才ですね。まぁ、言葉の定義の問題になっちゃうかも しれまんせが、Repetable ReadはOracleとかのシリアラザブルのような動作が本来あるべき意味かなと 思いまして。よく、Repetable Readの説明で*実際にSELECT*文を同じ条件などで 検索させる説明がありますが、あくまで例で、本来はSELECT文を発行するかは関係なく、 Repeatable Readのトランザクションの*開始時点*の既に存在する行のみ 保証し、開始以降他によって追加された行(ファントム行)は保証しないのが、本来のRRなのかなと。 つまり、951の例では、トランザクショクンAの更新で、既にBによって更新され、 トランザクションの開始時点の行を保証できないから、エラーで落とす。
それであれば、よく、Read Committedレベルの時に、日付のタイムスタンプ見てロスト アップデート防いだりしますが、RRだと本来は共有ロックとか実装方式に関係なく、 ロストアップデートとか考える必要がない。 と、共有ロック方式のRRは偽RRじゃないかなと。まぁ、すっきりしました。 ありがとうございます。
>>955 いや、ちょっと理解が違うような。
Repeatable Read と Serializable では、
あるトランザクションが一度読んだレコードが変更されないのはどちらも同じ。
(Read Committed では変更されることがありうる。
そういう意味で
>>956 の理解は正しい。)
Repeatable Read と Serializable の違いは、
Repeatable Read ではあるトランザクションが最初にある条件で検索し、
後でもう一度同じ条件で検索したとき、レコードが増えていることが
ありうるのに対して、Serializable ではそれも許さない。
>>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なのでしょうけど 具体的なビジョンはもってますか?
>>958 951の例で言えば「トランザクションAが同じ表AのレコードBをUpdateで更新」は
Repeatable ReadでもSerializableでも許される。
(トランザクションBが更新する前にトランザクションAが読んでいなければ。)
つまり、問題は開始時点でどうたったかじゃなくて一度読んだかどうか。
その上で、Repeatable Readでは一度読んだ「レコード」に対してだけ
ロックがかかるのに対して、Serializableでは一度検索した「条件」に対しても
ロックがかかるというイメージ。
Serializableでは他のトランザクションが一度検索した条件に抵触するレコードは
更新できない。
ただ、この違いを実装しているDBMSがあるかどうかは知らない。
961 :
NAME 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 と似ている気がするのですが、もう少しシンプルです。
select 列1,列2, rank() over (partition by 列1 order by 列2) as ,欲しい値 from xxxx order by 列1,列2
963 :
NAME 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しようと思ったのですが、
もっと華麗な方法がありますか?
と、教えていただいた検索結果を結合しようと思ったのですが、
あるテーブルに以下のデータが入ってるとします。 (テストの点数と氏名が入ってるテーブルです)) --------------------- 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を使っております。 よろしくお願い致します。
cursor cur is select * from A union all select * from B for update て書くとforうp句は書けネーヨって怒られるんだけど、もしかして ROWID を セレクツするようにして、where current of cur って書いてるところを where rowid = rec.rowid って書くと超いい感じじゃね? やべ、スゲー発見しちゃったかも。
>>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;
967 :
966 :2007/10/24(水) 02:38:29 ID:???
見落としてた。 MySQLで動くかどうかは知らない。
>>963 DENSE_RANK OVER(ORDER BY 列1)
969 :
963 :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
970 :
NAME 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月だけを取り出すにはどうしたらいいのでしょう。 よろしくお願いします。
>>970 select YMD from d_tbl where YMD like '200610*';
973 :
970 :2007/10/25(木) 08:05:06 ID:???
>>971 すみません間違いました。
何年かは関係なく、10月を取り出す場合はどうしたらいいのでしょうか。
YMD like '____10%'
substring(YMD, 5, 2) = '10'
976 :
970 :2007/10/25(木) 09:52:24 ID:arcZFewB
どちらも9999年までしか使えないなw
YMD like '%10__'
979 :
NAME IS NULL :2007/10/26(金) 02:03:40 ID:EigH0966
すみません、SQLの第一、二、三正規系などが初心者向けに 解説されているサイトはないでしょうか? 意味がわからなく困っています・・・・参考書四でもさぱーりです。。。 因みに、やさしく学ぶ1SQLです
つデータベースの教科書
982 :
NAME 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 | を取りたいと思います。 お手数おかけしますがご教授の程よろしくお願いします。
typeをgroup化してdateでmaxを取る
984 :
NAME 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
);
これだとダメですよね。
986 :
NAME 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
count(*) by b
間違えたgroup by b
>>986 SELECT b,count(*) FROM (SELECT a,b FROM Table GROUP BY a,b) AS T1 GROUP BY b;
select b, count(*) from (select distinct a, b from Table) group by b;
皆様ありがとうございます
>>988 その方法だと重複がカウントされてしまいました
>>989 >>990 今MySQL 5.0.45で実験してるんですが、サブクエリが何故かエラーになってしまいました
ちょっと環境について調べてきます
992 :
986 :2007/10/26(金) 22:54:25 ID:???
すみません、完璧でしたテーブル名をタイポしてました 皆様ありがとうございます サブクエリは必須みたいですね、勉強になりました
埋め
ume
梅
998
1000
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。