SQL質疑応答スレ 9問目
- 1 :NAME IS NULL:2009/09/09(水) 19:31:36 ID:???
- このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。
SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。
質問するときはDBMS名を必ず付記してください。
【質問テンプレ】
・DBMS名とバージョン
・テーブルデータ
・欲しい結果
・説明
前スレ:
SQL質疑応答スレ 8問目
http://pc11.2ch.net/test/read.cgi/db/1236253554/
- 2 :NAME IS NULL:2009/09/09(水) 19:32:51 ID:???
- SQL言語リファレンス一覧
Oracle Database
http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05750-03/toc.htm
Microsoft SQL Server
http://msdn.microsoft.com/ja-jp/library/bb510741.aspx
IBM DB2 Database
http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp (目次から参照情報→SQL)
PostgreSQL
http://www.postgresql.jp/document/current/html/sql.html
MySQL
http://dev.mysql.com/doc/refman/5.1/ja/sql-syntax.html
参考リンク
http://sql.main.jp/cont/sql/map.html
http://www.atmarkit.co.jp/fnetwork/rensai/sql01/sql1.html
http://oraclesqlpuzzle.hp.infoseek.co.jp/
http://www.techscore.com/tech/sql/
- 3 :NAME IS NULL:2009/09/09(水) 19:33:55 ID:???
- 過去スレ
SQL質疑応答スレ 8問目
http://pc11.2ch.net/test/read.cgi/db/1236253554/
SQL質疑応答スレ 7問目
http://pc11.2ch.net/test/read.cgi/db/1223525474/
SQL質疑応答スレ 6問目
http://pc11.2ch.net/test/read.cgi/db/1210940477/
SQL質疑応答スレ 5問目
http://pc11.2ch.net/test/read.cgi/db/1193486961/
【帰ってきた】SQL質疑応答スレ 4問目
http://pc11.2ch.net/test/read.cgi/db/1176553195/
【帰ってきた】SQL質疑応答スレ 3問目
http://pc11.2ch.net/test/read.cgi/db/1160458216/
【帰ってきた】SQL質疑応答スレ 2問目
http://pc8.2ch.net/test/read.cgi/db/1141622643/
【帰ってきた】SQL質疑応答スレ
http://pc8.2ch.net/test/read.cgi/db/1124178925/
SQL質疑応答スレ Part 2
http://pc8.2ch.net/test/read.cgi/db/1103113155/
SQL質疑応答スレ
http://pc8.2ch.net/test/read.cgi/db/1056973582/
- 4 :NAME IS NULL:2009/09/09(水) 19:35:02 ID:???
- よくある質問1
(問)
ID | DATE | DATA
--+----------+-----
1 | 2007-11-11 | aaa
2 | 2007-11-11 | bbb
1 | 2007-11-10 | ccc
3 | 2007-11-12 | ddd
3 | 2007-11-11 | eee
4 | 2007-11-10 | fff
1 | 2007-11-12 | ggg
このようなテーブルから、下記のように
1 | 2007-11-12 | ggg
3 | 2007-11-12 | ddd
2 | 2007-11-11 | bbb
4 | 2007-11-10 | fff
各idに対して最新の1件だけ抽出するSQLの書き方を教えてください。
(答)
select A.ID,
A.DATE,
A.DATA
from TableName A
inner join
(select ID, max(DATE) as MAX_DATE
from TableName
group by ID
) B
on A.ID = B.ID
and A.DATE = B.MAX_DATE
- 5 :NAME IS NULL:2009/09/09(水) 19:36:09 ID:???
- よくある質問2
(問)
key data
----------------
1 a
1 a
1 b
1 b
1 a
2 b
2 a
2 a
というテーブルから
key a b
--------------------
1 3 2
2 2 1
というExcelのピボットの様なデータを取得したいのですが、どういうSQLになりますか?
a,bというのは固定なので、仮にcというデータがあっても無視して構いません。
(答)
SELECT key,
SUM(CASE data WHEN 'a' THEN 1 END) AS a,
SUM(CASE data WHEN 'b' THEN 1 END) AS b
FROM table
GROUP BY key
ORDER BY key
;
- 6 :NAME IS NULL:2009/09/09(水) 19:37:35 ID:???
- よくある質問3
(問)
ID HOGE
01 A
01 B
01 C
02 A
03 B
HOGEをAもBもCも持っている、ID:01だけ取り出すにはどうすればよかですか
(答1)
SELECT id
FROM TableName
WHERE hoge in ('A','B','C')
GROUP BY id
HAVING count(DISTINCT hoge) = 3
;
(答2)
select *
from TableName T1
where not exists (select *
from (values 'A', 'B', 'C') T2 (HOGE)
where not exists (select *
from TableName T3
where T1.ID = T3.ID
and T2.HOGE = T3.HOGE
)
)
;
※valuesの部分(Table Value Constructor)はDBMSによって文法がかなり違うので注意
- 7 :1:2009/09/09(水) 19:40:02 ID:???
- なんか落ちてたんで立てた
後悔はしていない
- 8 :NAME IS NULL:2009/09/09(水) 20:00:55 ID:???
- >>1
乙
- 9 :NAME IS NULL:2009/09/10(木) 06:37:53 ID:???
- おつ
- 10 :NAME IS NULL:2009/09/10(木) 20:13:02 ID:???
- SQL の SELECT で取得する個数を指定することはできますか?
例えば、ソートした結果の100番目から150番目を個取得するなどです。
- 11 :10:2009/09/10(木) 20:14:00 ID:???
- 「個数を指定する」というよりも、「範囲を指定する」の方が言葉として適切でした _o_
- 12 :NAME IS NULL:2009/09/10(木) 20:17:00 ID:???
- >>11
どっちもできるよ
- 13 :10:2009/09/10(木) 20:24:15 ID:???
- >>12
■件数指定 LIMIT
・先頭から 3 件問い合わせるには、次のようにする。
access の top と同じことができる。
(TOP 10 取得、表示行制限、レコード数限定、件数指定、表示件数)
(1 レコード取得、1 件取得)
select * from testm
order by key1
limit 0, 3
;
みたいな感じでしょうか?
「access の top と同じことができる。」の意味が解らないのですが。。
- 14 :NAME IS NULL:2009/09/10(木) 20:29:43 ID:???
- count(1)とcount(*)の違いを教えていただけないでしょうか?
- 15 :NAME IS NULL:2009/09/10(木) 21:21:19 ID:91yFw6iE
- お願いします。
テーブル1(t1)には
[ID][受け渡し区分][客着日]フィールドがあります。
主キー 数値 日付型です
テーブル2(t2)には
[ID][データ内容][受け渡し日]フィールドがあります。
主キー テキスト 日付型です。
主キーで結合し、[データ内容][受け渡し日][客着日]の選択クエリを作ろうとしています。
[受け渡し日]の日付に[受け渡し区分]に入った数値を加算した日付を、
[客着日]に入るようなイメージなのですが、
どうもうまく作れません。
分かりにくいかもしれませんが、どうぞよろしくお願いします。。
- 16 :NAME IS NULL:2009/09/10(木) 21:46:29 ID:???
- >>14
その違いは、使ってるデータベスのマニュアルに書いてあるはずだから、
マニュアル読んでくるといいよ
- 17 :NAME IS NULL:2009/09/10(木) 21:52:43 ID:???
- >>15
よう分からんが、こうか?
select
t2.データ内容, t2.受け渡し日, t1.客着日
from テーブル1 t1
join テーブル2 t2 on t1.id = t2.id
where
t1.客着日 = t1.受け渡し区分 + t2.受け渡し日
あと、使ってるDBとバージョンは提示した方がいいぞ
- 18 :NAME IS NULL:2009/09/10(木) 22:15:32 ID:91yFw6iE
- >>17
すいません。
access2000とかいう化石みたいなもの使ってます。
大まかにご提示いただいたようなテーブルを作成したのですが、
select t2.データ内容, t2.受け渡し日, t1.客着日
from t1,t2
join t2 on t1.id = t2.id
where t1.客着日 = t2.受け渡し区分 + t2.受け渡し日
where指定のあたりが間違ってるとのことなのです・・。
- 19 :NAME IS NULL:2009/09/10(木) 22:16:37 ID:???
- >>16
わかりませんでした、ごめんなさい
- 20 :NAME IS NULL:2009/09/10(木) 22:19:12 ID:???
- 日付演算の方法がわからんというオチだったりしてなw
- 21 :NAME IS NULL:2009/09/10(木) 22:54:35 ID:???
- >>19
Oracle
ttp://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05750-03/functions.htm#37956
MySQL
ttp://dev.mysql.com/doc/refman/5.1/ja/group-by-functions.html
PostgreSQL
ttp://www.postgresql.jp/document/pg840doc/html/functions-aggregate.html
firebird
ttp://firebird.skr.jp/wiki/%C1%C8%B9%FE%A4%DF%B4%D8%BF%F4%B0%EC%CD%F7#count
SQL Server
ttp://msdn.microsoft.com/ja-jp/library/ms175997.aspx
DB2
ttp://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.sql.ref.doc/doc/r0000759.html
好きなの嫁
言ってることは、どのドキュメントも同じだから
- 22 :NAME IS NULL:2009/09/10(木) 23:05:29 ID:???
- >>21
親切にありがとうございました
結論として、まったく変わらないということですね
勉強になりました
- 23 :NAME IS NULL:2009/09/10(木) 23:24:41 ID:???
- だめだこりゃ・・・
- 24 :NAME IS NULL:2009/09/10(木) 23:42:45 ID:???
- >>22の来世に幸あれ
- 25 :NAME IS NULL:2009/09/11(金) 06:12:59 ID:???
- おまえら自信なさげに不親切な回答してるけど
count(1)とcount(*)の結果は同じだぜ?
- 26 :NAME IS NULL:2009/09/13(日) 14:43:18 ID:BgFEKAE5
- Oracle10gでスキーマ内で更新されたレコードを抽出することはできますでしょうか?
判別としては各テーブルにUPDDATE項目があります。
DBA_TAB_COLUMNSあたりを使用して抽出できないでしょうか?
- 27 :NAME IS NULL:2009/09/13(日) 16:06:40 ID:olkIEqmS
- お願いします。
access2003です。
あるテーブルに日付フィールドがあり、
そのフィールドの日付が土日であれば、
翌営業日(月)の日付を返してくれるクエリを作成したいと思っています。
どうぞよろしくお願いします。
とゆうか、sql単体では出来ないのでしょうか
- 28 :NAME IS NULL:2009/09/13(日) 18:49:28 ID:???
- SELECT Switch(Weekday(日付)=1, Dateadd("d", 1, 日付), Weekday(日付)=7, Dateadd("d", 2, 日付)) AS 営業日
FROM あるテーブル AS T1
WHERE T1.日付 = (SELECT Max(T2.日付) FROM あるテーブル AS T2);
最新日が土日なら翌月曜日に
でも確認してないから全然自信ないわ…
vba使ったほうが絶対良いよ
- 29 :NAME IS NULL:2009/09/13(日) 20:16:58 ID:???
- >>26
LogMinerを使うか、FlashBack Queryでもどうにかできるかも
まあトリガーをあらかじめ仕掛けておくのが常道だけど
- 30 :NAME IS NULL:2009/09/13(日) 20:28:08 ID:olkIEqmS
- ありがとうございます。
UPDATE T1 SET [土日後]=[加算前]+2 WHERE WEEKDAY(加算前)=1;
これで、T1テーブルの、
加算前フィールドの日付が日曜の場合、
+土日後フィールドに2日を加算した値を入れるようには出来ました。
ここから、スウィッチを文に含めると構文エラーと怒られるんですが、
何かケアレスしてそうな所ございませんか・・・
vbaは読みづらい書きづらいで、sqlで済ませたいんです。。
- 31 :NAME IS NULL:2009/09/13(日) 20:51:49 ID:mrtjO9XU
- >>29
既存のシステムの保守にあたり、テストを行いたいのですが、
機能を処理してメインとなるテーブルはわかるのですが、その他にもないか
判別したいのです。
トリガーとなるとすべてのテーブルに仕掛けておかないといけないですよね
それしか方法はないですか・・・
- 32 :NAME IS NULL:2009/09/13(日) 21:01:45 ID:???
- >>31
じゃあやっぱLogMinerで掘るしかないんじゃね?
- 33 :NAME IS NULL:2009/09/13(日) 21:04:26 ID:???
- >>30
無理して1SQLでやらなくても、土曜の場合+2するUPDATE文と
日曜の場合+1するUPDATE文2回実行すればいいんじゃないかね
余計なお世話かもしれないが
お前のとこの営業日は、祝祭日も年末年始も考慮しないのか
- 34 :NAME IS NULL:2009/09/13(日) 21:45:34 ID:???
- >>30
UPDATE文だったのか…Accessだと確か更新クエリでサブクエリ使えなかったような
構文にも自信ないからこっちに行った方がいいかも
Access総合相談所 其の22
http://pc11.2ch.net/test/read.cgi/bsoft/1251297578/
- 35 :NAME IS NULL:2009/09/14(月) 14:44:11 ID:???
- 注意: 他のSQLデータベース管理システムでの作業に親しんだユーザは、count集約関数がテーブル全体に適用される場合の性能に失望するかも知れません。
SELECT count(*) FROM sometable;のような問い合わせはテーブル全体を逐次スキャンを用いてPostgreSQLにより実行されます。
うわ、今まさに失望した。
- 36 :NAME IS NULL:2009/09/14(月) 14:46:41 ID:???
- ちなみにpostgresqlのdistinct速くなったらしいね、というのはもう古い情報だろうか
- 37 :NAME IS NULL:2009/09/15(火) 19:01:50 ID:nAU+9E+9
- 複数のテーブルから同条件で抽出したレコードのカウントを取得したいのですが、
スマートな方法はありませんか?
テーブルをUNION ALLで連結し、
countした結果をさらに合計する方法を考えたんですが、
他にいい方法はありますか?
例)
select count as (cnt) from ta union all select count as (cnt) from tb
これの結果をさらに合計↑
- 38 :NAME IS NULL:2009/09/15(火) 19:15:01 ID:???
- UNION ALLしてからcountすればいいじゃない
- 39 :37:2009/09/15(火) 22:23:28 ID:nAU+9E+9
- >>38
すみません、よかったら具体例書いていただけませんか?
- 40 :NAME IS NULL:2009/09/15(火) 22:31:25 ID:???
- select count(*) from (select * from ta union all select * from tb) where 条件
ということだったんじゃないの?
- 41 :37:2009/09/15(火) 23:53:26 ID:nAU+9E+9
- サブクエリーですね。
試してみます。ありがとうございました!
- 42 :NAME IS NULL:2009/09/17(木) 14:32:22 ID:???
- 今PHPを学習していて、SQLite使ってますが、やはりMySQLの方がいいのでしょうか?
ユーザ管理機能などの点でSQLiteは駄目だとか読みました
しかし何か、SQLiteの方がPHP本体では推奨しているとか、MySQLを禁止しているところもあるとか聞いたりしたものでどうなのかなぁ、と
それでも学習するという意味でも、実用的という意味でもMySQLの方がいいのかなぁと思い始めてきたのですが、どういう違いがあるのでしょうか?
- 43 :NAME IS NULL:2009/09/17(木) 14:51:03 ID:???
- コンパクトで、別途サービスなりデーモンなりを設定しなくていいのがSQLiteの優位性かなあと
- 44 :37:2009/09/17(木) 16:47:58 ID:k//XEl+s
- 37ですが、残念なことにMySQLではサブクエリーが使用できませんでした。
37のはなんとか他の方法でいけたのですが、もう一つ質問があります。
複数のテーブルから同条件で抽出した結果セットの並び替えを行いたいのですが、
サブクエリーを使用せず並び替える方法はありませんか?
select * from ta union all select * from tb order by 条件
とするとテーブルtbのみ並び替えが行われると思うのですが、
taとtbテーブルを合わせた結果セットの並び替えを行いたいのです。
どうすればいいのでしょう?
- 45 :NAME IS NULL:2009/09/17(木) 17:15:04 ID:???
- >select * from ta union all select * from tb order by 条件
>とするとテーブルtbのみ並び替えが行われると思うのですが、
思うだけではなく、実行してみれば?
実行環境がないのかな?
- 46 :37:2009/09/17(木) 17:18:33 ID:k//XEl+s
- すみません、whereが各select個々に記述しないとだめだったので、
orderも個々じゃないと駄目なのかなと。
確かに推測ではなく確認を取るべきですね。
動作させて出直してきます。
- 47 :NAME IS NULL:2009/09/17(木) 19:27:07 ID:???
- >>44
> MySQLではサブクエリーが使用できませんでした
半端な情報を流すのはやめた方がいいです。
同じような言い方をするならば、MySQLはサブクエリをサポートしています。
- 48 :NAME IS NULL:2009/09/17(木) 20:00:27 ID:???
- × MySQLはサブクエリをサポートしています
○ MySQLはバージョン4.1からサブクエリをサポートしています
- 49 :NAME IS NULL:2009/09/17(木) 20:25:33 ID:???
- 両方にorder byかけたっけ?
と思いSQL Server2008で試したけど無理だった。
unionの外でかけるしかないね
- 50 :NAME IS NULL:2009/09/17(木) 20:29:32 ID:???
- order byの評価順は一番最後
unionよりも後
- 51 :NAME IS NULL:2009/09/18(金) 15:36:31 ID:???
- 複数店舗の定休日を管理するテーブル設計はどうしたらいいでしょうか。
定休日は「毎週土日、第三木曜日、祝日、毎月15日のみ」などいろいろあります。
また、どの店が定休日かを抽出する必要があります。
( 来週の金曜日が定休日でなく、かつ予約がない店など )
一番先に思いついたのは例えば「毎週土曜日」というデータを持ち、そこから今月であれば 9/5, 9/12, 9/19, 9/26 という日付データを持とうかと考えましたが、来月や年末を見ることを考えると、データ量が膨大になります(^^;。
お知恵を貸してください!
- 52 :NAME IS NULL:2009/09/18(金) 17:07:13 ID:???
- テーブル設計はすれ違いな気もするが
日付、店舗ごとに休みの日もてばいいんじゃね
1店舗最大366件/年だぜ。それで膨大ってことはないだろ
- 53 :NAME IS NULL:2009/09/18(金) 17:27:07 ID:???
- で、バッチでレコード作ればいいよねきっと。
- 54 :51:2009/09/18(金) 17:43:05 ID:???
- >>52-53
すれ違い気味にもかかわらず、ありがとうございます。
# どこがいいかと探してみて「何故データベース設計は軽視されるのか」があったのですが、
# ここもちょっと違う感じです。相応しい板に誘導していただければ移動します><
確かに言われてみれば、366×年数×店舗の件数なので、そんなに膨大ではないですね。
下記のように持ち方でいいのでしょうか。
ShopID|Holiday
------+-------
1|2009/1/1
1|2009/1/3
2|2009/9/18
2|2009/9/19
3|2000/1/1
この場合、2009/1/1 が休みじゃない ShopID の抽出 ( 2 と 3 ) の SQL はどのようになるでしょうか。
- 55 :NAME IS NULL:2009/09/18(金) 17:58:54 ID:???
- select * from ショップマスタ where not exists (
select * from 休日マスタ where 休日マスタ.ShopID = ショップマスタ.ShopID and Holiday = '2009/1/1');
こんな感じで取れない?
- 56 :51:2009/09/18(金) 18:07:45 ID:???
- >>55
ありがとうございます!ばっちりです。
先の話ですが、ショップマスタが 1000 件、
休日マスタが 10 万件の場合、
ShopID と Holyday へのインデックス適用以外に
パフォーマンスで考えることはなんでしょうか。
SQL もこのままでいけるものでしょうか。
- 57 :NAME IS NULL:2009/09/18(金) 18:28:38 ID:???
- 速度はある程度出ると思うけど、一応実測してみてね
- 58 :NAME IS NULL:2009/09/18(金) 18:33:41 ID:???
- >>57
そうですね。ありがとうございます。
0.3s くらい出ているので問題なさそうです。
- 59 :NAME IS NULL:2009/09/18(金) 19:00:35 ID:???
- オプティマイザとかによるんだが、(Holiday,ShopID)で主キーにするなら
select * from ショップマスタ where ShopID not in
(select ShopID from 休日マスタ where Holiday = '2009/1/1')
のが速い気がする
- 60 :NAME IS NULL:2009/09/18(金) 20:29:55 ID:???
- >>59
ああ、やっぱりいろいろあるのですね。
ありがとうございます。
PostgreSQL 8.3 を考えています。
データ件数を 100 万件など増やして試してみます。
- 61 :NAME IS NULL:2009/09/19(土) 15:47:13 ID:???
- inとexistsでの速度計測したらはってほしいな。
- 62 :NAME IS NULL:2009/09/20(日) 08:41:22 ID:OTmXdOaQ
- このスレの存在をしらずに、別のスレで同じ書き込みをしました。
すみません。
質問は、、、
Mampを使って、php、mysqlとつないで簡単な掲示板を作ったのですが、
文字化けだらけです。utf-8に設定してるのですが、、
どこが問題なのでしょうか。
この問題を解決された方、アドバイスをよろしくお願いします。
- 63 :NAME IS NULL:2009/09/20(日) 10:47:07 ID:???
- >どこが問題なのでしょうか。
macじゃね?
- 64 :NAME IS NULL:2009/09/20(日) 23:22:18 ID:???
- >>61
ちなみにSQL Server2008だとどっちも全く同じ実行計画だった
- 65 :NAME IS NULL:2009/09/21(月) 03:59:08 ID:???
- データ量は?
- 66 :NAME IS NULL:2009/09/23(水) 00:06:44 ID:???
- CREATE TABLE test (username VARCHAR(50),password VARCHAR(32))
というので、usernameにPRIMARY KEYを設定したいのですが、
CREATE TABLE test (username VARCHAR(50),password VARCHAR(32) PRIMARY KEY(username))
のように設定すればいいのでしょうか?
主キーの設定の仕方が分からないもので教えていただけたらと思います
- 67 :NAME IS NULL:2009/09/23(水) 01:22:34 ID:???
- >>66
使ってるDB書いてくれないと答えられないよ!!!!
- 68 :66:2009/09/23(水) 13:43:47 ID:1c6MbXvq
- すみませんでした
リレーショナルデータベースで、抽象化レイヤはSQLiteです
PEAR::Authを利用前にユーザ情報テーブルを定義しようと思ったのです
- 69 :NAME IS NULL:2009/09/23(水) 18:57:27 ID:???
- CREATE TABLE test (username VARCHAR(50),password VARCHAR(32),PRIMARY KEY(username))
でいけるんじゃない
- 70 :NAME IS NULL:2009/09/24(木) 01:17:28 ID:???
- SQL Server 2005+Management Studioを使用しています。
1列目 2列目 3列目
0 2
3 2
0 4
1 5
1,2列目を使って計算し、3列目に結果を格納したビューを作りたいと考えています。
・1列目が0以外の時は1,2列目を使って計算して結果を3列目に格納し、
・1列目が0の時は計算しない(3列目はNULL値を格納)。
のような場合を考えているのですが、どのような方法があるでしょうか?
ご教授よろしくお願いします。
- 71 :NAME IS NULL:2009/09/24(木) 01:27:33 ID:???
- CASE でできるだろ。
- 72 :NAME IS NULL:2009/09/24(木) 02:00:53 ID:???
- select
a.1列目,
a.2列目,
case when a.1列目<>0 then null
else a.1列目+a..列目 end as 3列目
table a
- 73 :70:2009/09/24(木) 02:21:50 ID:???
- >71,72
さっそくやってみたらできました!本当にありがとうございます!!
- 74 :NAME IS NULL:2009/09/24(木) 13:15:44 ID:Z8PuTcTT
- MYSQL5使用してます。
テーブル
id code date
1 abc 2009-09-01 00:00:00
2 def ...
3 abc ...
4 abc ...
・欲しい結果
1日範囲で個別コードごとの総カウント数(COUNT)を取得し返したい。
・説明
アクセス集計していますが、コードがバラバラのため
個別にどれだけ該当コードでアクセスされたのか集計したいのです。
SQL文2回なら出来ますが、出来れば1度にやりたいのです。
よろしくお願いします。
- 75 :51:2009/09/24(木) 13:49:14 ID:???
- >>61
計測してみました。
PostgreSQL 8.3.7 ( Xeon 1.86GHz x 2、 メモリ 2G ) の環境で
shop 10 万件、holiday 1000 万件で試しました。
shop.shop_id, holiday.shop_id, holiday.holiday に INDEX 張ってます。
5 回くらい explain analyze した結果。
■ IN
select count(shop.shop_id) from shop where shop_id not in (
select shop.shop_id from holiday,shop where shop.shop_id=holiday.shop_id and holiday.holiday = '2009/1/1');
→270ms
■ exsits
select count(s.*) from shop s where not exists (
select s.* from holiday where s.shop_id = holiday.shop_id and holiday.holiday = '2009/1/1');
→cost が IN の 900 倍あって計測中止
- 76 :NAME IS NULL:2009/09/24(木) 15:10:15 ID:???
- select s.*
→
select *
でもおなじかの
- 77 :51:2009/09/24(木) 15:27:56 ID:???
- >>76
同じでしたのう。
何か根本的に間違えているのかな。
- 78 :NAME IS NULL:2009/09/24(木) 21:43:03 ID:???
- >>77
なんでnot inのサブクエリーを改悪する
つかそれでもnot inが900倍も速いのかw
existsのサブクエリのs.*を普通に*とかにしてもホントに遅いままか?
holiday.*とかholiday.shop_idとか1とかにしても遅いままか?
- 79 :NAME IS NULL:2009/09/24(木) 22:24:43 ID:???
- 最近のPostgreSQLでは (NOT) IN は速いよ。
でも900倍は変。
holiday.shop_id や holiday.holidayにインデックス貼ってみたらマシになるかも。
- 80 :NAME IS NULL:2009/09/24(木) 22:28:18 ID:???
- holiday(shop_id,holiday)という複合INDEXがなければnot existsはそんなに
パフォーマンスが出ないというのは想像がつくが、この例ではholiday.shop_idの
holiday.holidayのどっちのINDEXが使われたのかねぇ。
それと、'2009/01/01'を休日に持つshopは10万件のうち何割だったんだろう?
普通に考えて、前者のnot inはshopとholidayのfull scanを1回ずつ、後者の
not existsはshopのfull scanを1回*nested loop joinだから、両方のテーブルが
メモリに収まらないくらい十分大きく、nested loop joinがindex scanできる
条件でならば通常後者のnot existsの方が速いはずだけど。
どっちにしても、せっかくexplainしても実行計画見ないんじゃ何もわからないね。
- 81 :NAME IS NULL:2009/09/24(木) 22:41:13 ID:???
- >>80
テーブルの構成や行数にもよるが、サブクエリでユニークインデクスで検索する場合でも
EXISTS (インデックススキャンをメインテーブル行数回)
より
IN (両テーブルを各1回フルスキャン)
の方が速い場合もある。(つか、あった)
- 82 :NAME IS NULL:2009/09/24(木) 23:01:00 ID:???
- どっちか一方が常に有利なんてことはないんだから、それは別に不思議じゃないと思うが。
- 83 :NAME IS NULL:2009/09/24(木) 23:20:57 ID:???
- >>80
おれはPostgreSQL詳しくないので、特有な癖とかあったらわからんが
もともとnot inは、
>(Holiday,ShopID)で主キーにするなら
って前提だぜ。つまり(Holiday,ShopID)で複合インデックスがあれば
holidayテーブルのフルスキャン必要なくなるはずだ
- 84 :81:2009/09/24(木) 23:31:01 ID:???
- すまん、ちょっと脊髄反射した...orz
- 85 :NAME IS NULL:2009/09/24(木) 23:45:40 ID:???
- >>83
たしかに、holidayが十分選択性が高ければそこでフルスキャンはかかんないね。
その場合shop_idとの複合にする意味はあんまないと思うけど。
- 86 :NAME IS NULL:2009/09/25(金) 00:31:30 ID:???
- >>85
カバードインデックスってPostgreSQLじゃ有効じゃないのか?
- 87 :NAME IS NULL:2009/09/25(金) 04:37:07 ID:???
- not in と not existsだと調査するまでもなく後者の方が速いと思いこんでいた。
勉強が足りないなぁ俺。。。
- 88 :51:2009/09/25(金) 10:31:33 ID:???
- みなさん、いろいろとアドバイスありがとうございます。
>>78
遅いっすね。
>>80
複合 INDEX を張ったら 1/30 になりました!
それでも IN に比べると 30 倍遅いです。
「'2009/01/01'を休日に持つshopは10万件」中 15% です。
explain 結果は分けてポストします。
- 89 :NAME IS NULL:2009/09/25(金) 10:32:25 ID:???
- ■ 複合 INDEX 前の exists
# explain select count(*) from shop s where not exists (
select 1 from holiday where s.shop_id = holiday.shop_id and holiday.holiday = '2009/1/1');
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Aggregate (cost=28065024.77..28065024.78 rows=1 width=0)
-> Seq Scan on shop s (cost=0.00..28064899.76 rows=50003 width=0)
Filter: (NOT (subplan))
SubPlan
-> Bitmap Heap Scan on holiday (cost=276.60..280.62 rows=1 width=0)
Recheck Cond: (($0 = shop_id) AND (holiday = '2009-01-01'::date))
-> BitmapAnd (cost=276.60..276.60 rows=1 width=0)
-> Bitmap Index Scan on index_holiday_shop_id (cost=0.00..5.88 rows=71 width=0)
Index Cond: ($0 = shop_id)
-> Bitmap Index Scan on index_holiday_holiday (cost=0.00..270.47 rows=14550 width=0)
Index Cond: (holiday = '2009-01-01'::date)
- 90 :NAME IS NULL:2009/09/25(金) 10:33:08 ID:???
- ■ 複数 INDEX 後の exists
( vacuum full analyze してます )
# explain select count(*) from shop s where not exists (
select 1 from holiday where s.shop_id = holiday.shop_id and holiday.holiday = '2009/1/1');
QUERY PLAN
-----------------------------------------------------------------------------------------------------------
Aggregate (cost=938409.27..938409.28 rows=1 width=0)
-> Seq Scan on shop s (cost=0.00..938284.26 rows=50003 width=0)
Filter: (NOT (subplan))
SubPlan
-> Index Scan using index_holiday_shop_id_holiday on holiday (cost=0.00..9.37 rows=1 width=0)
Index Cond: (($0 = shop_id) AND (holiday = '2009-01-01'::date))
- 91 :NAME IS NULL:2009/09/25(金) 10:34:18 ID:???
- ■ in
# explain select count(shop.shop_id) from shop where shop_id not in (
select shop.shop_id from holiday,shop where shop.shop_id=holiday.shop_id and holiday.holiday = '2009/1/1');
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Aggregate (cost=36525.88..36525.89 rows=1 width=4)
-> Seq Scan on shop (cost=34610.79..36400.87 rows=50003 width=4)
Filter: (NOT (hashed subplan))
SubPlan
-> Hash Join (cost=3459.70..34574.27 rows=14609 width=4)
Hash Cond: (holiday.shop_id = public.shop.shop_id)
-> Bitmap Heap Scan on holiday (cost=278.57..30593.96 rows=14609 width=4)
Recheck Cond: (holiday = '2009-01-01'::date)
-> Bitmap Index Scan on index_holiday_holiday (cost=0.00..274.91 rows=14609 width=0)
Index Cond: (holiday = '2009-01-01'::date)
-> Hash (cost=1540.06..1540.06 rows=100006 width=4)
-> Seq Scan on shop (cost=0.00..1540.06 rows=100006 width=4)
- 92 :51:2009/09/25(金) 10:38:00 ID:???
- 5 回くらい実行した explain analyze 結果。
in → 268ms
exists → 780ms
INDEX は下記。
・shop(shop_id)
・holiday(holiday)
・holiday(shop_id)
・holiday(shop_id, holiday)
こんな感じです。複合 INDEX をすっかり忘れていました。
やはり in がずっと成績がいいですね。
- 93 :NAME IS NULL:2009/09/25(金) 10:55:28 ID:???
- >>92
だから、なんでnot inのサブクエリにshopテーブルが必要なんだ?
わざわざ改悪して速度調査ってなんなの?馬鹿なの?本気で馬鹿なの?
なんでおそらく最速になるであろう方法をためさないの?
ちゃんとnot inのサブクエリ直してholiday(holiday,shop_id) に
インデックはった上で実行した結果がみたいぞ
- 94 :62:2009/09/26(土) 07:00:08 ID:JyUvDari
- >>62
62ですが、解決しました。phpmyadminで確認したら、sjisで設定してありました。
utf-8に設定しなおして、文字化け、なくなりました。
初めての掲示板、ちっぽけな事ですが、私にとっては、ビッグニュースです。
mysqlとphp、これから猛勉強して、はまります。
- 95 :NAME IS NULL:2009/09/28(月) 21:05:35 ID:???
- MySQL 5.1
週間日付テーブルがあります
week_tbl
w_sdate 週初日付
w_edate 週末日付
〜
で、ある日付を元にそれが属している週のデータを知りたい。
例えばその日付が '2009-09-28'だとすると、
select w_sdate,w_edate from week_tbl
where w_sdate < '2009-09-28' and
'2009-09-28' < w_edate;
で良いのですが、この日付の部分を他のsqlで持って来よう
とする場合、どのように書けばいいのでしょうか?
- 96 :NAME IS NULL:2009/09/28(月) 21:57:27 ID:???
- >>95
こういうこと?
select w_sdate, w_edate
from week_tbl, (select ほげほげ from ふがふが)
where w_sdate < ほげほげ
and ほげほげ < w_edate;
しかし週の初めと終わりを取りたいだけなら
select ほげほげ - interval dayofweek(ほげほげ) - 1 day,
ほげほげ + interval 7 - dayofweek(ほげほげ) day
from (select ほげほげ from ふがふが)
みたいな感じでいいような。
- 97 :95:2009/09/28(月) 22:26:06 ID:???
- >>96
すんません、教えてください(アセ
日付は
select max(in_date) from data_dailytbl
where code = 9999;
で出すmax(in_date)を元にしたいんですが、そのsqlにはどうあてはめれば
よろしいのでしょうか?
- 98 :NAME IS NULL:2009/09/29(火) 00:11:39 ID:???
- これじゃいかんか?
select a.w_sdate,a.w_edate from week_tbl a,
(
select max(in_date) as maxdate from data_dailytbl
where code = 9999;
) as b
where a.w_sdate < b.maxdate and
b.maxdate < a.w_edate;
- 99 :NAME IS NULL:2009/09/29(火) 06:47:26 ID:???
- >>98
9999;の";"を取り除いて動作しました。
ありがとうございました m(_ _)m
- 100 :NAME IS NULL:2009/10/01(木) 08:33:30 ID:???
- 失礼します
独習SQLのP67に書いてあるのですが、「WK_仕入先」テーブルに「仕入先テーブルの行を挿入する(テーブルのデータを別のテーブルにコピーする)」とあるのですが、
@CREATE TABLE WK_仕入先 (仕入先コード NUMBER(5), 仕入先名 CHAR(20) )
と
ACREATE TABLE WK_仕入れ先 AS SELECT * FROM 仕入先 WHERE 1 = 2
が同じとあります
それで分からない事があるのですがAの最後の部分、【WHERE 1 = 2】の部分の 1 = 2とは何を意味しているのでしょうか?
仕入価格 = 12000とかならば分かるのですが、1 = 2 というのは抽象的過ぎて何をやっているのかが分かりません
すみませんがご回答いただければと思います
- 101 :NAME IS NULL:2009/10/01(木) 09:45:29 ID:???
- 抽象的な訳じゃなくて、面食らっただけじゃないのかな
1と2は同じではないので、抽出結果は常に0件になる
ただ、WK_仕入れ先を作るために必要なカラム情報は取れる
- 102 :NAME IS NULL:2009/10/01(木) 16:07:29 ID:???
- >>101
はい、面食らいました
未だに意味は分かっていないのですが、コレは特に意味の無い表記なのでしょうか?
ただ@の仕入先コードや仕入先名のようなカラム情報を得たいが為だけに記入されているのでしょうか?
この1や2が何を意味するのかも見当もつきません・・・
- 103 :NAME IS NULL:2009/10/01(木) 16:46:36 ID:???
- 1は数字の1、2は数字の2 そのままの意味
1と2を比べれば等しくないのでその条件は不成立となる
かならず不成立となる条件として書いてあるだけ
- 104 :NAME IS NULL:2009/10/01(木) 17:21:45 ID:???
- >>103
説明有難うございました
- 105 :NAME IS NULL:2009/10/02(金) 14:44:20 ID:aRTkE45u
- OracleとAccess(JetやSQL Server)はどちらがいいのでしょうか?
自分、まだ全然良く分かっていない初心者なのですが、最初からずっと使うであろう方を学んで使い続けたいと思っているのですが
本屋でパッと見たところSQLServerの本が多かったように思えますが、Oracleの方が有名な気がします
どのような違いがあって、どちらがいいのか教えていただけたらと思います
- 106 :NAME IS NULL:2009/10/02(金) 15:00:56 ID:???
- >>105
どちらも体験版というか、ExpressEditionはある。ただ、SQLServerの方が判り易い(と俺は思う)
どちらを選ぶにしろ、解説本を読んで自分のPCで試してみたら?
OracleはOS毎にあるけど、SQLServerは当然のことながらWindows用しかない。
けど、今のレベルではそんなの関係ないだろ?
どちらで勉強しても基本的な所をしっかり押さえれば、大丈夫だと思うけどね。
- 107 :NAME IS NULL:2009/10/02(金) 21:33:49 ID:???
- ほげ台帳
--------
ほげ名 テキスト
担当1コード 数値
担当2コード 数値
担当3コード 数値
担当者テーブル
----------
コード オートナンバー
氏名 テキスト
これを
----------
ほげ名
担当1氏名(ほげ台帳.担当1コード=担当者テーブル.コードになる担当者テーブル.氏名)
担当2氏名(ほげ台帳.担当2コード=担当者テーブル.コードになる担当者テーブル.氏名)
担当3氏名(ほげ台帳.担当3コード=担当者テーブル.コードになる担当者テーブル.氏名)
という形にするにはどうすれば良いでしょうか?
環境はAccessです。
- 108 :NAME IS NULL:2009/10/02(金) 22:20:56 ID:???
- >>107
select T1.ほげ名,
T2.氏名 as 担当1氏名,
T3.氏名 as 担当2氏名,
T4.氏名 as 担当3氏名
from ほげ台帳 T1
inner join
担当者テーブル T2
on T1.担当1コード = T2.コード
inner join
担当者テーブル T3
on T1.担当2コード = T3.コード
inner join
担当者テーブル T4
on T1.担当3コード = T4.コード
Accessでどう書くかは知らない
- 109 :NAME IS NULL:2009/10/02(金) 22:31:54 ID:RteXPf/F
- >>105
インストール後、使えるようになるまではSQL Server の方が少し楽な気がする
OracleXEは分かってる人が使うものって感じかなぁ>個人的な意見
Webのマニュアル(英語版)位しかないよ>出た時ね
今本はあった気がするけど、内容は見たことがないので
#保守契約ないと、パッチ手に入れられないから、業務には使いづらいし
#SQLServerは、一応SPはでるからね
最初は「現場で使えるSQL 第2版」が個人的にお勧め(両方対応してるし)
#10g、2005対応だけどね
Accessは悪くはないけど、最初に触るものとしては、薦めたくないな・・
最初にSQLをちゃんと使うことを覚えて欲しいと思うから
- 110 :NAME IS NULL:2009/10/02(金) 22:49:08 ID:???
- .NET やるなら SQL Server で。
- 111 :NAME IS NULL:2009/10/03(土) 01:12:59 ID:???
- SQL Serverはあまり使ったこと無いけど、ホスト言語も含めた開発環境で変な癖がつかないか?
MSにどっぷりはまるのなら別にいいけど、ここに書かれる質問で、SQL側とホスト言語側の
切り分けが出来ていない物がたまに見受けられる。
ま、問題の切り分けが出来ない人はMS絡みに限ったことじゃないし、SQL Serverも含め
MSに対して他意はない。
- 112 :NAME IS NULL:2009/10/03(土) 01:46:14 ID:???
- .NETとMSSQLが相性いいのは間違いないだろ。
ORMapperにLINQtoSQL使ってみなさいよ。
- 113 :NAME IS NULL:2009/10/03(土) 03:07:05 ID:???
- 切り分けができてないだけなのか、がんばればSQLで解決できるのかもしれないと思っているのか
その判断が俺にはできないわ。
- 114 :NAME IS NULL:2009/10/03(土) 07:49:05 ID:jYp+tLjS
- >>111
>ホスト言語も含めた開発環境で変な癖がつかないか?
あまり無いと思うよ>普段はSQL鯖使い
Linuxから、アクセスするときはFreeTDS使うけど、後はあまり無いんじゃね?
Oracleと比較しても、そう変わらん気がする
#pl/sqlと比べてストアドがかなり弱い気がするけど
パフォチュー関係の情報があまりでてきてないくらいかな
- 115 :111:2009/10/03(土) 09:52:16 ID:???
- 相性がいいから癖がついちゃうとか。
SQLの中に割り当てるホスト言語の変数を埋め込んだままとか、
ホスト言語の一文そのままここに晒されても、とかって思うときがあった。
俺の偏見かな。
一応俺も.NET(C#)使うけど、LINQはまだだし、.NET+DBって機会がろくにないな。
やりたいんだけど、誰か仕事クレw
- 116 :NAME IS NULL:2009/10/03(土) 18:04:22 ID:???
- >>108
Accessではこんな感じで出来ました、ありがとうございます
見かけのフィールド名(担当1〜3氏名)については、プロパティで設定したためSQLにはありません
select ほげ台帳.ほげ名, T1.氏名, T2.氏名, T3.氏名
from ((ほげ台帳
inner join 担当者テーブル as T1 on ほげ台帳.担当1コード = T1.コード)
inner join 担当者テーブル as T2 on ほげ台帳.担当2コード = T2.コード)
inner join 担当者テーブル as T3 on ほげ台帳.担当3コード = T3.コード;
- 117 :NAME IS NULL:2009/10/03(土) 20:47:59 ID:???
- 116の追記ですが、最終的にはLEFT JOINになりました。
第二、第三担当がNULLの場合に対応するためです。
- 118 :NAME IS NULL:2009/10/03(土) 21:41:20 ID:???
- ___
,r' `ヽ、
,i" ゙;
!.(●) (●),!
ゝ_ _,r''
/ ;;;;;; ・・ ;;;;) <それは報告しなくてもいいです。
/ (_
| f\ トェェェイノ  ̄`丶.
| | ヽ__ノー─-- 、_ )
. | | / /
| | ,' /
/ ノ | ,'
/ / | /
_ノ / ,ノ 〈
( 〈 ヽ.__ \
ヽ._> \__)
- 119 :NAME IS NULL:2009/10/04(日) 01:55:14 ID:???
- mysql 5.1.37
(問)
[groupテーブル]
group_id | group_name
---------+-----------
g1 | グループ1
g2 | グループ2
g3 | グループ3
[belongテーブル]
group_id | user_id | status
---------+---------+------
g1 | u1 | 1
g2 | u2 | 0
g2 | u3 | 1
g2 | u4 | 1
このようなテーブルから、下記のように
group_name | user_count
-----------+-----------
グループ1 | 1
グループ2 | 2
グループ3 | 0
各グループ毎の「belong.status = 1」の所属ユーザ数を取得したいです。
以下のようなsql文を考えてみましたが、
SELECT group.group_name as group_name, count(belong.user_id) as user_count
FROM group left join belong on group.group_id = belong.group_id
WHERE belong.status = '1'
GROUP BY belong.group_id
group_name | user_count
----------+-----------
グループ1 | 1
グループ2 | 2
と、グループ3に対してデータを取得することができませんでした...orz...
※外部結合している為、「belong.status = '1'」の部分で…
なにか良い方法はないでしょうか?
- 120 :NAME IS NULL:2009/10/04(日) 01:57:26 ID:???
- グループ化した結果を、group テーブルに LEFT JOIN。
- 121 :119:2009/10/04(日) 02:05:58 ID:???
- >> 120
レスありがとうございます。
アドバイスして頂いた内容ですが、「サブクエリを使って…」と
解釈しましたが、問題ないでしょうか?
できれば、サブクエリを使わない方法で取得したいのです。
- 122 :119:2009/10/04(日) 02:39:28 ID:???
- >>120
アドバイスして頂いたことを元に、
SELECT
group.group_id,
group.group_name,
IFNULL(count_table.user_count, 0) as user_count
FROM
group left join
(SELECT group_id, count(*) as user_count FROM belong WHERE status='1' GROUP BY belong.group_id) as count_table
on group.group_id = count_table.group_id
と、sqlを発行することで、取得することができました。
やはり、サブクエリをつかってしか取得することはできないのでしょうか?
『サブクエリを使用すると、レスポンスが悪くなる』
と、聞いたことがあり、なるべくなら、使用したくありません。
※今回の場合、上記sqlを発行すると、都合、2回、sqlが発行されることになると思います。
- 123 :NAME IS NULL:2009/10/04(日) 03:57:37 ID:???
- SELECT group.group_name as group_name, count(belong.user_id) as user_count
FROM group left join belong on group.group_id = belong.group_id
GROUP BY belong.group_id, belong.status
HAVING belong.status = '1'
- 124 :NAME IS NULL:2009/10/04(日) 04:14:30 ID:???
- サブクエリなしのSQL(笑)
- 125 :NAME IS NULL:2009/10/04(日) 05:14:07 ID:???
- SELECT group.group_name as group_name, sum(case when belong.status is null then 0 else 1 end) as user_count
FROM group left join belong on group.group_id = belong.group_id
GROUP BY belong.group_id, belong.status
HAVING belong.status = '1' or belong.status is null
グループ3を0人と出すならこうかな。
- 126 :NAME IS NULL:2009/10/04(日) 07:02:54 ID:???
- >>123,125
アドバイスして頂き、ありがとうございます。
アドバイスして頂いた中にあった「case句」を使うことで取得することができました。
SELECT
group.group_id as group_id,
group.group_name as group_name,
CASE WHEN belong.status IS NULL THEN 0 ELSE COUNT(belong.user_id) END user_count
FROM
group left join belong on group.group_id = belong.group_id
WHERE
belong.status = '1' OR belong.status IS NULL
GROUP BY
group.group_id
>>123,125
少し気になったのですが、アドバイスして頂いたsql文で
>GROUP BY belong.group_id, belong.status
と、「belong.group_id」にて、GROUP BYされていますが、これは、「group.group_id」の
間違いではないでしょうか?
- 127 :119:2009/10/04(日) 08:21:47 ID:???
- >>126のsqlでもダメでした。
【ダメな理由】
belongテーブルに「belong.status」が'0'のレコードのみ存在する場合、
対応するgroupテーブル中のレコードが表示されない。
[groupテーブル]
group_id | group_name
---------+-----------
g1 | グループ1
g2 | グループ2
g3 | グループ3
[belongテーブル]
group_id | user_id | status
---------+---------+------
g1 | u1 | 0
g2 | u2 | 0
g2 | u3 | 1
g2 | u4 | 1
[取得したい結果]
group_name | user_count
----------+-----------
グループ1 | 0
グループ2 | 2
[取得される結果]
group_name | user_count
----------+-----------
グループ2 | 2
もう少し、考えて見ます。m(_ _)m
- 128 :NAME IS NULL:2009/10/04(日) 11:03:48 ID:???
- テーブルAにdatetime型のカラムがあり、select結果として
date_split_by_year
--------------┤
y/m/d h:m:s 1 |
y/m/d h:m:s 2 |
y/m/d h:m:s 3 |
y/m/d h:m:s 4 |
y/m/d h:m:s 5 |
y/m/d h:m:s 6 |
y/m/d h:m:s 7 |
: |
: |
y/m/d h:m:s N |
y/m/d h:m:s 1 = テーブルAの最小年月日(Minで取得?)
y/m/d h:m:s 2〜N-1 = y/m/d h:m:s 1 に 1年ずつ加算していった年月日
y/m/d h:m:s N = 現在日時
という風に取得結果を取りたいのですが、どうすれば良いでしょうか?
おそらく問題は、y/m/d h:m:s 1とy/m/d h:m:s Nの値が常に変動するので
Nの数が決まっていないということです。
先生方よろしくお願いしますm(_ _)m
- 129 :NAME IS NULL:2009/10/04(日) 11:05:02 ID:???
- DBはSQL Server 2005 SP2 です
- 130 :NAME IS NULL:2009/10/04(日) 11:14:57 ID:???
- もう少し具体的に。row_number() 使えばいいだけの話にも見える。
- 131 :NAME IS NULL:2009/10/04(日) 11:21:25 ID:???
- テーブルに有る訳でもないレコードを取ってくるとか
自分ならわざわざSQLでやらないなぁ
- 132 :NAME IS NULL:2009/10/04(日) 11:40:17 ID:???
- ありがとうございます。
具体的にご説明しますと、
@[テーブルA]
code_id | updt_time
------------+--------------------
code1 | 2003/01/01 00:00:00
code2 | 2004/07/01 12:30:00
code3 | 2005/07/01 22:00:00
現在日時 2009/10/04 11:20 にクエリ実行
[結果]
date_split_by_year
--------------------┤
2003/01/01 00:00:00 |
2004/01/01 00:00:00 |
2005/01/01 00:00:00 |
2006/01/01 00:00:00 |
2007/01/01 00:00:00 |
2008/01/01 00:00:00 |
2009/01/01 00:00:00 |
2009/10/04 11:20:00 |
---------------------
A6年後テーブルAに削除がかかっていたとして
[テーブルA]
code_id | updt_time
------------+--------------------
code2 | 2004/07/01 12:30:00
code3 | 2005/07/01 22:00:00
6年後 現在日時 2015/10/04 11:20 に再度クエリ実行
[結果]
date_split_by_year
--------------------┤
2004/07/01 12:30:00 |
2005/07/01 12:30:00 |
2006/07/01 12:30:00 |
2007/07/01 12:30:00 |
2008/07/01 12:30:00 |
2009/07/01 12:30:00 |
2010/07/01 12:30:00 |
2011/07/01 12:30:00 |
2012/07/01 12:30:00 |
2013/07/01 12:30:00 |
2014/07/01 12:30:00 |
2015/07/01 12:30:00 |
2015/10/04 11:20:00 |
---------------------
といった取得結果にしたいです。
>>131
素直にテーブルAから最小日時をとって、コードで(開発言語はVB6.0です)
1年ずつ足して配列に格納とするほうが自然でしょうか。
意図としてはクエリ一発でできればやってしまおうー!と思ったしだいです。
ですが不自然なコードは今後のメンテナンスのためにも書くことは避けたいので、
そのやりかたは変だとあれば、この案はあきらめたいと思います。
- 133 :NAME IS NULL:2009/10/04(日) 11:42:56 ID:???
- 俺ならストアドにして終わり、だな。
- 134 :NAME IS NULL:2009/10/04(日) 16:10:50 ID:???
- ストアドかアプリかな
- 135 :NAME IS NULL:2009/10/04(日) 18:29:15 ID:???
- DBに存在しない値をSQLで生成するという考え方がおかしい
どうしてもクエリ1発でやりたかったらストアド書け
- 136 :NAME IS NULL:2009/10/04(日) 23:05:08 ID:???
- SELECT A.風, A.林, B.火, B.山
FROM 南斗 A, 北斗 B
WHERE A.風 = B.風
AND A.風 IN ( SELECT C.風 FROM 北斗 C WHERE 山 >= 10000 )
すみません、このテーブル結合が分かりません
何故、「北斗(テーブル) B」があるのに、INの後に「北斗(テーブル) C」という記述があるのでしょうか?
同じ北斗テーブルなのにBというのとCと言う風に分けられていて、このテーブルBとテーブルCの違いは何なのでしょうか?
- 137 :NAME IS NULL:2009/10/04(日) 23:14:14 ID:???
- 書いた奴に聞けよ。
- 138 :136:2009/10/04(日) 23:36:01 ID:???
- やはり書いた人間の意図によって分けられているだけなのですか・・・
では、すみませんがこの点を教えて下さい
上記のように北斗テーブルをBに設定しているのに、また別にCに設定すると言うことは出来るのでしょうか?
- 139 :NAME IS NULL:2009/10/04(日) 23:37:03 ID:???
- できるよ。
- 140 :NAME IS NULL:2009/10/04(日) 23:45:55 ID:???
- 使い道はもちろんあるんだよ。
社員が給与振込口座を複数持つことが出来て、
銀行マスタをいくつも結合する場合、とか。
- 141 :136:2009/10/04(日) 23:54:33 ID:???
- >>139
分かりました、有難うございます
>>140
具体的に例を挙げていただき有難うございます
で、今思いついたのですが、自分の考えとしては、>>136はおそらくBのまま使うと、山>=100000の条件が出てこないからかなと思いました。
BはAとの関連付けだけに設定し、CはBの中のC条件だけをAに付加すると言う意図で別に設定したのかな、と。
このような考えで宜しいのでしょうか?
- 142 :NAME IS NULL:2009/10/04(日) 23:57:26 ID:???
- これってサブクエリー使う意味あんの?
SELECT A.風, A.林, B.火, B.山
FROM 南斗 A, 北斗 B
WHERE A.風 = B.風
AND B..山 >= 10000
でいいと思うんだけど。
- 143 :NAME IS NULL:2009/10/05(月) 00:10:41 ID:???
- うん。それでいい。
みんないじわるして教えなかっただけで。
- 144 :NAME IS NULL:2009/10/05(月) 01:09:50 ID:???
- 常にそうとも言えないのではないだろうか。
- 145 :NAME IS NULL:2009/10/05(月) 01:24:18 ID:???
- サブクエリで抽出してるのが風で、WHERE句の1つ目の条件が風なんだからこの場合は同じだよ。
- 146 :NAME IS NULL:2009/10/05(月) 01:34:30 ID:???
- 同じだねごめん
- 147 :NAME IS NULL:2009/10/05(月) 03:36:21 ID:???
- 普通に考えれば>>142で行けるだろうなぁ
セレクトリストに存在しない項目はWHERE条件に書けない、みたいな制約の
あるDBMSとか存在してるのかも
集約関数あるとGROUP BYに無い項目使うと怒られる、みたいな
もしくは、結合条件でNULL=NULLを真とみなすDBMSとか
- 148 :NAME IS NULL:2009/10/06(火) 09:04:06 ID:1YwLzITZ
- >集約関数あるとGROUP BYに無い項目使うと怒られる
仕様上はこれが正しい(らしい)のだが
MySQL以外にあるの?
- 149 :NAME IS NULL:2009/10/06(火) 12:18:48 ID:???
- 普通はNG
- 150 :NAME IS NULL:2009/10/06(火) 12:34:29 ID:???
- 誤読だな。
- 151 :NAME IS NULL:2009/10/08(木) 11:06:45 ID:???
- すいません、教えてください。
・Oracle10gR2
・CREATE TABLE test (col_a varchar2(10);)
・PL/SQL記述の動的SQLで文字列の検索を正常に行いたい
・考えてみたSQL
declare
w_sql varchar2(1000);
w_wrk varchar2(10);
begin
w_wrk := 'aaa';
w_sql := 'update test set col_a = ''更新'' where col_a = :wrk';
execute immediate w_sql using w_wrk
end;
通常のSQLでSQLを書くと「update test set col_a = ''更新'' where col_a = 'aaa'」
質問内容:
col_aは文字列なので通常であれば右辺を'aaa'とするべきですが、
動的SQLでは上記のように書くことになる、もし'をつけたくて
w_sql := 'update test set col_a = ''更新'' where col_a = '':wrk''';
と書くと、バインドされなくなっている気がする。
ここはどう書くべきです?
ここを読んでみたけどよくわからない・・・。
ttp://www.shift-the-oracle.com/plsql/native-dynamic-sql.html
- 152 :NAME IS NULL:2009/10/08(木) 12:09:53 ID:???
- ストアド、PL/SQLはスレ違いじゃないかな
- 153 :NAME IS NULL:2009/10/08(木) 12:22:28 ID:???
- スレチすいません。どこかわからず・・・誘導お願いします。
- 154 :NAME IS NULL:2009/10/08(木) 13:03:42 ID:???
- >>153
http://pc11.2ch.net/test/read.cgi/db/1250995281/
- 155 :NAME IS NULL:2009/10/10(土) 02:01:42 ID:KRCSZ/Pg
- SELECT
(SELECT DISTINCT 'X' FROM B WHERE EXISTS (SELECT 'X' FROM B WHERE A.ID = B.ID)
FROM A
SELECT
(SELECT MAX ('X') FROM B WHERE EXISTS (SELECT 'X' FROM B WHERE A.ID = B.ID)
FROM A
SELECT
(SELECT COUNT ('X') FROM B WHERE A.ID = B.ID)
FROM A
最も速いのはどれ?
- 156 :NAME IS NULL:2009/10/10(土) 02:27:49 ID:???
- なにがしたいんだろう。
とりあえず実行計画みてみたら。
- 157 :NAME IS NULL:2009/10/11(日) 09:38:51 ID:???
- MS SQLServerではupdate table set col1 = value from table A where A.col1 = value2のようにsetの後ろにfrom句が書けるけど、これって標準SQLなのかな?
他dbmsではどう?
- 158 :NAME IS NULL:2009/10/11(日) 10:17:12 ID:???
- >>155
それ3つとも動くのか?
- 159 :NAME IS NULL:2009/10/11(日) 11:27:12 ID:???
- >>157
標準SQLじゃない
他のDBMSで書けるかどうかは>>2
- 160 :NAME IS NULL:2009/10/11(日) 19:06:57 ID:???
- >>159
thx。
- 161 :NAME IS NULL:2009/10/15(木) 22:07:42 ID:???
- 【質問テンプレ】
・DBMS名とバージョン
Microsoft Access 2000
・テーブルデータ
支店テーブル
ID | DATA
--+----------+-----
1 | 東京センター
2 | 大阪支店
3 | 名古屋△センター
4 | 福岡△博多△センター
※△は全角スペース
・やりたいこと
スペースを二つ以上含むデータの抽出
このテーブルに対して
SELECT * FROM 支店テーブル WHERE TRIM(DATA) LIKE '*△*△*';
というSQLを実行したところ
4番だけでなく3番のデータも抽出されてしまいました。
別の方法で目的は達成したのですが
なぜ、3番のデータも抽出されてしまったのか教えていただきたいです。
ちなみに
SELECT * FROM 支店テーブル WHERE TRIM(DATA) LIKE '*△';
でも同じ結果がでました。
よろしくお願いします。
- 162 :NAME IS NULL:2009/10/15(木) 22:44:57 ID:???
- Trimして試してみて。
- 163 :161:2009/10/17(土) 11:31:13 ID:???
- >>162
WHERE TRIM(DATA) LIKE '*△*△*'
としてるんですが、後はどこにいれるんでしょうか。
- 164 :NAME IS NULL:2009/10/17(土) 11:57:37 ID:???
- ああ、もうしてたのか。
- 165 :NAME IS NULL:2009/10/17(土) 18:52:23 ID:???
- スペースだからなのかな
'*屋*屋*'だと3は取れるの?
- 166 :NAME IS NULL:2009/10/17(土) 19:40:03 ID:???
- 想像するに全角と半角が区別されずに判定されてるのかもね。
replaceで置き換えるかなんかして工夫が必要かも。
- 167 :161:2009/10/18(日) 09:22:12 ID:???
- >>165-166
Accessが会社にしかないので月曜日に試してみます。
- 168 :NAME IS NULL:2009/10/18(日) 17:14:03 ID:???
- MicrosoftSQL Server2005 を使ってます。
とある鯖用のデータベースなのですが、手元にあるLevelList.sqlというスクリプトを使ってそれをaccountdbのテーブルにしろと言われました。
初心者なものでどうやるのかが全くわかりません。
どなたか教えていただけないでしょうか。
http://up3.viploader.net/net/src/vlnet000528.png
- 169 :NAME IS NULL:2009/10/18(日) 17:19:51 ID:???
- >>168
スレ違い
- 170 :NAME IS NULL:2009/10/18(日) 21:32:46 ID:???
- LevelList.sqlを実行すればいいだけじゃ?
- 171 :NAME IS NULL:2009/10/19(月) 20:26:06 ID:FLpLj6wo
- おねがいします。
テーブルT1、T2があります。
T1には、[ID1] [ID2] [データ名]フィールドがあり、
T2には、[ID3] [日付]フィールドがあります。
ID1とID2の連結した値が、ID3に含まれていれば、日付とデータ名を抜き出すように
SELECT T1.データ名,T2.日付
From T1,T2
Where T1.ID1 + T1.ID2 = T2.ID3
としています。
ここにさらに、
日付が存在しない場合、
日付フィールドを空の状態で
全てのデータ名フィールドを表示させたいのですが、
どうすればよいのでしょうか。
出来るだけアクションクエリを利用せずに作成したいです。
- 172 :NAME IS NULL:2009/10/19(月) 22:15:27 ID:???
- >>171
DB何かくらい書いたら?
でアクションクエリって何?
INSERTとかUPDATEのことか?
- 173 :NAME IS NULL:2009/10/19(月) 22:18:55 ID:???
- 失礼しました。
access2003を使っています。
はい、更新クエリや挿入クエリで複数のクエリを作ることを出来るだけ避けたいと思っています。
不一致クエリと選択クエリを結合させると実現は出来たのですが、
非常に効率が悪いとかんじていたので、他に手段がないかと考えています。
- 174 :NAME IS NULL:2009/10/19(月) 22:34:52 ID:???
- 外部結合すればいいだけのように思うけど、それをaccess2003でどう書くかは知らない
- 175 :NAME IS NULL:2009/10/19(月) 22:49:36 ID:FLpLj6wo
- 外部結合で実行は出来るのですが、全外部結合をアクセスがサポートしてないようで、
最低4つはクエリが必要ということなのです。
おとなしく4つ作るべきでしょうか・・
- 176 :NAME IS NULL:2009/10/19(月) 22:55:01 ID:???
- 何で4つ?日付が存在しないだけなら
T1 left join T2 on T1.ID1 + T1.ID2 = T2.ID3
where T2.ID3 is null
でいいじゃん
- 177 :NAME IS NULL:2009/10/19(月) 22:55:36 ID:???
- >>171
とりあえず用語が曖昧でやりたいことがいまいち伝わらない。
具体例をあげて説明してみてはどうでしょ。
- 178 :NAME IS NULL:2009/10/19(月) 23:06:36 ID:???
- 説明に不自由ですいません。
明日一度見直した後、改めて整理したものを書きますね。
すいません、自分でもいまいちどうしたいか理解できていない気がします。
- 179 :NAME IS NULL:2009/10/19(月) 23:10:06 ID:???
- ああ、全外部結合がしたいのか・・・(って>>171に書いてることとかなり違う気もするけど)
accessだったら確かにできないから右外部結合のクエリと左外部結合のクエリを
UNIONでくっつけるしかないと思うよ
- 180 :161:2009/10/19(月) 23:18:25 ID:???
- >>165
とれないですねー
>>166
M$だからってことで結論づけたほうがいいかもしれませんね(汗
みなさん、ありがとうございました。
- 181 :NAME IS NULL:2009/10/19(月) 23:49:32 ID:???
- >>171
SELECT T1.データ名,T2.日付
From T1 LEFT JOIN T2 ON T1.ID1 + T1.ID2 = T2.ID3
でいいんじゃないの?
- 182 :NAME IS NULL:2009/10/20(火) 18:17:47 ID:NX+GWuNh
- 【質問テンプレ】
・DBMS名とバージョン
MySQL 5.x
・テーブルデータ
会員マスタテーブル
IDがユニークキーです。
ID | 登録日 | 退会日
--+----------+-----
1 | 2009-08-15 2009-09-10
2 | 2009-09-12 2009-10-10
3 | 2009-09-28 2006-01-01
4 | 2009-10-01 2006-01-01
5 | 2009-10-17 2006-01-01
・やりたいこと
現在月(CURRENT_DATE)までを対象にして、各月毎の登録者が何人いて
その月の登録者が現在月までの各月(当月を含む)で何人が退会したのか、そして何人が
退会していないで残存しているのか抽出したい。
※退会日の 2006-01-01は退会していない事を表しています
※現在月は10月とします。
・希望する結果
8月の登録数が1件、当月の退会が0件、一か月後の退会が1件、残存数が0件
9月の登録数が2件、当月の退会が0件、一か月後の退会が0件、残存数が1件
10月の登録数が2件、当月の退会が0件、一か月後の退会が0件、残存数が2件
色々と考えたのですがさっぱり回答が分からないです。
どなたか教えて頂けませんか。
よろしくお願いします!
- 183 :NAME IS NULL:2009/10/20(火) 18:25:53 ID:???
- 分けなさいな。
- 184 :182:2009/10/20(火) 19:13:49 ID:???
- 一発で取得するのが難しくてSQLを分けるにしても
せめて現在月までの各月に対して1回ずつ発行する
みたいな形にできないですかね?
細かく各月毎に対してばんばんSQLを発行したら課題でNG
にされました・・・
- 185 :NAME IS NULL:2009/10/20(火) 19:34:28 ID:???
- select to_char(trunc(登録日, 'MONTH'), 'YYYY/MM') as 月,
count(*) as 登録,
count(case when trunc(登録日, 'MONTH') = trunc(退会日, 'MONTH') then 1 end) as 当月の退会,
count(case when trunc(登録日, 'MONTH') = trunc(add_months(退会日, -1), 'MONTH') then 1 end) as 一か月後の退会,
count(case when 退会日 = '2006-01-01' then 1 end) as 残存
from 会員マスタ
group by trunc(登録日, 'MONTH')
order by trunc(登録日, 'MONTH')
;
日付関数はDBMSによってだいぶ違うのでMySQLの場合は自分で調べて
- 186 :NAME IS NULL:2009/10/20(火) 19:42:15 ID:???
- とりあえず分けて作って(考えて)から連結するとか。
MySQLのdate_trunc関数やinterval型ってどうやるんだっけ、
そこらヘンでこねてやれば一発(つってもサブクエリまみれ)でできるけど。
- 187 :NAME IS NULL:2009/10/20(火) 19:49:47 ID:???
- 一か月後の退会
これは何を指してるんだろう。
> その月の登録者が現在月までの各月(当月を含む)で何人が退会したのか
5月の登録者が6,7,8,9,10月で何人退会したか、という風に読めるので、これは
6月の登録者が7,8,9,10月それぞれの月で何人退会したか
7月の登録者が8,9,10月それぞれの月で何人退会したか
と出さないとダメ?
- 188 :NAME IS NULL:2009/10/20(火) 20:40:59 ID:???
- >>187
それだと1SQLで無理じゃね?
まあそう読み取れるけど。
- 189 :182:2009/10/20(火) 20:41:20 ID:???
- みなさんありがとうございます。
>>187
その通りです。
説明が下手くそですいません。
- 190 :NAME IS NULL:2009/10/21(水) 09:04:15 ID:???
- 質問です。
あるテーブルに登録日と更新日の列があります。
どちらか新しい日付だけ取り出す方法はありますか?
日付が両方ヌル値の場合は最後に表示したいです。
Web画面上に昇順、降順を選択して表示しようと考えています。
宜しくお願いします。
- 191 :190:2009/10/21(水) 12:08:56 ID:???
- 自己解決しました
- 192 :182:2009/10/21(水) 12:52:23 ID:ZbRjCu5t
- んー色々と考えましたが無理でした・・・
せめて登録のあった月から現在月までの月数分SQLを発行
すればなんとかならないですかね?
5月の登録者が10人、5月に登録して5月に退会した人が5人、5月に登録して6月に退会した人が3人、
5月に登録した人の残存数が2人
↑このSQLを5月を基準として現在月まで発行する(現在月を10月とすると計6回発行)
書き込み多くて申し訳ありません。
- 193 :NAME IS NULL:2009/10/21(水) 19:35:53 ID:???
- >>192
とりあえず月別の登録数、残存数と、その月の登録者の月別の退会数がわかれば良いならこんな感じか
select 月別入会.登録年,月別入会.登録月,月別入会.当月入会,残存数,月別退会.所属月数,月別退会.退会数 from
(select YEAR(登録日) as 登録年,MONTH(登録日) as 登録月,COUNT(*) as 当月入会,count( case when 退会日='2006-01-01' then 1 end ) as 残存数 from 会員マスタ group by YEAR(登録日),MONTH(登録日)) as 月別入会
left join
(select YEAR(登録日) as 登録年,MONTH(登録日) as 登録月,YEAR(退会日) as 退会年,MONTH(退会日) as 退会月,((YEAR(退会日)*12+MONTH(退会日))-(YEAR(登録日)*12+MONTH(登録日))) as 所属月数,COUNT(*) as 退会数
from 会員マスタ where 退会日<>'2006-01-01' group by YEAR(登録日),MONTH(登録日),YEAR(退会日),MONTH(退会日)) as 月別退会
on 月別入会.登録年=月別退会.登録年 and 月別入会.登録月= 月別退会.登録月
SQL Serverで作ったんで日付の扱いは適当になんとかしてくれ
入会者が一人もいなかったときの年月はしらん
月別入会と月別退会はViewなり別テーブルなりで作るべきだな
退会日付はなんで退会してないならNULLにしないんだ
これ、なんかの課題なんだとしたら、こんな設計する人間に課題出されたくはないな
- 194 :NAME IS NULL:2009/10/21(水) 20:04:09 ID:???
- NULLにするぐらいなら退会日付テーブル作るべき
それは面倒なので、NULL不可にして、業務上あり得ない過去日を設定した
というのが関の山
- 195 :182:2009/10/21(水) 20:31:11 ID:???
- >>193
ありがとうございます!mysql用に直します
そうです。課題なんですよ。
集計を便利にするために月別入会と月別退会は別テーブルで
作るのが本当の正解の用な気がしました。
課題とは関係ないですが会員マスタを元に月別入会者数と月別退会者数
を別テーブルに分けたデータ構造を考えてみたいと思います。
>>194
その通りだとおもいます。
- 196 :NAME IS NULL:2009/10/21(水) 20:54:13 ID:???
- >>182
おまえら頭固いw
mssqlだけどこれでいいだろ。
登録期間0の人数がやめてない人数、
登録機関1の人数が登録後1ヶ月でやめた人数てなかんじでみてね。
select
t2.入会月,t2.登録期間,COUNT(t2.入会月)AS 人数
from
(
select
DATEPART(MONTH,t.Registdate) AS 入会月,
CASE WHEN DATEDIFF(DAY,t.RegistDate,t.ExitDate)>0
THEN DATEPART(MONTH,t.ExitDate) - DATEPART(MONTH,t.Registdate)
ELSE 0 END AS 登録期間
from SQL9_182 t
)t2
group by t2.入会月,t2.登録期間
- 197 :NAME IS NULL:2009/10/21(水) 21:03:36 ID:???
- >>196
とりあえず年またがりが出来なさそう
- 198 :NAME IS NULL:2009/10/21(水) 21:15:16 ID:???
- おおほんとだな。すっかりぬけてるw
まあやりたいことはわかるだろ。
- 199 :NAME IS NULL:2009/10/21(水) 23:59:16 ID:???
-
ID | 日付 | データ | 更新日
--+----------+-------+----------+
1 | 2008-02-23 | 0 | 2008-12-04 |
2 | 2008-10-21 | 112 | 2009-10-11 |
7 | 2008-12-11 | 10 | 2009-10-11 |
100| 2009-11-10 | 0 | 2009-10-10 |
日付が2008年のデータの大きい方から5件取得し
その5件で更新日が2009年でないものを取得したいのですが
mysqlではサブクリエでlimitが使えないようでエラーが出ます
1回で済ませたいのですがほかに方法はないでしょうか
例:(php5+mysql5)
SELECT *
FROM table1
WHERE id IN (
SELECT id
FROM table1 WHERE
更新日 >= '2008-01-01'
AND 更新日 <= '2008-12-31'
ORDER BY データ DESC limit 5
)
AND 更新日 < '2009-01-01'
- 200 :NAME IS NULL:2009/10/22(木) 00:18:01 ID:???
- >>199
なんかサンプルデータが中途半端なんだが、
その例だと結局ID=1の行だけ抽出できたらいいの?
- 201 :NAME IS NULL:2009/10/22(木) 00:40:19 ID:???
- >>200
はい
- 202 :NAME IS NULL:2009/10/22(木) 02:05:47 ID:???
- >>199
select id, (
select count(*) from table1 as t2
where t2.data > t1.data
and 日付 >= '2008-01-01' and 日付 <= '2008-12-31'
) as rank
from table1 as t1
where rank < 5
and 更新日 < '2009-01-01'
mysql知らないけどこんな感じにできないかなー
- 203 :NAME IS NULL:2009/10/22(木) 02:35:50 ID:???
- SELECT * FROM Table1 AS T1
WHERE (SELECT count(*) FROM Table1 WHERE 日付 BETWEEN '2008-01-01' AND '2008-12-31' AND T1.データ < データ) < 5
AND 更新日 < '2009-01-01';
- 204 :199:2009/10/22(木) 12:53:58 ID:???
- >>202,203
ありがとうございました。
参考になりました
- 205 :182:2009/10/23(金) 11:23:43 ID:8hF/z7x3
- 課題の件ですがみなさんの意見を参考にしてテーブルを
分けてみました。
●入会月別の集計TBL
ID | 年月 | 入会数 |
--+----------+-------
1 | 2009-08 | 30 |
2 | 2009-09 | 20 |
3 | 2009-10 | 15 |
●入会月別の退会者集計TBL
ID | 入会月 | 退会月 |退会数
--+----------+-------+-----
1 | 2009-08 | 2009-08| 10
2 | 2009-08 | 2009-09| 15
3 | 2009-08 | 2009-09| 20
4 | 2009-09 | 2009-09| 5
5 | 2009-09 | 2009-10| 13
6 | 2009-10 | 2009-10| 3
これで8月に入会した人数と8月に入会した人が8月に何人
退会したか9月に何人退会したかを現在年月まで抽出するSQLを
取得したいのですが方法は無いでしょうか?
みなさんよろしくお願いします。
- 206 :NAME IS NULL:2009/10/23(金) 12:12:31 ID:???
- >>205
何の冗談だよこれw
もう集計されちゃってるじゃんw
- 207 :182:2009/10/23(金) 12:39:34 ID:???
- >>206
えっ?!
この二つのTBLを元にこんな結果を抽出するSQLが知りたかった
んですけど変なことしてます?
●入会月別の集計TBL
ID | 年月 | 入会数 |
--+----------+-------
1 | 2009-08 | 30 |
2 | 2009-09 | 20 |
3 | 2009-10 | 15 |
●入会月別の退会者集計TBL
ID | 入会月 | 退会月 |退会数
--+----------+-------+-----
1 | 2009-08 | 2009-08| 10
2 | 2009-08 | 2009-09| 15
3 | 2009-08 | 2009-10| 5
4 | 2009-09 | 2009-09| 5
5 | 2009-09 | 2009-10| 13
6 | 2009-10 | 2009-10| 3
▲抽出したい結果
登録月 |入会数|退会数(当月)|退会数(翌月)|退会数(翌々翌月から現在月まで対象)
--------+------+------------+------------+----------------------------------
2009-08|30 |10 |15 |5
2009-09|20 |5 |13 |0
2009-10|15 |3 |0 |0
- 208 :NAME IS NULL:2009/10/23(金) 13:31:12 ID:???
- 横列固定になったのかな?
「翌々月から現在まで」ってひっくるめるの?
- 209 :NAME IS NULL:2009/10/23(金) 13:47:46 ID:???
- いや、横可変の仕様は変わってないんじゃないかな。
>>196のように行で考える風にしないとダメなのがわかってない。
- 210 :182:2009/10/23(金) 13:57:06 ID:???
- >>208
翌々月から現在までの意味は5月に登録した人が6月以降から現在月
までに退会したかを対象とする意味です。
>>209
何か根本的に分かってないですかね?
頭が固いから横列固定の考えになっているのかもです。
抽出したい結果があっているのならば横列固定とかは問いません・・・
- 211 :NAME IS NULL:2009/10/23(金) 14:10:58 ID:???
- 今月抽出する結果と来月抽出する結果では列数が1つ増えるわけでしょ?
列可変は普通にやったら無理じゃないかな。
- 212 :NAME IS NULL:2009/10/23(金) 15:07:41 ID:NlrCHYmt
- よくある質問1>>4に近いのですが、どうしても上手くいかないので質問させてください。
【質問テンプレ】
・DBMS名とバージョン:MySQL 5.1
・テーブルデータ
テーブルA
A_ID PRIMARY
DATA1
DATA2
DATA3
DATA4
テーブルB
B_ID PRIMARY AUTO_INCREMENT
A_ID
MESSAGE
DATE
・欲しい結果
テーブルAとテーブルBを結合し、以下のように表示させたいです。
A.A_ID (B.A_IDを参照し、テーブルBにあるMESSAGEを反映させたい)
A.DATA1
A.DATA2
A.DATA3
A.DATA4
B.MESSAGE (A.A_ID=B.B_IDと対応させ、NULLの場合はそのままNULLを表示、メッセージが存在する場合はDATEが最新の物のみ表示)
・説明
現在、LEFT JOINでテーブルAとテーブルBを結合した物を表示させ、
テーブルBのMESSAGEにメッセージがあろうとNULLであろうと結合したテーブルの結果をすべて表示し、
GROUP BY A.A_IDで、A.A_IDのエントリーは1つしか表示されないようにしているのですが、
この状態だと、一番古いMESSAGEが表示されてしまいます。
よろしくお願いします。
- 213 :NAME IS NULL:2009/10/23(金) 15:44:05 ID:???
- mysqlの環境がないのでmssql2008
SELECT
A.A_ID,A.DATA1,A.DATA3,A.DATA4,D.DATE,D.MESSAGE
FROM
Table_A A LEFT JOIN
(SELECT B.A_ID, MAX(B.DATE)AS DATE FROM Table_B B GROUP BY B.A_ID) AS C
ON A.A_ID = C.A_ID
INNER JOIN Table_B D ON C.A_ID = D.A_ID AND C.DATE = D.DATE
エイリアエスのつけ方はてきとう。
Joinもきれいじゃないけど参考程度に。
- 214 :NAME IS NULL:2009/10/23(金) 15:58:44 ID:NlrCHYmt
- >>213
ありがとうございます。
書かれたコードを参考にSQL文を入力しているのですが、Table_A A、Table_B Dとは何を指すのでしょうか?
- 215 :NAME IS NULL:2009/10/23(金) 16:01:49 ID:???
- 別名定義。エイリアス。
長いテーブル名なんかを短縮して書けると便利だと思わない?
- 216 :NAME IS NULL:2009/10/23(金) 16:23:26 ID:NlrCHYmt
- >>215
ありがとうございます。意味が分かりました。
>>213のSQL文を実行したら、>>4と同じ結果を得る事ができたのですが
私の欲しい結果は以下のような状態なので、どのようにすれば良いのでしょうか?
具体的なテーブル
テーブルA
A_ID | DATA1...DATA4
--+-----------+
1 | datadatadata |
2 | datadatadata |
3 | datadatadata |
4 | datadatadata |
5 | datadatadata |
6 | datadatadata |
7 | datadatadata |
テーブルB
B_ID | A_ID | MESSAGE| DATE|
----+-----+---------+-----+
1 | 1 | OK | 10/19
2 | 1 | エラー有 | 10/21
3 | 2 | OK | 10/17
4 | 4 | OK | 10/18
5 | 4 | 謎です | 10/22
6 | 6 | OK | 10/14
7 | 5 | ムリポ | 9/9
8 | 6 | エラー有 | 10/20
9 | 5 | OK | 10/9
結果テーブル
A_ID | DATA1...DATA4 | MESSAGE
----+--------------+----------
1 |datadatadata | エラー有
2 |datadatadata | OK
3 |datadatadata | NULL
4 |datadatadata | 謎です
5 |datadatadata | OK
6 |datadatadata | エラー有
7 |datadatadata | NULL
よろしくお願いします。
- 217 :NAME IS NULL:2009/10/23(金) 19:24:21 ID:???
- SELECT A.A_ID, A.DATA1, A.DATA3, A.DATA4, D.DATE, D.MESSAGE
FROM Table_A AS A LEFT OUTER JOIN
(SELECT A_ID, MAX(DATE) AS DATE
FROM Table_B AS B
GROUP BY A_ID) AS C ON A.A_ID = C.A_ID LEFT OUTER JOIN
Table_B AS D ON C.A_ID = D.A_ID AND C.DATE = D.DATE
これでいける。
最後のINNER JOINをLEFT JOINにかえる。
- 218 :NAME IS NULL:2009/10/24(土) 06:24:50 ID:kglbEO/C
- >>217
ありがとうございました。
求めている結果になりました。
- 219 :NAME IS NULL:2009/10/26(月) 13:34:17 ID:GG3WejBx
- SQL+VBSです。
データベースの更新を開いているプラウザでF5や更新じゃなくて
更新をトリガーとして自動的に画面に追加された情報を表示する方法はどんな方法がありますか?
なるべく簡単なほうがいいです。
- 220 :NAME IS NULL:2009/10/26(月) 14:41:54 ID:???
- 鼬害
- 221 :NAME IS NULL:2009/10/27(火) 22:04:11 ID:???
- MySQL 5.1.34
id|date
--+-----
1 |10/25
--+-----
1 |10/26
--+-----
2 |10/25
--+-----
2 |10/26
SELECT * FROM table
WHERE id = 1 AND date
= (SELECT date FROM
table WHERE id = 1
ORDER BY date ASC
LIMIT 0,1);
id = 2だったり
order by が descだったりします。
このような自己相関サブクエリを用いて
データの取得を行っていました。
しかし同じサブクエリでDELETEは
MySQLの仕様上できないようで
一時テーブルを使わないとダメらしいのですが
どうにもうまく動きません。
アドバイスをお願いいたします
- 222 :NAME IS NULL:2009/10/27(火) 23:24:39 ID:???
- >>221
delete from table
where id =1 and date =
(select max(t2.date) from table t2 where t2.id = id)
- 223 :NAME IS NULL:2009/10/30(金) 18:57:55 ID:iB0kBy0C
- どうかよろしくお願いします。
MySQL 5.1
>>5と似ているのですが
data
-----
いちご
メロン
ぶどう
ぶどう
イチゴ
バナナ
いちご
アボガド
というようなテーブルの中から
data|count
ーー+ーーー
いちご|2
メロン|1
ぶどう|2
イチゴ|1
バナナ|1
アボガド|1
というデータが取得したいです。
data列は何が増えるか分からないので、>>5のようにdataの値を固定してcountを取るという方法が使えないのですが…。
- 224 :NAME IS NULL:2009/10/30(金) 19:37:59 ID:???
- 普通に SQL 勉強しろよ・・・。
Group by するだけだろ?
- 225 :NAME IS NULL:2009/10/30(金) 19:57:43 ID:iB0kBy0C
- げ、マジだ…。なんでこんなに悩んでたんだろう。失礼しました…。
ありがとう>>224さん。
- 226 :NAME IS NULL:2009/10/31(土) 05:16:03 ID:IQbi1b6x
- id|flag|...
-+---
1|1
2|1
3|5
....
上記sqliteのテーブルに、30件より古いデータを削除する
DELETE FROM table WHERE id < (SELECT min(id) FROM (SELECT id FROM table WHERE flag > 1 ORDER BY id DESC LIMIT 30));
って書いてみたんですが、もっとスマートな記法があるのでしょうか?
ちなみに
DELETE FROM table WHERE id < min(SELECT id FROM table WHERE flag > 1 ORDER BY id DESC LIMIT 30);
ってやったらエラーになりました。。。orz
- 227 :NAME IS NULL:2009/10/31(土) 09:32:24 ID:???
- >>226
flag > 1の扱いがよく分からないが、こうゆうの?
delete from table
where
id in (
select id from table
where flag > 1
order by id desc limit 30
)
ちなみに
DELETE FROM table WHERE id < (SELECT min(id) FROM (SELECT id FROM table WHERE flag > 1 ORDER BY id DESC LIMIT 30))
で、データ削除された?
なんとなく、一件も削除さえ無いような希ガス
- 228 :NAME IS NULL:2009/10/31(土) 12:35:06 ID:???
- >>226 のやりたいことは、直近の30件だけ残して
それ以外を削除したいんじゃないの
>>227 だと真逆じゃね
- 229 :NAME IS NULL:2009/10/31(土) 13:58:39 ID:???
- >>222
返事が遅くなり申し訳ございません。
そちらも自己相関サブクエリとみなされるのか
- 230 :NAME IS NULL:2009/10/31(土) 14:00:15 ID:???
- >>222
返事が遅くなり申し訳ございません。
そちらも自己相関サブクエリとみなされるのか、実行できませんでした。
PHPからの操作だったのでSQL文を二つに分けることで解決いたしました。
ありがとうございました。
- 231 :226:2009/10/31(土) 15:29:11 ID:???
- 説明が不十分だったようですみません。
>>228さんの書いてる通り、直近の30件(flag=0が間に挟まってたら+α)だけ残して
それ以前を削除しようとしてます。
>>227
>ちなみに
>DELETE FROM table WHERE id < 〜略〜
>で、データ削除された?
これが最適解なのか判りませんが一応テストでは希望通り削除されてます。
- 232 :NAME IS NULL:2009/11/03(火) 17:36:01 ID:m1YxAjhk
- 数値Aを基準に、小さくても大きくても、近い値を、近い順に並べるsqlはどう書けば良いでしょうか?
- 233 :NAME IS NULL:2009/11/03(火) 18:15:17 ID:???
- SELECT ABS(対象値 - 数値A) as hoge FROM T1 ORDER BY hoge
- 234 :NAME IS NULL:2009/11/05(木) 15:29:53 ID:JywnUDtm
- あるカラムがいずれかの値をとっているかを調べるのに
カラム IN (値1, 値2, ...)
のような書き方があると思いますが、いずれかのカラムがいずれかの値かどうかを調べるにはどんな書き方があるでしょうか。
イメージは
(カラム1, カラム2, ...) IN (値1, 値2, ...)
です。
今のところはこんな書き方しか思いつきません。
( カラム1 IN (値1, 値2, ...) OR カラム2 IN (値1, 値2, ...) OR ... )
- 235 :NAME IS NULL:2009/11/05(木) 21:11:48 ID:???
- そんな感じ。
ある値、なら、
値 in (カラム1, カラム2, カラム3) みたいに書けるけど。
あとは、連結して文字列から取ってくるとかかね。
- 236 :NAME IS NULL:2009/11/06(金) 00:25:02 ID:???
- >>234
標準SQLだけで解決したい場合、カラム数が少なければ、
select * from テーブル A
where
exists (
select 1 from (
select id, カラム1 as カラム from テーブル
union all
select id, カラム2 from テーブル
union all ...
) B
where
B.id = A.id
and B.カラム in (値1, 値2, ...)
)
って、やっちゃうかな
- 237 :234:2009/11/06(金) 18:24:29 ID:???
- >>235
やっぱそんなもんですか...
>>236
うーん、ぱっと見コストが大きそうですけどどんなもんですかね。
ちなみに非標準ならうまい方言があったりするんですかね?
まあなんにせよ、設計がよくない気がするのでそっちを見直す方がいい気がしてきました。
ありがとうございました。
- 238 :NAME IS NULL:2009/11/06(金) 18:25:08 ID:???
- 漠然とした質問で申し訳ないんですが・・・
プライマリキーをintegerにするのとcharにするのとでは、integerのほうが速いんでしょうか。
今、言語を表すテーブルを作っているんですが、プライマリキーとして、
id integer primary key auto_increment,
code char(2) not null, -- 'ja', 'en', 'fr' など
にするか、
code char(2) primary key -- 'ja', 'en', 'fr', など
にするか迷ってます。
charにしたほうが、テーブルを覗いたときにわかりやすいし、個人的に気に入っているんですが、
やはり文字列より数値のほうがなにかと高速なように思うし、どうしたもんでしょうか。
- 239 :NAME IS NULL:2009/11/06(金) 19:21:37 ID:???
- >>238
「テーブルには必ず数値のプライマリキーをつける」とかの設計思想なら
それはそれでアリだと思うけど「なにかと高速」なんていう曖昧な理由で
意味のない属性を追加しちゃうのはどうかと思う
- 240 :NAME IS NULL:2009/11/06(金) 22:13:53 ID:???
- >>238
そのレベルでパフォーマンス論じても意味ねぇ。誤差。
ただあえて言うなら、前者の方がタプルサイズが大きくて
意味のあるデータがリーフにしか存在しないから多分遅い。
でもやっぱり誤差。
- 241 :NAME IS NULL:2009/11/07(土) 20:34:59 ID:/yykcTFm
- SELECT した全レコードの特定カラムを文字列連結したものを得る方法はありますか?
SELECT C FROM T
とやったときに AAA、BBB、CCC といった値が得られる時、AAABBBCCC のような 1つの値が欲しいです。
さらにそれらの間に任意の区切り文字を入れて AAA:BBB:CCC のような値を得ることはできるでしょうか。
- 242 :NAME IS NULL:2009/11/07(土) 20:53:37 ID:???
- concatとか||とかそういうの。
- 243 :NAME IS NULL:2009/11/08(日) 00:45:26 ID:???
- ソートに関する質問です。
データ(文字列)として'1'・'2'・'3'・'1〜2'・'1〜3'・'2〜3'があるのですが、
これを'1'・'1〜2'・'1〜3'・'2'・'2〜3'・'3'の順に
出力する方法はないでしょうか。
#普通にorder byで並べると、
'1〜2'・'1〜3'・'1'・'2〜3'・'2'・'3'順になってしまいます。
- 244 :241:2009/11/08(日) 01:03:09 ID:???
- >>242
イメージとしては
SELECT CONCAT(SELECT C FROM T)
とか
SELECT 〜, CONCAT(C) FROM T GROUP BY 〜
みたいな感じです。
なんとなく伝わるでしょうか?
- 245 :NAME IS NULL:2009/11/08(日) 01:28:17 ID:???
- 取得してからアプリ側でやれよ。
- 246 :NAME IS NULL:2009/11/08(日) 01:33:32 ID:???
- >>244
あ、ごめん。俺バカス。
それは標準だと無理なのでストアド作るか、アプリでやるのがいいと思うです。
- 247 :NAME IS NULL:2009/11/08(日) 02:13:53 ID:???
- DBMSがなにかによるけど’〜’を’’に置換する関数があればそれでorder byすればできんじゃね?
- 248 :NAME IS NULL:2009/11/08(日) 02:24:29 ID:???
- 見た感じ文字列長が短いもののほうが後ろに行ってることが問題のように思うけど。
なんか設定あったじゃん。順序決めるやつの。
あれJAPANESE CIなんたらかんたらになってる?
- 249 :244:2009/11/08(日) 03:17:57 ID:???
- >>245,246
ですよね。アプリでやります。
>>243
文字列の種類が本当にそれだけしか無いなら、
order by concat(カラム, '〜0')
ってのはどうだろう。
- 250 :NAME IS NULL:2009/11/08(日) 03:23:26 ID:57QroYvr
- 使用DB sqlite3
key data
----------------
1 a
2 b
3 c
4 d
5 a
6 b
7 a
8 d
↑のtableテーブルからdataがaなのが何個あるか、bが何個あるか、cが何個あるか…
を調べるSQLがよくわかりません。
select data , count(*)
from table
where data = a
union
select data , count(*)
from table
where data = b
union
:
などとやっていくとdataの種類が700近くあるため
SQL文がものすごく長くなって実行出来なくなってしまいます。
欲しい結果は以下のような感じです。
data count
-----------
a 3
b 5
c 3
d 4
e 2
すみませんがどのように書けばよいか教えていただけないでしょうか。お願いします。
- 251 :249:2009/11/08(日) 03:28:12 ID:???
- あれごめん、間違ったかも。
普通に order by しても >>243 の欲しい通りの結果が返ってくるみたい。
そんな環境で実験したから >>249 の案も間違ってるかも。
それでも
order by substr(concat(カラム, '〜0'), 0, 3)
ならいけるんじゃないかとおもうけど。
- 252 :NAME IS NULL:2009/11/08(日) 03:31:09 ID:???
- >>250
つ group by
- 253 :NAME IS NULL:2009/11/08(日) 04:52:28 ID:???
- >>241,246
標準的なSQLでどこまで使えるのかは知らんが、再帰SQLが使えるなら可能かもしれない。
ただし、俺もホストアプリでやるべきだと思う。が、一応考えてみた
結合する順序をどうするかって問題もあるが、とりあえずCの順序で結合する
SQL Server2008で実験
with
R as (select ROW_NUMBER() over (order by C) as rownum,convert(varchar(max),C) as C from T),
TEMP as (
select rownum,C from R where rownum=1
union all
select r.rownum,(t.C+r.C) from R r join temp t on r.rownum = t.rownum+1)
select MAX(C) from temp;
なんかできたっぽいw
大量のデータで実行するとえらいことになりそうだ
- 254 :NAME IS NULL:2009/11/08(日) 07:17:37 ID:???
- >>252
すいません。ありがとうございます。早速勉強します。
- 255 :NAME IS NULL:2009/11/08(日) 10:00:51 ID:???
- そのunion並べる発想がすげえ・・・
select data,count(data) from table group by data order by data;
- 256 :NAME IS NULL:2009/11/08(日) 14:46:09 ID:???
- r1 r2 r3
--------
a 1 aaa
b 1 aaa
a 1 bbb
a 1 ccc
b 1 bbb
c 1 aaa
↑のようなデータを
↓のように、r1の件数が多い順に並べ替える方法はありますか?
Mysql 5.1
r1 r2 r3
-------
a 1 aaa
a 1 bbb
a 1 ccc
b 1 aaa
b 1 bbb
c 1 ccc
- 257 :NAME IS NULL:2009/11/08(日) 14:53:34 ID:???
- select r1, count(r1) from table
group by r1
と結合してソートすればいいんかね。
- 258 :NAME IS NULL:2009/11/08(日) 15:09:23 ID:???
- やってみた
select table.* from table join (select r1 from table group by r1 order by count(r1) desc) a on a.r1 = table.r1 order by a.r1;
- 259 :NAME IS NULL:2009/11/08(日) 15:13:52 ID:???
- 何か違うだろw
- 260 :NAME IS NULL:2009/11/08(日) 16:01:11 ID:???
- foo22
foo5
foo11
というデータで
foo5
foo11
foo22
とソートするにはどうすればいいですか
- 261 :NAME IS NULL:2009/11/08(日) 16:45:18 ID:???
- >>260
foo の部分が常に一定なら、まず文字列長でソートしちゃうとか?
- 262 :NAME IS NULL:2009/11/08(日) 16:47:15 ID:???
- 右側二桁切り取って数値に変換してソート。
- 263 :260:2009/11/08(日) 17:56:08 ID:???
- 右側二桁ですか?
fo o5
foo 11
foo 22
- 264 :NAME IS NULL:2009/11/08(日) 17:58:07 ID:???
- 右側二桁じゃダメだな。ごめんごめん。
左側三桁の残り。
- 265 :NAME IS NULL:2009/11/08(日) 18:20:47 ID:???
- PostgreSQLでやってみた
select * from table order by (substr(data, 4))::INT;
- 266 :260:2009/11/08(日) 18:38:20 ID:???
- 済みません
実際はfoo以外もあります
foo22
foo11
hoge1
foo5
hoge15
- 267 :NAME IS NULL:2009/11/08(日) 20:23:14 ID:???
- SQLServerかつ、hogeやfooのところに数字が混じってないと仮定して。
SELECT
A + B
FROM
(
SELECT
LEFT(COL, PATINDEX('%[0-9]%', COL) - 1) A,
SUBSTRING(COL, PATINDEX('%[0-9]%', COL), LEN(COL)) B
FROM
TBL
) TBL2
ORDER BY A, CAST(B AS int)
OracleならREGEXP_SUBSTRでも使えばいいさ。DBMS書いてねーから後はシラネ
>>1を音読してからry
- 268 :243:2009/11/09(月) 22:34:58 ID:???
- >>251
ありがとう。
アイデアを元に、以下でいけたっぽいです。
# 実際には'1個'・'1〜2個'というデータだったので、個を消してます。
order by substr((translate(Kosu, '個', '') || '〜0'), 0, 4);
- 269 :NAME IS NULL:2009/11/09(月) 22:51:15 ID:???
- >>268
'個' を消して order by するだけでよくね?
- 270 :243:2009/11/10(火) 01:04:28 ID:???
- >>269
確かに。
おっしゃる通り、以下でよさそうです。
order by translate(Kosu, '個', '')
# そもそも、>>243の質問の仕方が悪かったですね。申し訳ない…
- 271 :NAME IS NULL:2009/11/12(木) 20:42:44 ID:61MaVw/S
- select sum(price) from table limit 10;
ってするとsum(price)の結果から先頭10行を取ってくる(結果的にlimit意味なし)んだが、
これをlimit 10で抽出した結果をsumしたい場合はどうすればいいのでしょう
select sum(select price from table limit 10)
みたいなことをしたいのだが、こう書いたら当然だがエラーになった
mysql5
- 272 :NAME IS NULL:2009/11/12(木) 21:15:40 ID:???
- select sum(price) from (select price from table order by price desc limit 10)
じゃないの?
- 273 :NAME IS NULL:2009/11/12(木) 21:24:30 ID:???
- >>271
select
key1,
sum(price) price
from table t1
group by key1
having (select count(*) from table where key1 < t1.key1) < 10
order by key1
動作確認はしていない。
- 274 :NAME IS NULL:2009/11/14(土) 10:35:28 ID:/EMexGow
- test
- 275 :NAME IS NULL:2009/11/20(金) 00:54:43 ID:C7l1oPDg
- 環境 SQL Server 2005
次のようなテーブルがあります。
テーブル:TEST
A | B |
------------------
1 | 2 |
このテーブルには列(A,B)があります。
データにはAに'1', Bに'2'という値があります。
質問
次の二つのSQL文を実行すると同じ結果になるのはどうしてですか?
SELECT * FROM TEST WHERE A = '1'
SELECT * FROM TEST WHERE A = '1 '
- 276 :NAME IS NULL:2009/11/20(金) 01:32:52 ID:???
- >>275
DDLでてないから、憶測だけど、
列Aの定義が、char(4)である可能性に100ジンバブエドル
- 277 :NAME IS NULL:2009/11/22(日) 14:31:47 ID:???
- 列Aの定義がint(とかの数値系)であった場合、
SQL Serverの暗黙の型変換により文字列'1 'が数値1と判定されるため、に500000000ジンバブエドル
- 278 :NAME IS NULL:2009/11/23(月) 11:37:46 ID:???
- 安い掛け金だなあ
- 279 :NAME IS NULL:2009/11/25(水) 10:00:25 ID:NcYOsBxp
- ここで聞くのが適切かわからんが・・・
SQLをselect,from,whereとかいう配列にいれて、実行時に組み立てる利点がよくわからない。面倒だし、サブクエリーしづらいし意味わからん。
利点を説明してください。
↓こういうの。
$params = array(
'from' => array(
'hoge' => array(
'*'
),
),
'join' => array(
'hogehoge' => array('hoge.hogeid = hogehoge.hogeid', array('*')),
),
'where' => array(
'hoge.foo = ?' => 't',
'hoge.bar = ?' => '3',
),
'order' => $options['sort']
);
- 280 :NAME IS NULL:2009/11/25(水) 12:38:10 ID:???
- >>279
自由なクエリを組み立てづらいというのは置いといて、そのようにするメリットは、
同じ条件なら完全に同一なSQL文になること。パラメタライズドクエリーが使える
DBMSなら使うのを強制できるし。
「同じ条件なら完全に同一なSQL文」を発行することのメリットは、DBMSが
SQLのパースと実行計画立案の結果をキャッシュしているはずなので、
そのキャッシュを使い回し、結果的に全体のパフォーマンスが上がること。
- 281 :NAME IS NULL:2009/11/25(水) 16:04:13 ID:???
- >>280
おお!なるほど!
それは一理ですね!
- 282 :NAME IS NULL:2009/11/25(水) 20:58:17 ID:???
- >>280
ホストアプリでの配列や文字列の扱いがよくわからんが、
同一条件で完全に同一なSQLになるのは、「配列」に入れることとは
あんまり関係ないと思うんだが
>>279
そのホストアプリでの(SQL)文字列の生成について、配列にすることに
メリットがあるか?って話だろう
最終的にSQLとして発行するってだけで、ホストアプリでの文字列操作の話なんだから
ここではスレ違いだ。そのホストアプリの言語のスレで聞くべきだな
- 283 :NAME IS NULL:2009/11/25(水) 22:23:51 ID:???
- 教えてください。
DB に対するクエリを効率よく実行できるようにしたいと思います。
そこで「プリミティブSQL」?と言う言葉を聞きました。
実行する SQL の条件部分以外を先に定義しておいて?、条件をパラメータのような形で
引き渡すことと伺いました。
ようするに、
SELECT * FROM table WHERE id = ?
のような SQL を定義し、実行時に ? の部分だけを指定してあげること、と。
このような形で実行すれば DB 上のキャッシュに情報が残るので検索が速くなる、と。
うえのようなコトをするためのものとしては SQL Server であればストアドプロシージャを
連想するのですが、これとは違う物なのでしょうか。
自分は DB の経験はほとんどなく、上記の話を聞いたときも慌ただしかったため十分には
理解できませんでした。ですのでもしかしたら言葉も間違っているかも知れません。
※ぐーぐる先生に上の用語で質問したのですが、思ったような記事にたどり着けませんでした。
教えていただけると幸いです。
- 284 :NAME IS NULL:2009/11/25(水) 22:29:22 ID:???
- パラメータクエリーだな。
検索条件の値だけが違うんで、キャッシュされたクエリーが実行される。
なので、ちょっとだけ速い。
ストアドの単純版みたいなイメージかね。
- 285 :NAME IS NULL:2009/11/25(水) 23:00:13 ID:???
- >>283
実行プランまで出しておいて、パラメータが渡されたときに即実行される。
だけど、パラメータによっては予定されたプランが最良と限らない時もある。
複雑なSQLほど有用だと思うけど、思わぬ落とし穴にはまった記憶が。
- 286 :NAME IS NULL:2009/11/25(水) 23:07:56 ID:???
- SQLに負担をかけないようにクライアント側で処理したほうが
速くなる可能性大
- 287 :>>283:2009/11/25(水) 23:20:55 ID:???
- ありがとうございます。
一応、「DB のプロ」の方に伺った話ではあったんですが。。。
やはり自分でもちゃんと調べて納得しないとダメみたいですね。当然ではありますが。
配慮すべき点の注意もありがとうございました。
また自分で調べてみますが、もし分からないことがあったら教えていただけると幸いです。
- 288 :NAME IS NULL:2009/11/25(水) 23:25:12 ID:???
- >>283
おそらくプリペアドSQLだと思われ
同じSQLを大量に発行する場合に有効
厳密にはプリペアドでサーバが「データを検索」する時間は短くならない
SQLがDBサーバに渡された場合、まずDBサーバはそのSQLが間違ってないかチェックして
実際にデータを検索する方法を決定する。プリペアドにすれば、2回目以降は
この解析処理を(キャッシュを利用することで)省略できるので、結果として
データを返すのが速くなる、って理屈
SQL ServerでADO.NETだとかだと、プリペアドは一時ストアドプロシジャ使ってるんじゃなかったかな
- 289 :283:2009/11/25(水) 23:36:35 ID:???
- >>288
ありがとうございます。
「プリペアドSQL」言われてみればそんな言葉だった気も。。。
そう言う理屈なんですね。助かります。
こちらのキーワードでももう一回調べ直してみます。
- 290 :NAME IS NULL:2009/11/26(木) 14:33:33 ID:9DZPU7hh
- ・DBMS名とバージョン
Microsoft SQL Server 2005
・テーブルデータ
tblA
pkey|value
----+-----
1 |a
2 |b
tblB
pkey|value
----+-----
1 |c
・欲しい結果
tblA
pkey|value
----+-----
1 |c
2 |b
・説明
両テーブルとも、pkeyが主キーです。
pkeyを条件に、tblAのvalueを、tblBのvalueで上書きしたいのですが、
どの様に書くのが一般的なのでしょうか。
UPDATE tblA
SET tblA.value = tblB.value
WHERE tblA.pkey = tblB.pkey
↑だと、「マルチパート識別子 "tblB.pkey" をバインドできませんでした。」
とエラーメッセージが出てしまいます。
UPDATE tblA
SET tblA.value = (SELECT MAX(tblB.value) FROM tblB WHERE tblA.pkey = tblB.pkey)
WHERE EXISTS
( SELECT *
FROM tblB
WHERE tblA.pkey = tblB.pkey
)
↑とすると、ほしい結果は得られるのですが、
非常に複雑な書き方の様な気がします。
- 291 :NAME IS NULL:2009/11/26(木) 15:12:15 ID:???
- >>290
pkeyが主キーならMAX()はなくてもいいんじゃね。
MS-SQLで実行可能かどうか不明だが、
UPDATE tblA SET value = tblB.value FROM tblB where tblA.pkey=tblB.pkey;
- 292 :NAME IS NULL:2009/11/26(木) 15:15:34 ID:2WFte6Oi
- 前者は tblB がSQL内で解決されないから、駄目じゃない?
後者は SELECT * -> SELECT '適当な文字でも可' の方がいい気がする
# 自分は 'A' が多いかな>対象数が増えると、きいてくるよ
- 293 :290:2009/11/26(木) 15:35:52 ID:???
- >>291の様な書き方が出来たんですね。
知りませんでした。
>>292
EXISTSの場合は*を使うのがいいよ。
って聞いていたので、いつも*でした。
調べてみます。
どうもありがとうございました。
- 294 :NAME IS NULL:2009/11/26(木) 15:58:47 ID:???
- 今は、* で十分。
下手に定数を仕込むより、プランナやオプチマイザがちゃんと判断する。
と、思ってます。
- 295 :NAME IS NULL:2009/11/26(木) 17:30:00 ID:???
- >>290
ためしてないけど、SQL Serverならたぶんこう
update tblA set tblA.value = tblB.value
from tblA join tblB on tblA.pkey = tblB.pkey
>>292
existsのサブクエリに定数書けなんて、昔に通用してたバッドノウハウ
定数じゃなくて主キー項目セレクトした方が早いとかいうのもあったな
どっちも今じゃ不要の、単なる昔の高速化テクニック
今のDBMSのオプティマイザはかなり賢いぞ
- 296 :NAME IS NULL:2009/11/26(木) 17:34:05 ID:???
- ストアドでやるな
- 297 :NAME IS NULL:2009/11/26(木) 20:07:21 ID:???
- >>295
「今のDBMS」にMSSQL2005は含まれますか?
- 298 :NAME IS NULL:2009/11/26(木) 20:55:23 ID:???
- SQLDBのaddNEWでのインサートが100万件ぐらいあるのでループで50行追加に時間がかかるようになります。
どうやって、対処するか説明があるようなところ知りませんか?
- 299 :NAME IS NULL:2009/11/27(金) 01:05:18 ID:???
- ・DBMS名とバージョン
SQLite3
・テーブルデータ
[table_A]
key valueA
------------
1 5
2 2
[table_B]
key valueB
------------
1 2
3 1
・欲しい結果
key valueA valueB
-----------------------
1 5 2
2 2 0 <-「NULL」じゃなくて「0」
3 0 1
・説明
table_A、table_BともにUNIQUE(key)になっています。
単純に結合しようとすると、片方だけに存在するkeyはどちらかがNULLになってしまいます。
それを「NULL」ではなく「0」にする方法はありませんでしょうか?
#「NULL」は「0」に自動変換うんぬんではなく、「0」にする方法です。
- 300 :NAME IS NULL:2009/11/27(金) 01:10:51 ID:???
- >>299
COALESCE(valueB,0)
- 301 :NAME IS NULL:2009/11/28(土) 03:31:52 ID:???
- >>283
効率の問題だけでなく、安全性やデバッグ効率からも評価してあげてください><
#アドホッククエリ濫用しまくってる奴にサニタイジング云々言われると(検閲削除)したくなるよね('A`)
- 302 :NAME IS NULL:2009/11/28(土) 05:58:47 ID:???
- 今更だけどSQLServer2005においてはPreparedなクエリとParameterizedなクエリは区別されている。
単にキャッシュ云々ということであれば、ADO.NETであれば
適切にパラメータを設定してやれば勝手にキャッシュされる。
(内部的にストアドsp_executesqlで処理される。
preparedはsp_prepexecという、また別のストアドで処理される。)
PreparedはSqlCommand.Prepare()、またはsp_prepxecを実行することでなる。
MSDNによると単一のコネクション中で、
パラメータ部分のみ違うクエリを4回以上流して、
ようやくPrepareする効果があると言えるそうだ。
- 303 :NAME IS NULL:2009/11/28(土) 21:46:31 ID:???
- mysql 5.1.34
table test_data
id int
vol int
title_sentence varchar(50)
title_sentenceがnullでなく、かつ関数と言う語句が含まれているものと言う事なら
select id, vol from vba
where
title_sentence is not null and
title_sentence like '%関数%';
で良いと思うのですが、nullでなく、かつ関数という語句が含まれていないものを
抽出したい場合、どのように書けばいいのでしょうか?
- 304 :NAME IS NULL:2009/11/28(土) 21:48:45 ID:???
- not like
- 305 :NAME IS NULL:2009/11/28(土) 22:09:48 ID:???
- >>304
thx なんか考えすぎていたみたいですねw
- 306 :NAME IS NULL:2009/11/29(日) 23:58:57 ID:???
- >>302
ん、Oracleでも違うし、どんなRDBMSでも違うんじゃないの?
- 307 :NAME IS NULL:2009/12/01(火) 18:09:14 ID:???
- 質問させてください。 DBMS:mysql5.0.45
業務テーブル G_info
業務ID | 業務名 |
G0001 | ○○設計 |
G0002 | ××調査 |
G0003 | ○△設計 |
業務担当テーブル G_charge
業務ID | 役割 | 社員ID
G0001 | 管理 | P101
G0001 | 検査 | P103
G0001 | 設計 | P105
G0002 | 管理 | P102
G0002 | 検査 | P103
G0002 | 設計 | P106
G0003 | 管理 | P101
G0003 | 検査 | P104
G0003 | 設計 | P107
こんなテーブル構成だったとして、
設計 = P101 かつ 検査 = P103 の担当者を持つ業務名を取り出すSQLはどのようにすれば良いのでしょうか?
- 308 :NAME IS NULL:2009/12/01(火) 18:36:45 ID:y01OwToP
- 質問です。
SQL文の中に@を入れて項目を繋げて書くのは、
どんな処理をするためなのでしょうか。
- 309 :NAME IS NULL:2009/12/01(火) 20:40:04 ID:???
- 例をあげてみ。
- 310 :NAME IS NULL:2009/12/01(火) 21:27:20 ID:???
- >>307
とりあえず脊髄反射で書くとこうなる
select I.業務名
from G_info I
inner join
G_charge C1
on I.業務ID = C1.業務ID
inner join
G_charge C2
on I.業務ID = C2.業務ID
where C1.役割 = '設計'
and C1.社員ID = 'P101'
and C2.役割 = '検査'
and C2.社員ID = 'P103'
;
- 311 :NAME IS NULL:2009/12/02(水) 06:15:28 ID:???
- オレは条件反射してみた。
SELECT 業務名 FROM G_info
WHERE 業務ID IN (
SELECT 業務ID FROM G_charge
GROUP BY 業務ID
HAVING 2 = SUM(CASE
WHEN 役割 = '設計' AND 社員ID = 'P101' THEN 1
WHEN 役割 = '検査' AND 社員ID = 'P103' THEN 1
ELSE 0 END))
例に挙げたデータに一致するものがないのは愛嬌か?
- 312 :307:2009/12/02(水) 10:49:11 ID:???
- 310さん311さんありがとうございました。
ちょとSQLをゴテゴテ書いたらタイムオーバーになってしまったので(業務担当テーブルが2万行ぐらい)
自分なりに方法工夫していこうと思います。
>例に挙げたデータに一致するものがない
昨日は相当テンパっていたぽいのでご容赦下さい^^;
- 313 :NAME IS NULL:2009/12/02(水) 13:28:45 ID:???
- インデックス使ってるか見てみたら?
- 314 :NAME IS NULL:2009/12/05(土) 14:34:03 ID:zE+CTdjd
- 簡単そうな気がするのですが、どうしてもうまくいかないので、分かる方がいれば教えてください。
ユーザーが複数の資格を持っているというありがちなテーブル構成があるのですが、
「資格1または資格2を持っているユーザー」の検索はできるのですが、
「資格1と資格2」を両方持っているユーザー」の検索ができません。
データベースはpostgresです。
テーブル構成はこんな感じです。
ユーザーテーブル
[ユーザーID、名前]
001,山田
002,鈴木
資格テーブル
[ユーザーID、資格]
001,資格1
001,資格2
002,資格1
「資格1または資格2を持っているユーザー」であれば、
select distinct ユーザーテーブル.ユーザーID、名前 from ユーザーテーブル
inner join 資格テーブル on (ユーザーテーブル.ユーザーID = 資格テーブル.ユーザーID)
where 資格テーブル.資格 = '資格1'
or 資格テーブル.資格 = '資格2'
で取得できました。
「資格1と資格2」を両方持っているユーザーとして山田さんを検索したいのですが、
単純にorをandにすると、対象が0件になってしまいます。
とても困っているので、よろしくお願いします。
- 315 :NAME IS NULL:2009/12/05(土) 14:48:08 ID:???
- 307と同じ問題じゃないの
select 名前 from ユーザーテーブル
where ユーザーID in (
select ユーザーID from 資格テーブル
group by ユーザーID
having 2 = sum(
case when 資格 in ('資格1','資格2')
then 1 else 0 end))
他にもいろいろ解があるからためしてみ
- 316 :NAME IS NULL:2009/12/05(土) 16:00:12 ID:???
- てか>>6だな
- 317 :NAME IS NULL:2009/12/06(日) 00:17:28 ID:u5F21TQj
- >>315
>>316
回答ありがとうございます。
とても助かりました!
- 318 :NAME IS NULL:2009/12/07(月) 01:41:23 ID:???
- ストアドである値が入ってきた時だけ、それを検索するというものを作りたいのですが
たとえば input が
客番号
電話番号
顧客氏名のとき
デフォルトは空で、値があるときだけ
where句に
custnum = @in_custnum
という条件が入るような。
入ってきたパラメータで、検索条件をストアド内で変える書きかた教えてください
- 319 :NAME IS NULL:2009/12/07(月) 02:20:48 ID:???
- @in_custnum is null or custnum = @in_custnum
- 320 :NAME IS NULL:2009/12/08(火) 18:13:35 ID:???
- MySQL 5.1.35 WinXP
table book
title varchar(50) cp932
このカラムで先頭1文字が漢字のもの、ひらがなのものとかって
言う風に取出したいのですが、どう書けばいいのでしょうか?
- 321 :NAME IS NULL:2009/12/08(火) 18:58:13 ID:???
- 質問があります。
sqlite2を使用しています。
スコアランキングで、自分の上下4人を含めた9人分の情報を取ってきたいのですが、どのようにすればよいでしょうか?
(自分が1位などの場合は自分と下位8人分を取得します)
SELECT T3.*
FROM score_tbl as T1, score_tbl as T2, score_tbl as T3
WHERE T1.userno = 5(自分のユーザーナンバー)
AND T1.score >= T2.score
GROUP BY T3.userno
ORDER BY T3.score DESC
LIMIT 0,9;
試行錯誤しながら上の文まで書きました。
あとLIMITの0の部分に COUNT(T2.userno) - 4 が指定できればOKなんですが…
もっと別の考え方が必要なのでしょうか。
よろしくお願いします。
- 322 :NAME IS NULL:2009/12/08(火) 19:10:25 ID:???
- 自分と、上4人と、下4人を UNION したらいいんじゃないのか?
- 323 :NAME IS NULL:2009/12/08(火) 20:26:55 ID:???
- SQL Server2008
ばらばらの金額データが1000行くらい入っているテーブル(主キーは別にある)で
例えば1531円になる組み合わせをすべて抜き出すとかできますか?
Excelとかでできるならそれでもいいんだけど
プログラム書いて総当りでやったほうがいいかな?
- 324 :NAME IS NULL:2009/12/08(火) 20:47:42 ID:???
- 1円から1000円までで1000行だとすると、膨大な計算量になるね。
- 325 :NAME IS NULL:2009/12/08(火) 20:49:06 ID:???
- その組み合わせってのは、2個の組み合わせなのか、任意の個数の組み合わせなのか
二つで1531円なら直積取れば簡単にできるな
任意の個数で1531円になるのは、再帰SQL書けばできるかも
- 326 :Jolly Rogers ◆0tkoCr0voc :2009/12/08(火) 21:09:44 ID:???
- >323
そもそももし任意個数だと、それって部分和問題(ナップザック問題の限定パターン)に
なるから相当力業になるような……
いや早く解くためのアルゴリズム(動的計画法)はあるけど。
- 327 :321:2009/12/09(水) 00:48:16 ID:???
- >>322
UNIONの使い方を知らなかったので調べて試してみたのですが、LIMITの後ろにUNIONを置くことが出来ないので、上4人と下4人をSELECTしてUNIONするっていうのがうまくできませんでした。
「LIMIT clause should come after UNION not before」と出ます。
難しい…
- 328 :NAME IS NULL:2009/12/09(水) 00:51:52 ID:???
- sqliteて使ったこと無いけど
limitを含むselect分を丸ごと括弧でくくってもう一回selectすりゃいいんじゃないの
- 329 :321:2009/12/09(水) 13:07:51 ID:???
- >>328
丸ごと括弧でくくって試してみたのですが、
(自分が1位などの場合は自分と下位8人分を取得します)
などの取り方が分かりませんでした。
ムリに1つのSQL文で書こうとせず、自分より上位8人と下位8人をそれぞれ
取得して、それぞれ取得出来た数などを計算して結果を作成しようかと考え
てます。
トランザクションしておけば上位を取得中にデータが更新されることもない
と思いますし。
- 330 :NAME IS NULL:2009/12/09(水) 14:08:28 ID:???
- ■DBMS
PostgresSQL 8.3以上
■テーブル定義
・IDテーブル
id_1 integer,
id_2 integer,
id_3 integer
・マスターテーブル
id integer,
class char(1)
■テーブルデータ
・IDテーブル
1, 2, 3
1, 2, 4
5, -1, -1
-1, 1, 2
2, -1, 5
・マスターテーブル
1, A
2, A
3, A
4, B
5, B
-1, Z
■やりたいこと
マスターテーブルを参照してIDテーブルの各IDにクラス(A, B, Z)を振り当て、
各レコードが同一クラスに属するか否かを判定し、同一クラスに属するレコード
だけクラス付で抽出する。
ここで「同一クラスに属する」とは、クラスA, B, Zからなるグループに対して、
Z以外の要素が一種類しか存在しない場合に、グループはそのクラスに属すると定める。
【例】
A, A, B, Z -> 属するクラス無し
Z, Z, A, A, Z -> クラスAに属する
B, A -> 属するクラス無し
B -> クラスBに属する
今の場合、
1, 2, 3 -> A, A, A -> A
1, 2, 4 -> A, A, B -> 属するクラス無し
5, -1, -1 -> B, Z, Z -> B
-1, 1, 2 -> Z, A, A -> A
2, -1, 5 -> A, Z, B -> 属するクラス無し
であり、最終的に欲しいデータは
1, 2, 3, A
5, -1, -1, B
-1, 1, 2, A
となります。よろしくお願いします。
※IDテーブルの列数=3、クラス数=3 というのは揃っている必要はなく
IDが5列ありクラスが10種類あるという場合でも適用可能な回答をお願いしたいです。
- 331 :330:2009/12/09(水) 14:12:56 ID:???
- なお、自力で
1, 2, 3, A, A, A
5, -1, -1, B, Z, Z
-1, 1, 2, Z, A, A
というデータを返すSQLを作成することはできたのですが、その先がわからない状態です。
またその作成したSQLもあまり(全然?)スマートではなく、できるだけ簡潔な構成のSQLを
利用したいと考えています。どうかみなさんのお知恵をお貸しくださいm(_ _)m
■作成したSQL
SELECT
id_1,
id_2,
id_3,
class_1,
class_2,
class_3
FROM
(
SELECT
id_1,
id_2,
id_3,
m_1.class as class_1,
m_2.class as class_2,
m_3.class as class_3
FROM
ID_TABLE,
MASTER_TABLE m_1,
MASTER_TABLE m_2,
MASTER_TABLE m_3
WHERE
ID_TABLE.id_1 = m_1.id
AND
ID_TABLE.id_2 = m_2.id
AND
ID_TABLE.id_3 = m_3.id
) AS TMP_TABLE
WHERE
CASE
WHEN (class_1 != 'Z' AND class_2 != 'Z') THEN class_1 = class_2
ELSE class_1 = class_1
END
AND
CASE
WHEN (class_2 != 'Z' AND class_3 != 'Z') THEN class_2 = class_3
ELSE class_2 = class_2
END
AND
CASE
WHEN (class_3 != 'Z' AND class_1 != 'Z') THEN class_3 = class_1
ELSE class_3 = class_3
END
- 332 :330:2009/12/09(水) 14:17:04 ID:???
- 連投すみません。
>>331のSQLを修正して欲しいというわけではなく、
初めから作り直していただいて一向に構いません。
また
> ※IDテーブルの列数=3、クラス数=3 というのは揃っている必要はなく
> IDが5列ありクラスが10種類あるという場合でも適用可能な回答をお願いしたいです。
これは一般形でも通用するようなSQLそのものが欲しいというわけではなく、
この例の個数に適用できるもので構いません。(それが完全に個数依存のもので
他の個数の場合に応用が利かないものだと困る、という意味で書きました)
長々と失礼しました。
- 333 :NAME IS NULL:2009/12/09(水) 17:21:33 ID:???
- テーブルを始めから作り直せ
- 334 :NAME IS NULL:2009/12/09(水) 19:07:05 ID:???
- >>331
テーブル設計やり直せって意見に激しく同意する
PostgresSQLは使ったことないし手元にないので、SQL Server2008でやってみた
with
DATA_TABLE as (
select
i1.id_1,i1.id_2,i1.id_3,i1.id,m1.class as class
from
( select id_1,id_2,id_3,id_1 as id from ID_TABLE
union
select id_1,id_2,id_3,id_2 as id from ID_TABLE
union
select id_1,id_2,id_3,id_3 as id from ID_TABLE ) as i1
join MASTER_TABLE m1 on i1.id=m1.id
),
CLASS_TABLE as (
select distinct
id_1,id_2,id_3,class
from
DATA_TABLE
where
class <> 'Z'
)
select
id_1,id_2,id_3,max(class) as class
from
CLASS_TABLE
group by
id_1,id_2,id_3
having
COUNT(*)=1
withって便利だなぁw
with使えないならCLASS_TABLEとDATA_TABLEをビューで作るか、
fromに直接カッコつきでselect文書けば行けると思うが
- 335 :NAME IS NULL:2009/12/10(木) 17:33:52 ID:MkNFz2CF
- 営業時間を入れて、ある特定の時間にオープンしているかどうか検索するにはどうしたらいいのでしょうか?
最初考えたのは
CREATE TABLE shop(
id INT AUTO_INCREMENT PRIMARY KEY,
open_time TIME,
close_time TIME
)Type=InnoDB;
こんなテーブルで
SELECT * FROM shop WHERE (open_time <= CURRENT_TIME) AND (close_time >= CURRENT_TIME);
と考えたのですが、これだと、日をまたいだ、0時を過ぎる深夜営業が管理できないです。
なんかちょっとひらめいたのは、close_dateの代わりに何時間オープンしているかというINTERVALをしまえば検索出来そうな気もしたのですが
型を何にすればいいのか、又、どんな演算・関数で条件を記述するのか、いろいろ試してもうまくいきません。
使用DBはMySQLです。
なにか、アイデア、アドバイスあったらお願いします。
- 336 :NAME IS NULL:2009/12/10(木) 18:05:58 ID:???
- closeのほう、日をまたぐときは24時間足して登録するとか
- 337 :NAME IS NULL:2009/12/10(木) 20:31:16 ID:???
- あるいは取得時に
open > closeならcloseに24時間足すか
- 338 :NAME IS NULL:2009/12/11(金) 01:12:53 ID:hK/pkhDF
- >> 335
レスポンスを考えないで良いなら。
SELECT *
FROM shop
WHERE (open_time < close_time AND CURRENT_TIME BETWEEN open_time AND close_time)
OR (open_time = close_time)
OR (open_time > close_time AND (CURRENT_TIME <= close_time OR open_time <= CURRENT_TIME));
で取得可能かと。
ただ、TIME型は,'00:00:00'-'23:59:59'の間を必ず取ると仮定しております。
- 339 :NAME IS NULL:2009/12/11(金) 02:09:13 ID:???
- datetimeにして、25時とかで登録して、検索するときも '21:00:00' as datetimeとかにすればだいじょぶだよきっと
- 340 :NAME IS NULL:2009/12/12(土) 10:44:05 ID:???
- 話の流れをぶった切ってスマソ
ネットワークエンジニアなんだが、昨日、会社からデータベーススペシャリストの
資格取れと言われた。
Mysqlからはじめようと思うのだが、Mysqlの良い基本書はないかな?
できればコマンドラインからの入力から説明している基本書がいい。
Webの説明は見にくいのが辛い…。
- 341 :NAME IS NULL:2009/12/12(土) 10:46:22 ID:???
- すまん、誤字った。
Mysql→MySQL
- 342 :NAME IS NULL:2009/12/12(土) 11:01:01 ID:???
- ここはSQL文のスレだな
MySQL 総合 Part17
http://pc11.2ch.net/test/read.cgi/db/1258928470/
- 343 :340:2009/12/12(土) 11:08:20 ID:???
- 誘導サンクス!
- 344 :NAME IS NULL:2009/12/12(土) 14:43:10 ID:???
- 初歩的な内容だと思うのですが・・・・
(問)
ID | NAME | DATA
--+-------+-----
1 | tanaka | aa
2 | satou | bb
3 | suzuki | cc
例えばこんなテーブルがあったときに
IDとNAMEに関してマッチするレコードを
取得するとしたら
WHERE ID = 1 AND NAME = 'tanaka'
としますけど、マッチングの条件が複数あるときって
WHERE (ID = 1 AND NAME = 'tanaka')
OR (ID = 2 AND NAME = 'satou')
こんなふうに単純に書くしかないでしょうか?
マッチング条件の対象列がひとつなら
WHERE NAME in ('satou', 'suzuki')
とできますが、複数列の場合にもこういうふうに
まとめて書く方法がないかと思いまして・・・
- 345 :NAME IS NULL:2009/12/12(土) 14:49:44 ID:???
- ない。
- 346 :NAME IS NULL:2009/12/12(土) 14:55:01 ID:???
- そうですか・・
どうもありがとうございました。
- 347 :NAME IS NULL:2009/12/12(土) 16:53:04 ID:???
- 少なくともOracleなら
where (ID, NAME) in ((1, 'tanaka'), (2, 'satou'))
とか書けるけどな。
他は知らない。
- 348 :NAME IS NULL:2009/12/12(土) 18:05:39 ID:???
- >>347
おお!それで出来ました!
ありがとうございます!
- 349 :NAME IS NULL:2009/12/13(日) 16:57:39 ID:6mnFzqzE
- MYSQL5.1使ってます。
結合しつつ、最新データの抽出がうまぐできないのでよろしくお願いします。
(idlist テーブル)
id name taxfree
1 A 1
2 B 0
3 C 1
4 D 0
5 E 0
6 F 1
(sales テーブル)
id data price
1 12/8 3000
1 12/7 2500
2 12/8 2000
2 12/7 2800
3 12/8 150
3 12/7 200
6 12/5 500
上記2つのテーブルから、
下記の形式のように、idlistから taxfree=1 のものをまず表示し、
最新日付のデータか、最新日付が無い場合一番近い日付のデータを表示したいと考えています。
id name data price
1 A 12/8 3000
3 C 12/8 150
6 F 12/5 500
SELECT
idlist.id AS id ,idlist.name AS name ,sales.data AS data ,sales.price AS price
FROM idlist
LEFT JOIN sales
ON idlist.id=sales.id
AND sales.data=(SELECT max(DATA) FROM sales )
WHERE idlist.taxfree=1
これだとやたら重いのと、最新日付以外は表示されません。
どうぞよろしくお願いします。
- 350 :NAME IS NULL:2009/12/14(月) 02:58:08 ID:???
- >>349
>>4とjoin
- 351 :NAME IS NULL:2009/12/14(月) 18:55:19 ID:???
- >>4 でもうjoinが使われてるんで難しいね
- 352 :NAME IS NULL:2009/12/14(月) 21:32:26 ID:???
- 要はid毎の最新日付のレコードを取得すればいいわけだから、>>4にtaxfreeの条件を
追加すればいいはず。
ただ確かに、>>4はカラムやテーブルの追加などの応用がしにくいという問題がある。
個人的には not exists を使った相関サブクエリがお勧め。
select idlist.id, idlist.name, sales.data, sales.price
from idlist A
join sales B on B.id = A.id
where A.taxfree = 1
-- ここまでは単なるjoin
and not exists (
select * from sales
-- グルーピングに用いるキー属性は'='で…(a)
where id = B.id
-- それ以外は同一キーを排除できる何らかの条件を指定…(b)
and data > B.data
)
ここでBのキー属性がもっと多い場合など、グルーピングの単位を変更する必要がある
ならば(a)にその属性を追加すればよいし、(b)は同一値を排除できればよいので、'>'でも
'<'でも、あるいは必要に応じてその他の条件に変更してよい。
「属性Xが最大のもののうち属性Yが最小のもの」などという複合条件でも同じ考え方で
容易に応用できる。
- 353 :NAME IS NULL:2009/12/14(月) 23:09:02 ID:???
- なんで>>4じゃダメだって言ってるのかイマイチワカンネ
select C.ID,
C.NAME,
A.DATA,
A.PRICE
from SALES A
inner join
(select ID,
max(DATA) as MAX_DATA
from SALES
group by ID
) B
on A.ID = B.ID
and A.DATA = B.MAX_DATA
right outer join
IDLIST C
on A.ID = C.ID
where C.TAXFREE = 1
;
- 354 :NAME IS NULL:2009/12/15(火) 06:24:40 ID:???
- >>353 さんのselect文でうまくいきました。
ありがとうございました。
初心者なのでよくわからないんですが、外部結合をするとコストかかるのは常識なんですかね。
1000×20万レコードくらいで10秒ほどかかってしまいます。(ローカル環境)
さくらサーバーで実行すると2秒くらいなので気にはしてないんですが。
>>352 のほうは何故かうまくいかずで・・・(わたしの書き方がマズかった可能性大です。)
- 355 :NAME IS NULL:2009/12/15(火) 08:11:58 ID:???
- 外部結合のコスト云々より、>>4の処理で最新行だけを取得するのに2回スキャンかかるからだろうな。
高速化するのなら各RDBMSにあわせた書き方がある。>>4は汎用。
MySQLならこんなのはどぉ? 推奨できないけどw
SELECT A.id,A.name,C.data,C.price FROM
(SELECT * FROM idlist WHERE taxfree=1)AS A
JOIN (SELECT id,max(data)AS data,price FROM
(SELECT * FROM sales ORDER BY id,data DESC) AS B GROUP BY id
) AS C USING(id);
MySQLの仕様って細かく追っていないけど、PostgreSQLのDISTINCT ONと同等になったのかな。
4.xの時代はORDER BY句はなし(2重目のサブクエリが不要)でもいけてた気がするんだけどなぁ。
- 356 :NAME IS NULL:2009/12/15(火) 15:45:36 ID:???
- >>355
レスどうもです。
MySQL5.1でやりましたが、結果・・・爆速(0.2秒)でした!
有難うございます!
- 357 :NAME IS NULL:2009/12/16(水) 14:47:00 ID:???
- PostgresSQL 8.3 での全文検索についてですが、
http://www.postgresql.jp/document/current/html/textsearch-tables.html
ここの冒頭にある例文を参考にして、
CREATE TABLE hoge (
name TEXT
);
INSERT INTO hoge (name) VALUES ('aaa');
INSERT INTO hoge (name) VALUES ('abc');
INSERT INTO hoge (name) VALUES ('aac');
INSERT INTO hoge (name) VALUES ('bbb');
を実行した後に
SELECT * FROM hoge
WHERE to_tsvector('english', name) @@ to_tsquery('english', 'a');
を実行したのですが、結果が返ってきません。
(aaa, abc, aacの3レコード返ってきてほしい)
条件を変えて
SELECT * FROM hoge
WHERE to_tsvector('english', name) @@ to_tsquery('english', 'aaa');
とすると1レコード(aaa)返ってくるのですが…
何か勘違いや基本的な見落としをしているでしょうか?
- 358 :NAME IS NULL:2009/12/16(水) 15:04:32 ID:???
- スレ違いっぽいな。
Posgreは知らんけど、全文検索って、形態素解析とかでキーワードに分割して、
そのキーワードで検索するんじゃないの?
となると、'a' なんてのはキーワードとして登録されないと思うよ。
- 359 :NAME IS NULL:2009/12/16(水) 15:17:15 ID:???
- なるほど、そういうことだったのですね。
ありがとうございます。
なお LIKE を使うことで当初の目的は果たせました。
# すみません、確かにスレ違いな気がします
- 360 :NAME IS NULL:2009/12/18(金) 12:00:33 ID:GtpUvhEu
- すみません
AccessのSQLで、日付を絞り込む構文教えてください
絞り込み対象日付、開始日付、終了日付
ただし終了日付がnullの場合があり、代わりに2999年12月31を代入するといった処理をしたいです。
- 361 :NAME IS NULL:2009/12/18(金) 20:27:57 ID:???
- アドバイスをお願いします。
PostgreSQL8.3
word varchar256
全文検索についてですが、varchar256 のフィールドに対して検索を
行っています。
SELECT * FROM hoge WHERE
to_tsvector('english', word) @@ to_tsquery('english', 'aaa');
検索自体は問題ないのですが、ストップワードに登録されているもの
(a や i など)が破棄されてしまい困っています。
ネットで調べたところ、english.stop でストップワードを設定して
いるようでしたので、ここから該当のものを削除しました。しかし、
to_tsvector()では削除したものが破棄されずに残り、to_tsquery()
では削除したものが破棄されて検索ができません。
現状
to_tsvector('english', 'a pen') > 'a' 'pen'
to_tsquery('english', 'a pen') > 'pen'
to_tsquery()のストップワードはどこで設定されているのでしょうか?
よろしくお願いします。
- 362 :361:2009/12/18(金) 20:35:45 ID:???
- すみません、追記です。
希望
to_tsvector('english', 'a pen') > 'a' 'pen'
to_tsquery('english', 'a pen') > 'a' 'pen'
- 363 :361:2009/12/18(金) 22:29:18 ID:???
- 自己解決しました。
- 364 :NAME IS NULL:2009/12/18(金) 22:32:30 ID:???
- よかったね。スレ違いだから、二度と来んな。
- 365 :NAME IS NULL:2009/12/20(日) 13:41:41 ID:???
- >>360
AccessだとCOALESCEが無いみたいだから、代わりにIIF()使ってみては
- 366 :NAME IS NULL:2009/12/23(水) 17:23:20 ID:???
- あるテーブルからランダムに5つ選択する必要があるんですけど、SQLでの書き方がわかりません。
select *, rand() randval from employees where deleted is false order by randval limit 5;
なんてやってるんですけど、たくさんのレコードがある時に、たかがランダムに5つ選ぶためだけにたくさんのレコードをソートするのもばからしいように思います。
なんかかっこいい方法あれば教えてください。
- 367 :NAME IS NULL:2009/12/23(水) 17:26:53 ID:???
- 連番のキーがあれば、それでやることはできるだろうけど、そういうの(ROWNUM とか含む)
がなければ、ソートするしかないだろう。
- 368 :NAME IS NULL:2009/12/23(水) 17:55:51 ID:???
- >>367
おお、連番のキーがあればできるんですか?
今は
id integer primary key auto_increment
というのがあるので、これでできますか?おしえてください!
- 369 :NAME IS NULL:2009/12/23(水) 18:07:46 ID:???
- DBMS がわからんので、rand() 関数の仕様がわからないけど、
where id in (rand(), rand(), rand(), rand(), rand())
みたいなイメージでやればいい。当然、rand() から、id の範囲内に収まるように
計算することを忘れずに。
- 370 :NAME IS NULL:2009/12/23(水) 18:18:07 ID:???
- >>369
うーん、その方法だと、現時点でのidの最大値がわかってないといけなさそうだし、
なにより where 句での条件指定ができなくないですか?
今回は>>366に書いたように、where deleted = false みたいな条件がはいるので、
where id in (rand(), rand(), rand(), ... ) の条件と deleted = false が重なると、
検索結果が5件より少なくなる可能性があります。
- 371 :NAME IS NULL:2009/12/23(水) 18:34:02 ID:???
- 後付君ウザイです。
- 372 :NAME IS NULL:2009/12/23(水) 18:45:40 ID:???
- まぁまぁ、deleted is false は最初から書いてあったし。
ただ、DBMSが何かは書いて欲しいところ。auto_incrementってあるからMySQLだとは思うけどね。
んで、where句でrand()を使うとインデックスを利用しなかったりするから、
ソートしてlimit 5でいいんじゃね。他にいい方法は無いと思うよ。
- 373 :NAME IS NULL:2009/12/23(水) 20:08:31 ID:???
- >>372
> ただ、DBMSが何かは書いて欲しいところ。auto_incrementってあるからMySQLだとは思うけどね。
DBはMySQL4です。DBを限定すると、もっといい方法があったりするんでしょうか。
> 他にいい方法は無いと思うよ。
やっぱりそうですか。まあ、ないということがわかっただけでもありがたいです。
ありがとうございました。
- 374 :NAME IS NULL:2009/12/23(水) 22:16:25 ID:???
- 特にMySQLとかだったらバージョンによってはサブクエリが使えないとか、あるいはDBMS毎に固有の関数・句が
有るとかないとかで書き方が変わる
と言う事は方法を提示してもそちらでは使えない…なんて事があると言う事は容易に想像できると思うのだが。
- 375 :NAME IS NULL:2009/12/23(水) 22:36:40 ID:???
- DBMSによる独自拡張があるからね
MySQL4なら拡張以前の問題があるけど
- 376 :372:2009/12/23(水) 23:52:30 ID:???
- ちょっと補足(半分言い訳)
「他にいい方法は無いと思うよ」とは書いたが、あくまで「思うよ」だからな。
ま、SQLだけでしかもMySQL4なら間違ってはいないと"思う"けどね。
ただ、乱数を付加しつつ全行取得してソートのコスト(行数による)が非常に高いのであれば、
ホスト言語などで乱数を生成して
SELECT * FROM employee WHERE deleted is false AND id = 乱数;
を5件取得するまで繰り返した方が速いかもね。
auto_incrementの現在値(=現在の最大値)を取り出す方法も全スキャンmax(id)じゃなく
関数かシステムカタログからで取り出せるんじゃね。MySQLでの方法を俺は知らないけど。
WITH RECURSIVEをサポートするDBMSならSQLだけで済みそうだがな。
- 377 :NAME IS NULL:2009/12/26(土) 19:04:21 ID:dwahwS+t
- oracle 10gのUPDATE文で質問です。
Aテーブル
aaa|ddd
Bテーブル
aaa|bbb
Cテーブル
bbb|ccc
Aテーブルに対して、カラムaaaでBテーブルが紐づき、
Bテーブルに対して、カラムbbbでCテーブルが紐づくとします。
(つまり、Aテーブルのレコード1件は、Bテーブルを経由してCテーブルのレコード1件と紐づく)
ここで、A.ddd = 'X'のとき、C.ccc = 'Y'に更新したいのですが
下記の文であってますでしょうか?
また、もっと効率のいい方法はありますでしょうか?
update C set C.ccc = 'Y' where C.bbb in
( select B.bbb from B where B.aaa in
( select A.aaa from A where A.ddd = 'X')
)
- 378 :NAME IS NULL:2009/12/26(土) 19:08:27 ID:???
- 連結しちゃった方が速そうな気もする。
- 379 :NAME IS NULL:2009/12/27(日) 12:56:27 ID:???
- >>377
update C set C.ccc = 'Y'
where exists (select *
from A inner join B on A.aaa = B.aaa
where A.ddd = 'X' and B.bbb = C.bbb
)
動かせる環境が無いので、typoはご容赦。
- 380 :377:2009/12/27(日) 16:44:31 ID:???
- >>378,379
ありがとうございます!
参考にさせていただきます。
- 381 :NAME IS NULL:2009/12/31(木) 17:30:56 ID:???
- 弁護士の名前(name)とその人の所属法律事務所の名称(ofic)から成るテーブルがあるとして、
法律事務所は弁護士がひとりしかいないところから300人以上いるところまでさまざまなので、
「所属する弁護士の数が多い事務所トップ10」 の事務所名と人数を select一発で表示させるには
どうすればいい?
自分で考えたのはサブクエリが二重になってしまったが、うまくやれば一重で済む気がする。
- 382 :NAME IS NULL:2009/12/31(木) 17:50:44 ID:???
- それはギャグで言っているのか?
- 383 :NAME IS NULL:2009/12/31(木) 19:27:02 ID:???
- いやマジ
- 384 :NAME IS NULL:2009/12/31(木) 19:30:19 ID:???
- サブクエリなんていらんよ。
- 385 :NAME IS NULL:2009/12/31(木) 20:18:40 ID:???
- 自己解決しますた。マジでサンクス
- 386 :NAME IS NULL:2009/12/31(木) 20:19:32 ID:???
- あ、サブクエリ一重じゃなくて全然使わない方法でです
- 387 :NAME IS NULL:2009/12/31(木) 20:21:37 ID:???
- どうやって解決したかを書くならともかく、そんな報告なんの意味もないからしなくていいよ。
- 388 :NAME IS NULL:2009/12/31(木) 20:44:44 ID:???
- そんな解決策書かれたって、なんの足しにもならんだろ。
- 389 :NAME IS NULL:2010/01/01(金) 16:48:49 ID:???
- select top 5 ofic, COUNT(name) from table group by ofic order by COUNT(name) desc
同人数の時にどうするかが書かれていないので考慮なしで。
- 390 :NAME IS NULL:2010/01/03(日) 00:15:51 ID:???
- 多いのベスト10じゃなくて200人以上の事務所とかいうんだったらサブクエリが必要だな
- 391 :NAME IS NULL:2010/01/03(日) 00:27:57 ID:???
- いらないだろ・・・。
- 392 :NAME IS NULL:2010/01/03(日) 11:59:52 ID:???
- having
- 393 :NAME IS NULL:2010/01/07(木) 00:52:36 ID:???
- SELECT文について質問です。
【質問テンプレ】
・PostgreSQL8
・テーブルデータ
テストデータ
名前 |1回目点数|2回目点数|
----+--------+--------|
田中 | 100 | 90 |
鈴木 | 80 | 80 |
成績マスタ
成績 | 点数 |
----+-------|
A | 100 |
B | 90 |
C | 80 |
・欲しい結果
名前 |成績(1回目)|成績(2回目)|
----+---------+---------|
田中 | A | B |
鈴木 | C | C |
・説明
2TABLEを連結してSELECTしたいのですが、テストデータの点数を下に、成績マスタから(1回目)と(2回目)の値をひっぱってくるにはどう書けばよいでしょうか。
手元に実行環境がないので机上で↓のようなSQLを考えてみました。ただ正常に動くとは思えませんorz
これでOKか、違っていたら教えてもらえませんか?
select 名前,成績 AS 成績(1回目),成績 AS 成績(2回目)FROM テストデータ
LEFT JOIN 成績マスタ.点数 ON テストデータ.点数
- 394 :NAME IS NULL:2010/01/07(木) 00:58:21 ID:???
- それじゃ無理。成績マスタを二回連結すればいい。
- 395 :NAME IS NULL:2010/01/07(木) 01:06:18 ID:???
- >>393
95点とかを考慮せず単純に考えた。
SELECT 名前,T2.成績,T3.成績 FROM テストデータ AS T1
JOIN 成績マスタ AS T2 ON T1.1回目点数 = T2.点数
JOIN 成績マスタ AS T3 ON T1.2回目点数 = T3.点数;
- 396 :NAME IS NULL:2010/01/07(木) 04:43:45 ID:???
- 成績マスタ
成績|点数FROM|点数TO|
----+--------+------+
A | 91| 100|
B | 81| 90|
C | 71| 80|
本当はこんなことしたいんじゃないの?
- 397 :NAME IS NULL:2010/01/07(木) 22:21:48 ID:???
- 基本的なことで申し訳ないんですけど、
あるテーブルから特定のデータが1件でも存在するかどうかの判断をしたいのですが、
COUNT()はテーブル内の全部のレコードを検索してしまうので、もっと高速でスマートな方法は無いか存じないでしょうか。
- 398 :NAME IS NULL:2010/01/07(木) 22:40:05 ID:???
- >>397
EXISTS
- 399 :NAME IS NULL:2010/01/07(木) 22:42:15 ID:???
- >>397
PostgreSQLならLIMIT
FirebirdならTOP
OracleならROWNUM
ほかのDBはシラネ。調べるのも面倒
- 400 :398:2010/01/07(木) 22:43:21 ID:???
- 何となく脊髄反射してしまったが、
「特定の条件」でインデックス検索するようであれば、COUNT(*)でも全部のレコードを検索しないし、
インデックス検索しなければ、EXISTSでも全部のレコードを検索してしまうわな。
- 401 :398:2010/01/07(木) 22:47:01 ID:???
- 何度もゴメソ。
EXISTSは1レコード見つかった時点で検索をやめるから、常に全レコードという分けじゃないな。
そういう点ではCOUNT(*)より速いか。
- 402 :NAME IS NULL:2010/01/07(木) 22:56:36 ID:???
- どうやらこれが爆速みたい。でもtrue/false返しているわけじゃない(0/1が返ってくる)からなんか怪しいなあ。
SELECT
EXISTS(SELECT * FROM ユーザ WHERE ユーザID IN('id'))
- 403 :NAME IS NULL:2010/01/08(金) 04:08:57 ID:???
- >>402
それが早いかどうかは実際のデータ量とインデックスの有無とデータの分布とオプティマイザの賢さによるので
お前が実験したときにたまたま早くてもあまり意味がない
ちなみにexistsは通常、真か偽か判定するのに使う。0/1が帰ってくるのは
お前の実験した処理系で真と偽が1と0に評価されてるだけだ
一般的に言えるのは、行があるかないかだけ判断すればよく、その行数まで必要ないなら
count使う必要はないだろう、ってぐらい
exists使ったことないってやつ結構多いんだろうなぁ
- 404 :NAME IS NULL:2010/01/09(土) 13:09:23 ID:???
- 多いよ。そして、existsとかいうやつを使わないように書き直してよ、とお願いされたりする。
- 405 :NAME IS NULL:2010/01/10(日) 04:06:38 ID:???
- 知らないものにはフタだね・・・
どうして勉強しようとしないのだろう
- 406 :NAME IS NULL:2010/01/12(火) 15:06:26 ID:5/3GZMUC
- 申し訳ありませんが、質問させてください
CREATE TABLE dog_cat (
dog_id INT(11),
cat_id CHAR(10),
PRIMARY KEY (dog_id, cat_id),
KEY dog_id (dog_id, cat_id) //【A】
);
CREATE TABLE dog (
dog_id INT(11) AUTO_INCREMENT,
〜
PRIMARY KEY (dog_id),
UNIQUE dog_id (dog_id), //【B】
KEY dog_id_2 (dog_id) //【C】
);
の【A】〜【C】の意味がわかりません
【A】 : KEYというものが分かりません。
自分の勉強不足でしょうが、持ってる本にも載っていないし、ネットで検索しても主キー(PRIMARY KEY)ばかり出てきます。
dog_id,とcat_idをKEYというデータ型に設定しているのでしょうが、その前(2つの引数の前)に書かれているdog_idとは何を意味しているのでしょうか?
【B】 : 上記【A】と同じく、dog_idをUNIQUE型に設定しているのでしょうが、その前に書かれているdog_idというのが分かりません。
例えばココ(http://www.techscore.com/tech/sql/03_03.html)などのUNIQUEの項目を参照してもUNIQUEの後には文字が無く説明もありません。
【C】 : 今度はdog_id_2と、2が付いていますが、この一文が何を意味したいのかとか、何の役割があるのかが分かりません
すみませんが教えていただければと思います
- 407 :NAME IS NULL:2010/01/12(火) 18:59:44 ID:???
- >>406
>>1
つかそれぐらい自分が使ってるDBMSのマニュアル探せ
- 408 :NAME IS NULL:2010/01/13(水) 00:38:00 ID:???
- PRIMARY KEYってnvarchar型にも設定していいんですか?
- 409 :NAME IS NULL:2010/01/13(水) 00:43:49 ID:???
- いいよ。
- 410 :NAME IS NULL:2010/01/13(水) 01:07:14 ID:???
- ありがとう!
- 411 :NAME IS NULL:2010/01/13(水) 01:08:02 ID:???
- お勧めしないけどな。
- 412 :NAME IS NULL:2010/01/13(水) 01:34:34 ID:???
- >>411
何故ですか?
- 413 :NAME IS NULL:2010/01/13(水) 01:36:04 ID:???
- 2chのスレタイ一覧を格納してるんだけど
1263039170.dat<>gyuttoについて語るスレ (3)
9240912012.dat<>【2ちゃんねる10周年】1000人BINGOでお試し●ゲット!!【無料】 (2)
9240912701.dat<>【設定無料】ドメイン移転を歓迎するレンタルサーバー【無制限】 (1)
これの .datはずしてintで格納したほうがいいかね?
こんな感じで書いてみたんだけど・・・
CREATE TABLE subject (
dat char(15)
, title nvarchar(256)
, response int(4)
, rank int(4)
, bbs nvarchar(20)
, PRIMARY KEY (dat)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SQL初挑戦なんでよくわからんw
- 414 :NAME IS NULL:2010/01/13(水) 05:16:17 ID:???
- intに収まるのならどうぞ
- 415 :NAME IS NULL:2010/01/13(水) 06:28:43 ID:???
- あ(・∀・)り(・∀・)が(・∀・)と(・∀・)う!
- 416 :NAME IS NULL:2010/01/13(水) 07:37:00 ID:???
- Primary Keyが重複ってエラーでるの無視するにはどうすればいいですか?
DBD::mysql::st execute failed: Duplicate entry '1111'' for key 'PRIMARY'
- 417 :NAME IS NULL:2010/01/13(水) 10:47:46 ID:???
- >>416
IGNORE オプションを付けてinsert
http://dev.mysql.com/doc/refman/4.1/ja/insert.html
けど、それって良い事なの?
- 418 :417:2010/01/13(水) 10:49:33 ID:???
- ごめん
間違ってたんで無視してくださいな
- 419 :NAME IS NULL:2010/01/13(水) 16:37:09 ID:???
- メモリーに入りきらないデータの検索ってどうやってやってるのですか?
- 420 :NAME IS NULL:2010/01/13(水) 18:50:41 ID:4+ds+P+d
- 質問させてください。今130万×130万くらいの巨大な行列があります。
ただ要素は、ほとんどが0で一行に数字が入っているのは最大32までで、
負の数もありません。
これで集合知プログラミング10章の非負値行列因子分解をしたいのですが、
あまりにも大きいのでとりあえずデータベース板に来ましたが、
MySQLの勉強がてらこの問題を解けないかと思っているのですが、
MySQLはこのような用途に向いていますか?またよさげなライブラリみたいなのは
ありますか?どこから手を付けていいか分からないのですがよろしくお願いします。
- 421 :NAME IS NULL:2010/01/13(水) 19:10:27 ID:???
- >>419
ディスクを使うに決まってるじゃない
>>420
よく分からんけど向いてないんじゃね?
一般的に言ってRDBMSは分析とか計算は苦手
特定の問題を解くために特別な機能が用意されてる場合もあるけど
それは本職じゃない
- 422 :NAME IS NULL:2010/01/13(水) 19:17:09 ID:???
- むしろ、Rとかみたいな統計ソフトの出番じゃね?
- 423 :420:2010/01/13(水) 21:09:08 ID:???
- >>422
これですか?
http://cse.naro.affrc.go.jp/takezawa/r-tips/r/21.html
これって値を設定しないところは0としてメモリは使わないとか
なってるんでしょうか?いまいち分かりませんが板違いですよね。
ここ行ってきます。
統計解析フリーソフト R 【第3章】
http://science6.2ch.net/test/read.cgi/math/1224142396/
- 424 :NAME IS NULL:2010/01/14(木) 09:32:37 ID:???
- 質問です。
以下のようなテーブルをもとに、
id , name , date , 売上
1 , りんご , 2010-01-12 , 350
1 , りんご , 2010-01-07 , 250
2 , みかん , 2010-01-12 , 450
2 , みかん , 2009-05-05 , 550
それを、売上があった日の1営業日後と3営業日後のそれぞれのidの価格も取得したいと考えております。
id , name , date , 売上 , 1営業日後売上 , 3営業日後売上
1 , りんご , 2010-01-12 , 350 , 400 , 500
1 , りんご , 2010-01-07 , 250 , 200 , 250
2 , みかん , 2010-01-10 , 450 , 500 , 300
2 , みかん , 2009-05-05 , 550 , 220 , 350
(ちなみに実際のdateはUNIXTIMEで格納しています。)
1営業日後にしているのは、休日の関係で1日後とできないからです。
ここまでやるのは厳しいでしょうか?
MYSQL 5.1.3
PHP 5.2.7
- 425 :NAME IS NULL:2010/01/14(木) 09:41:21 ID:???
- すいません上の質問はミスです。
改めまして・・・
SELECT * FROM tableA WHERE s_id = 7
というSQLで以下のように表示されるのですが、
id , code , name , date , 売上
1 , 7 , りんご , 2010-01-12 , 350
1 , 7 , りんご , 2010-01-07 , 250
2 , 7 , みかん , 2010-01-12 , 450
2 , 7 , みかん , 2009-05-05 , 550
それを、売上があった日の1営業日後と3営業日後のそれぞれのidの価格も取得したいと考えております。
id , code , name , date , 売上 , 1営業日後売上 , 3営業日後売上
1 , 7 , りんご , 2010-01-12 , 350 , 400 , 500
1 , 7 , りんご , 2010-01-07 , 250 , 200 , 250
2 , 7 , みかん , 2010-01-10 , 450 , 500 , 300
2 , 7 , みかん , 2009-05-05 , 550 , 220 , 350
(ちなみに実際のdateはUNIXTIMEで格納しています。)
1営業日後にしているのは、休日の関係で1日後とできないからです。
ここまでやるのは厳しいでしょうか?
MYSQL 5.1.3
PHP 5.2.7
- 426 :NAME IS NULL:2010/01/14(木) 09:43:31 ID:???
- 3行目 SELECT * FROM tableA WHERE code = 7
でしたね・・・。一服してきます・・・。
- 427 :NAME IS NULL:2010/01/14(木) 12:19:27 ID:???
- table sample
id int(11)
code int(11)
name varchar(10)
uriage_date date
uriage int(11)
select id,code,name,
sum(
case uriage_date
when ADDDATE(sysdate(),interval 1 day) then
uriage
else 0
end ) as day_after_1uriage,
sum(
case uriage_date
when ADDDATE(sysdate(),interval 3 day) then
uriage
else 0
end ) as day_after_3uriage
from sample
where
code=7;
みたいな?
- 428 :427:2010/01/14(木) 12:20:13 ID:???
- 営業日の所は判らんw
- 429 :NAME IS NULL:2010/01/14(木) 13:14:02 ID:???
- >>419 421
検索した情報によると
メモリーに入りきらない場合は
メモリー一杯によみこんで全部なめてから
次の領域をメモリーに読み込んで
同じようになめてくそうな
検索方法を自分で作って組み込む場合は、
この辺も気にして組まないといけないんだろうか
- 430 :NAME IS NULL:2010/01/14(木) 15:26:54 ID:???
- >>427
返信どうもです。
試したのですが1日後と3日後を取得してくれず、それぞれ0と表示されました。
あと、code=7 が複数該当していても1件しか表示してくれませんでした。
- 431 :NAME IS NULL:2010/01/14(木) 16:36:10 ID:???
- >>424,425
1 , 7 , りんご , 2010-01-12 , 350 , 400 , 500
この、400とか500とかいう数字はどっからでてきたんだ?
- 432 :NAME IS NULL:2010/01/14(木) 17:14:56 ID:???
- >>431
id , code , name , date , 売上
1 , 7 , りんご , 2010-01-12 , 350
のような形式のデータがたくさんあって、
>>425 に書いてるのはその一部だけで、
1営業日後売上 , 3営業日後売上のデータはサンプルです。
- 433 :NAME IS NULL:2010/01/14(木) 19:38:04 ID:???
- >432
足りないのはやりたいことをまとめる能力か他人に伝える能力か
営業日カウントの方法がまったく不明なので
とりあえず、該当id,codeでdateが1日後の売上の合計と、同3日後だとして
select
id,code,name,date,売上,
(select sum(売上) from tableA A1 WHERE A1.id=A.id and A1.code=A.code and A1.date=ADDDATE(A.date,interval 1 day))as 1営業日後売上,
(select sum(売上) from tableA A3 WHERE A3.id=A.id and A3.code=A.code and A3.date=ADDDATE(A.date,interval 3 day))as 3営業日後売上
from tableA A
where code = 7
でできるんじゃないかな
MYSQLはよく知らないし持ってないから試してない
日付の加算は>427から推測した
パフォーマンスとか言い出すなよ
これたぶんTableAなんて実表存在してないよな
- 434 :NAME IS NULL:2010/01/14(木) 22:25:29 ID:???
- ■DBMS名とバージョン
Oracle10g
■テーブルデータ
○荷物テーブル
id 中身id 荷受け
1 1 2009/12/11
2 1 2009/12/21
3 2 2010/12/25
○中身テーブル
id 品物 重さ
1 本 500
2 テレビ 1000
○作業テーブル
荷物id 作業項目id 作業者名 作業状況
1 1 佐藤 完了
1 3 志村 作業中
2 1 鈴木 完了
2 2 鈴木 未
2 3 田中 未
3 1 佐藤 完了
3 3 田中 未
○作業項目テーブル
id 作業内容
1 品物を入れる
2 領収書を入れる
3 封をして発送する
■欲しい結果
荷物id 品物 重さ 作業者名※1 作業内容※1 作業状況 対応班※2
2 本 500 鈴木 領収書を入れる 未 2
3 テレビ 1000 田中 領収書を入れる 未 1
※1 作業状況が完了以外かつ作業項目idが一番小さいもの
※2 重さが1000以上→作業班1、作業者名が鈴木かつ作業状況が未→作業班2、作業状況にかかわらず、作業者名に田中がある荷物→作業班3
(班1 > 班2 > 班3の順で優先し、荷物idを重複させない)
■説明
荷受けが2009/12/31以前の荷物かつ対応班が存在するものを抽出したいです。
荷物は沢山ありますのでパフォーマンスもできれば考慮したいです。
「パッとわからないけどちょっと考えればわかるだろJK」→「2時間考えてもできないorz」(今ここ)
- 435 :NAME IS NULL:2010/01/14(木) 22:42:55 ID:???
- そんなに難しくないだろ。
少しは自分で考えろよ。
- 436 :NAME IS NULL:2010/01/14(木) 22:51:27 ID:???
- 面倒なのは、作業テーブルの部分と対応班のところか。
1. まず、荷物テーブルと中身テーブルをjoinする。
2. 作業テーブルと作業内容テーブルをjoinする
3. 2を荷物idでグループ化し、作業状況が完了以外で一番作業項目idが小さい奴を抽出する。
4. 1と3をjoinする
5. 対応班はCASEとか使って出力する
って感じでいいんかな。
- 437 :434:2010/01/15(金) 00:00:13 ID:???
- ありがとうございます。
対応班1、対応班2、対応班3とバラバラにならばそれぞれSQLを書いて出すことはできました。
あとはそれぞれをまとめて重複しているidを削除すればなんとかなりそうです。
重複削除の処理ですが、例えば
table
id 対応班 value1 value2 ...
1 1 ...
1 2 ...
2 2 ...
2 3 ...
3 1 ...
というテーブルがある場合、
id 対応班 value1 value2 ...
1 1 ...
2 2 ...
3 1 ...
と最小の対応班をもつ行を出力するのは
SELECT 略 FROM table main JOIN (SELECT id, min(対応班) AS 対応班 FROM table GROUP BY id) sub
ON main.id = sub.id AND main.対応班 = sub.対応班
とすればできそうですが、もう少しスマートな方法はないでしょうか?
- 438 :NAME IS NULL:2010/01/15(金) 00:36:20 ID:???
- >>425
営業日カレンダー持てば?
- 439 :NAME IS NULL:2010/01/15(金) 01:59:13 ID:e1+mTjHW
- <DB名>
mysql
<バージョン>
Ver 14.12 Distrib 5.0.75, for debian-linux-gnu (i486) using readline 5.2
<テーブルデータ>
データなし。
create table table1 (u_id int(4) not null);でテーブルを作成した状態。
<ほしい結果>
+------+
| u_id |
+------+
| 1 |
| 3 |
+------+
<質問内容>
http://www.postgresql.jp/document/pg800doc/html/sql-savepoint.htmlから下記のコマンドコピーして実行した。
BEGIN;
INSERT INTO table1 VALUES (1);
SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (2);
ROLLBACK TO SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (3);
COMMIT;
なぜか下記のようになってしまう。
+------+
| u_id |
+------+
| 1 |
| 2 |
| 3 |
+------+
問題はどこにあるでしょうか。
- 440 :NAME IS NULL:2010/01/15(金) 04:16:08 ID:???
- >>434
これ作業日と荷受日は同じでいいの?
- 441 :NAME IS NULL:2010/01/15(金) 10:13:14 ID:???
- >>438
営業日カレンダーとはどんなものでしょう?
日付をunixtime(int型)で格納してあるので、1営業日後や3営業日後の判定がうまくできずで・・
1日後でいいなら
FROM_UNIXTIME(200201696)+86400
とかでいいんでしょうけど。
- 442 :NAME IS NULL:2010/01/15(金) 12:25:00 ID:7GILZKdj
- Postgres8.3.xを使ってます。
DB:hogeDbA
Schema:hogeScA
Table:hogeTableA
DB:hogeDbB
Schema:hogeScB
Table:hogeTableB
hogeTableAとhogeTableBのjoinはできますか?
- 443 :NAME IS NULL:2010/01/15(金) 17:29:22 ID:???
- >>442
普通は無理だが、何か手があった気がする。
スレ違いなんで以下のスレでどーぞ。
PostgreSQL Part.7
http://pc11.2ch.net/test/read.cgi/db/1256300618/
- 444 :NAME IS NULL:2010/01/15(金) 19:35:16 ID:???
- >>439
MyISAM使ってました
なんて落ちは無いよね?
- 445 :NAME IS NULL:2010/01/17(日) 06:23:20 ID:???
- MySQL 5.1での質問です。
A B C
1 q name1
2 w name2
3 e name3
4 q name4
5 t name5
上記テーブルのB列の重複を除いたA,B,C列がほしい場合
SELECT DISTINCT B FROM table_name;
ではB列の重複を除くだけで他の列がとれません。他の列も併せて取得する場合はどのような解決策がありますか?
望んでる結果は以下のものです。
A B C
1 q name1
2 w name2
3 e name3
5 t name5
よろしくおねがいします
- 446 :NAME IS NULL:2010/01/17(日) 07:41:10 ID:???
- >>445
>>4
- 447 :NAME IS NULL:2010/01/17(日) 08:57:49 ID:???
- >>446
ありがとうございます。
>>4 を参考に組み立てると以下でいいんでしょうか?
カラム名のせいで見づらいですが
SELECT A.A,
A.B
A.C
FROM tablename AS A
INNER JOIN
(SELECT A,
MAX(B) AS TEST,
C
FROM tablename
GROUP BY A
)B
ON A.A = B.A
AND A.B = B.TEST;
上記SQLだと全A(カラム)を拾ってきてしまいます。
- 448 :NAME IS NULL:2010/01/17(日) 09:19:34 ID:???
- >>4は「各idに対してdateが最大」の行を抽出している
>>445なら「各Bに対してAが最小」とか「各Bに対してCが最大」とか
になるんじゃないの?
- 449 :NAME IS NULL:2010/01/17(日) 13:25:00 ID:???
- sql初心者です。次のような統計を出したいのですが、行き詰まっています。
存在する列 pref_no(char) ,city_name<char), population(var_char)
表名 japan
何をしたいか?:各都道府県列(pref_no)ごとに人口(population)最大の都市名を降順に
一都市ずつ出したい。
打ち込んだ構文
select pref_no,city_name,population from japan
order by population desc;
たとえば
pref_no city_name population
25 otsu 330000
26 kyoto 1480000
27 osaka 2630000
27 sakai 820000
28 kobe 1540000
28 himeji 530000
29 nara 370000
というデータがあれば
27 osaka 2630000
28 kobe 1540000
26 kyoto 1480000
29 nara 370000
25 otsu 330000
というデータを出したいわけです。ちなみに使用している環境はmysqlで、INTERSECTが使えませんorz
- 450 :NAME IS NULL:2010/01/17(日) 13:27:01 ID:???
- >>449
>>4
- 451 :NAME IS NULL:2010/01/17(日) 13:33:32 ID:???
- mysql使ったこと無いが
population(var_char)であれば
25 otsu 330000
26 kyoto 1480000
だとotsu 330000の方が大きいと判断されるんじゃねーの
- 452 :NAME IS NULL:2010/01/17(日) 13:38:18 ID:???
- >>445
列A、列Cが昇順であるかどうかも本当のところわからない状態では、
RDBとしての設計が間違っているかも知れない。
重複した場合は最初のものでいい、と考えるなら完全に間違っている。
- 453 :NAME IS NULL:2010/01/17(日) 13:39:59 ID:???
- そういうのは設計スレでやれ。
- 454 :NAME IS NULL:2010/01/17(日) 13:41:15 ID:???
- >>450
ありがとうございます!>>4でうまくいかなかったのですが、改めて見直せばうまくいきました。
自己結合する表の中の列をMAXにするとうまくいくことを知り、とても勉強になりました。
- 455 :NAME IS NULL:2010/01/17(日) 13:45:30 ID:???
- >>451
すみません。int型です。別データと勘違いしてました。
- 456 :NAME IS NULL:2010/01/17(日) 17:13:40 ID:???
- >>453
設計の話ではなくて質問として成立しないと言っているような。
- 457 :NAME IS NULL:2010/01/17(日) 18:51:17 ID:???
- テンプレは役にたつなぁ
- 458 :449:2010/01/17(日) 18:59:09 ID:???
- 先程はどうもありがとうございます。あれから頑張って先頭列にrankという順位を付けてみたのですが、
この構文(成功はしてます)をこれ以上省略可能でしょうか?
select (select count(C.population)
from (select pref_no,max(population) as population from japan group by pref_no) as C
where C.population > A.population)+1 as rank,pref_no,city_name,population
from japan A join (select pref_no,max(population) as population from japan group by pref_no)
as B on (A.pref_no=B.pref_no and A.population=B.population)
order by rank;
- 459 :NAME IS NULL:2010/01/17(日) 19:03:13 ID:???
- すみません。列を表別名で修飾してませんでしたorz
select (select count(C.population)
from (select pref_no,max(population) as population from japan group by pref_no) as C
where C.population > A.population)+1 as rank,A.pref_no,A.city_name,A.population
from japan A join (select pref_no,max(population) as population from japan group by pref_no)
as B on (A.pref_no=B.pref_no and A.population=B.population)
order by rank;
- 460 :NAME IS NULL:2010/01/17(日) 19:09:41 ID:???
- DBMSによるがrankを簡単につけられる構文はあるよ。
またはCTEのように共通するsqlを1つにまとめたりできる。
- 461 :NAME IS NULL:2010/01/17(日) 21:11:33 ID:???
- >>456 うん、「設計」は適切でなかった。 name1が選択されてname4が排除される理由が見出せないというだけのことだね。
- 462 :445:2010/01/17(日) 22:20:33 ID:???
- >>461
すみません、間違いでした。実際はこうです。
A B C
1 q name1
2 w name2
3 e name3
4 q name1
5 t name4
で、以下の結果がほしい。
A B C
1 q name1
2 w name2
3 e name3
5 t name4
なんとか、がんばってみます。
- 463 :NAME IS NULL:2010/01/18(月) 06:39:30 ID:???
- >>462
まだ解決してなかったのかw
>>4そのまんまでIDをB、DATEをA、DATAをCに書き換えるだけだろ
(MAXをMINに書き換えるかどうかはご自由に)
- 464 :NAME IS NULL:2010/01/25(月) 04:27:19 ID:???
- OSQLGRIDを使っているのですが
DOSバッチでSQL文を実行できるソフト(できればフリー)
ありませんか?
OSQLGRIDでバッチを利用できるならば一番楽なんですが。
- 465 :464:2010/01/25(月) 04:28:55 ID:???
- できれば実行後にCSVファイルにしてくれるものがいいです
- 466 :NAME IS NULL:2010/01/25(月) 06:54:50 ID:???
- スレ違い
- 467 :NAME IS NULL:2010/01/26(火) 04:12:50 ID:???
- SQL*Plus使えばいいじゃん。「フリー」だからw
- 468 :NAME IS NULL:2010/01/26(火) 22:25:26 ID:???
- いじわゆ!
- 469 :NAME IS NULL:2010/01/27(水) 07:08:54 ID:???
- あっちょんぶりけ
- 470 :NAME IS NULL:2010/01/27(水) 19:31:30 ID:???
- あちょぷまうまう
- 471 :471:2010/01/29(金) 11:59:51 ID:???
- 【質問テンプレ】
・DBMS名とバージョン: SQLite 3
・テーブルデータ:長いため下記に記載
・欲しい結果:RSSリーダ(brief)のデータ(*.sqlite)から特定の記事データを削除したいです。
・説明:長いため下記に記載
●テーブルデータ
=======================================================================================================================
■entries
| id | feedID | primaryHash | secondaryHash | providerID | entryURL | date | read | updated | starred | deleted | bookmarkID |
-----------------------------------------------------------------------------------------------------------------------
■entries_text
| title | content | authors | tags |
-----------------------------------------------------------------------------------------------------------------------
■entries_text_content
| docid | c0title | c1content | c2authors | c3tags |
-----------------------------------------------------------------------------------------------------------------------
■sqlite_sequence
| name | seq |
=======================================================================================================================
- 472 :471:2010/01/29(金) 12:18:28 ID:???
- 1.【entries】テーブルの[deleted]フィールドが「 2 」の場合に、そのレコードを削除。
2.同時に、【entries_text_content】テーブルの[docid]フィールドが、1.で削除した
[id]フィールドと同じ値のレコードも削除。
3.更に同時に、【entries_textテーブル】から、1.で削除した[idフィールド]の値(数字)と
同じレコード番号のレコードを削除。 ※idフィールドがない為
4.その後、下記のフィールドの値を、1・2・3〜とリナンバリングしたい。
【entries】テーブルの[id]フィールド
【entries_text_content】テーブルの[docid]フィールド
5.そして、1.2.3.の三つのテーブルのレコード数がどれも同じ数だけあるか確認。
6.最後に、【sqlite_sequence】テーブルの[seq]フィールドに5.で確認したレコード数を
設定したい。
お手数ですが、以上よろしくお願いします。
- 473 :NAME IS NULL:2010/01/29(金) 18:06:24 ID:???
- トランザクションがかからんとか、そういう話?
- 474 :NAME IS NULL:2010/01/29(金) 19:34:54 ID:???
- SQL Server Compact 3.5 で、a_tbl と b_tbl のコードが一致した場合に
a_tbl に、b_tblの名前をセットするみたいなことしたいのですが無理ですか?
UPDATE a_tbl
SET name = b_tbl.name
FROM b_tbl
WHERE a_tbl.no = b_tbl.no
実行すると、「FROM 句はこのクエリの種類では使用できません」ってエラーになります。
SQL Server 2008 だと問題ないのですが・・・
- 475 :NAME IS NULL:2010/01/29(金) 20:22:02 ID:???
- コンパクト使ったことないからこれが通るかどうかわからんが
UPDATE a_tbl
SET a_tbl.name = b_tbl.name
FROM a_tbl JOIN b_tbl on a_tbl.no = b_tbl.no
が正解じゃないのか?
Fromにa_tblがないのにそれ通す2008も凄いと思うが
ちなみにUPDATEのFROM使わないでこんな書き方もある
UPDATE a_tbl
SET name = (select name FROM b_tbl WHERE no = a_tbl.no )
これもコンパクトで動くかどうかしらないが
こっちの方が通すシステムは多い気がする
まあ、これはデータ次第でエラー出る可能性はあるが
そんときは適当にmaxとっとけwそもそもの仕様がおかしいけどな
- 476 :NAME IS NULL:2010/01/29(金) 20:46:01 ID:???
- msdnみろ。compactにはupdateにfrom句は使えなかったはずだ。
- 477 :471:2010/01/29(金) 21:45:02 ID:???
- >>473
自分にレスしてくれてるのかな!?
SQLについてよく分からないもので・・・。
>>471の質問で自分で分かるのは、下の二つくらいでしてidフィールドが
ないテーブルからレコード削除するのにどうやるのがいいかとか、トリガ
とか、フィールドに1から番号を振りなおすとかが分からないのです。
DELETE FROM entries WHERE deleted = '2'
UPDATE sqlite_sequence SET seq = (SELECT count(*) FROM entries)
番号の振りなおしとかは、DOSでバッチとかJavaScriptやVBSとか、その他
を使用しないとできないのかな?
- 478 :NAME IS NULL:2010/01/29(金) 21:58:48 ID:???
- >>477
お前さんにだよ。
トランザクションは使えるみたいだけど、ストアドはないみたいだな。
普通にトランザクションかけて、プログラムで制御しかないだろ。
- 479 :471:2010/01/29(金) 22:52:07 ID:???
- >>478
レスどうもです。
SQLさっぱりなもので、調べても>>477が限界で・・・。 _| ̄|●lll
よろしければ>>471を実現するSQLを書いていただけると助かります。
- 480 :NAME IS NULL:2010/01/29(金) 22:59:11 ID:???
- だからプログラムでやれ、って言ってんじゃん。
どうせSQL単体でできるもんじゃないんだから、SQLにこだわる理由がわからん。
- 481 :471:2010/01/29(金) 23:07:44 ID:???
- >>480
レスありがとうございます。
SQLだけだと>>471-472は、できないんですね。
>>472で不可能な部分は除いて、可能な部分だけでも、SQLでどう書けばいいのか知りたいです。
SQL+JavaScript、SQL+VBS/WSH?で>>472を全て可能にするSQL+スクリプトを書いていただけると尚助かります。
ご存知の方いましたら、どうかよろしくお願いします。
- 482 :NAME IS NULL:2010/01/29(金) 23:14:28 ID:???
- 不可能ではない。が、あんまり意味はなさげ。
ところで、レコード番号って何?
- 483 :NAME IS NULL:2010/01/29(金) 23:18:27 ID:???
- 連番
http://oraclesqlpuzzle.hp.infoseek.co.jp/5-28.html
- 484 :471:2010/01/29(金) 23:25:12 ID:???
- >>482
レスありがとうございます。
【entries】と【entries_text_content】は、[id]と[docid]を元に消せると思うのですが、
【entries_text】には同じ数のレコードがあっても番号のフィールドがないので、
行番号というか、例えば【entries】の[id]が「 83 」のレコードを消したら、
【entries_text】の83番目のレコードも消したいという事で、レコード番号と書きました。
ただ、これも83番目を消したあとに、さらに【entries】の[id]が「 84 」を消そうとした場合
【entries_text】の83番目を消すと、その後の83番目は以前の84番目なのでその辺も
どうするのがいのか分からず・・・。
(番号の多い方から消していくとか、別にフィール作ってidを作成しておくとか!?)
- 485 :NAME IS NULL:2010/01/29(金) 23:26:03 ID:???
- RDBMSとしてありえない設計。普通にIDつけろよ。
- 486 :NAME IS NULL:2010/01/29(金) 23:29:43 ID:???
- 連番の振り直しって何で必要なの?
表示するときに加工すればいいだけじゃね?
- 487 :471:2010/01/29(金) 23:36:38 ID:???
- >>483
レスありがとうございます。
なるほどー。
>>472の自分が分かったSQLに、一つ追加され勉強になりました。
ただ、>>472の一連の動作がどうにも分からず!
>>485
レスありがとうございます。
そうですね。
RSSリーダの作者に言ってみます・・・。
すみませんが、ほとんど分かっていないので、とりあえず>>472を実行したいので、
>>472で不可能な部分は除いて、可能な部分だけでもSQLでどう書けばいいのか、
ご存知の方いましたら、SQLのみ、SQL+JavaScript、SQL+VBS/WSH?などで
書いていただけると大変助かります。
よろしくお願いします。
- 488 :NAME IS NULL:2010/01/29(金) 23:39:10 ID:???
- 丸投げ馬鹿は死ねと。
- 489 :NAME IS NULL:2010/01/29(金) 23:48:04 ID:???
- >>477とか>>483とかしか分からないってだけで丸投げしてないと思うが。
まあ俺が分かれば書いてやりたいところだが、俺も見に来てるだけだから分からないしな。
それより>>483以外は無駄にレス伸ばしているだけで意味ないから止めてくれ、ログ漁って調べるのに邪魔だ。
- 490 :NAME IS NULL:2010/01/29(金) 23:54:02 ID:???
- 1. delete from entries where deleted = 2
2. delete entries_text_content where docid in (select id from entries where deleted = 2)
* 順序考えろよ
3. rownum とかなきゃ無理
4. >>483
5. select count(*) を各テーブルに
6. update splite_sequence set seq = select count(*) from どれか
- 491 :NAME IS NULL:2010/01/30(土) 00:23:45 ID:???
- >490
3.は一時的にフィールド追加して>>483するとか方法は色々あるじゃん。
- 492 :NAME IS NULL:2010/01/30(土) 00:31:47 ID:???
- SQLiteではカラムの追加はできても削除はできないっぽい
まあ一時的にっつーか恒久的に追加すべきだが
てか現状のテーブル設計でentries_textはどうやって参照されるんだ?
- 493 :NAME IS NULL:2010/01/30(土) 00:40:00 ID:???
- 一時的にカラムを追加して、順序は誰が保証してくれんの?
- 494 :NAME IS NULL:2010/01/30(土) 06:35:37 ID:???
- >>492
briefのソース見れば分かる。
- 495 :NAME IS NULL:2010/01/30(土) 07:11:31 ID:???
- http://ww.himanavi.net/cgi/nade-1st/cbbs.cgi?mode=one&number=4559&type=4556&space=45&no=0
- 496 :NAME IS NULL:2010/01/30(土) 07:30:12 ID:???
- >>483,490
SQLiteじゃそれ実行できないよ。
- 497 :NAME IS NULL:2010/01/30(土) 08:49:58 ID:???
- >>490は、sqliteをspliteと間違ってたり酷いな(w
- 498 :NAME IS NULL:2010/01/30(土) 16:39:57 ID:???
- entries_textにIDをもたせずに連番っていうところが設計ミスだよな。
order byによって連番なんて変わるものだし他テーブルとの関連を結びつける何かが(IDが望ましい)必要となる。
sqliteにカスケード機能があるかどうか知らないが、あるとしたら設定するだけで削除は自動でなされる。
sqlite_sequenceは必要か?
欲しい時はcountとればいいと思うんだが。パフォーマンスも影響しないだろ。
- 499 :NAME IS NULL:2010/01/30(土) 17:40:13 ID:???
- entries_textのtitleと、entries_text_contentのc0titleが同じだからそれ使って削除できるな。
というか、briefのsqliteの構造について質問者にどうこういっても作者じゃないんだから意味ねーよ。
- 500 :NAME IS NULL:2010/02/09(火) 02:15:10 ID:???
- MYSQLなんですけど
date data
2010/01/01 hoge1
2010/01/05 hoge2
みたいなテーブルから
2010/01/01 hoge1
2010/01/02 NULL
2010/01/03 NULL
2010/01/04 NULL
2010/01/05 hoge2
のような結果の出せるSQLを求めてます。
select * from table between date '2010/01/01' and '2010/01/05'
とするとデータのある2レコードしか出ないのですが、
データがない部分も日付を出しつつ、デフォルトのデータないよっていう文字列を出せると助かります。
お助けください!
- 501 :NAME IS NULL:2010/02/09(火) 02:20:26 ID:???
- 単発SQLでやるような処理じゃないと思うけど
どうしてもやるなら日付テーブルを作っておいて外部結合するか
2010/01/02 NULL
2010/01/03 NULL
2010/01/04 NULL
をUNIONでくっつけるか
- 502 :NAME IS NULL:2010/02/09(火) 13:23:58 ID:???
- すいませんが、SQLを教えてください MySQL 5.1.35です
日付テーブル dailytbl
t_date 西暦日付
出来高aテーブル
code 1,2,3〜
a_date 西暦日付
dekidaka
出来高bテーブル
code a,b,c〜
a_date 西暦日付
dekidaka
日付テーブルのt_dateに沿って出来高を表示させたいです。
出来高aテーブルにしても、出来高bテーブルにしても出来高のない日が
ありますが、出来高のない日はdekidakaを0として表示させたい
イメージとしては
日付テーブル 出来高aテーブル 出来高bテーブル
t_date 1_dekidaka a_dekidaka
2010/01/28 1000 1500
2010/01/29 1026 0
2010/01/30 0 3400
2010/01/31 0 5500
2010/02/01 1020 0
2010/02/02 1030 0
2010/02/03 1040 4550
2010/02/04 1040 5500
2010/02/05 1000 0
みたいな感じなんですけど。
- 503 :NAME IS NULL:2010/02/09(火) 18:22:18 ID:???
- >>502
OUTER JOINとIFNULL()
- 504 :NAME IS NULL:2010/02/09(火) 18:29:25 ID:???
- t-sqlならこんな感じ。
select
t.t_date
ISNULL(a.dekidaka,0),
ISNULL(b.Dekidaka,0)
FROM
dailytbl t LEFT JOIN 出来高aテーブル a ON t.t_date = a.t_date
LEFT JOIN 出来高bテーブル b ON t.t_date = b.t_date
- 505 :502:2010/02/09(火) 21:32:45 ID:???
- なんか基本的な所を間違えているのか?
日付テーブルと出来高aテーブルとの2つだけでやっても、先程の例で言えば、
2010-01-30、2010-01-31の日付が出てこず orz
ちょっと考え直します。んでこの質問は閉じさせてください
176 KB
[ 2ちゃんねる 3億PV/日をささえる レンタルサーバー \877/2TB/100Mbps]
取りに行ったけどなかった。次は一時間後に取りに行くです。新着レスの表示
掲示板に戻る
全部
前100
次100
最新50
read.cgi ver 05.0.7.8 2008/11/13 アクチョン仮面 ★
FOX ★ DSO(Dynamic Shared Object)