このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。
SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。
質問するときはDBMS名を必ず付記してください。
【質問テンプレ】
・DBMS名とバージョン
・テーブルデータ
・欲しい結果
・説明
前スレ:
SQL質疑応答スレ 13問目
http://toro.2ch.net/test/read.cgi/db/1343899481/
よくある質問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
;
よくある質問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
;
よくある質問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によって文法がかなり違うので注意
よくある質問5
(問)
年月(YYYYMM)を指定し、その年月に対応する年月日を取得したい
例:201006を指定したら、以下の結果を得たい
20100601
20100602
・
・
・
20100630
(答)
SQLでは存在しないデータを生成することはできません。
この問いの場合は素直にカレンダーテーブルを用意しましょう。
どうしてもやりたければ以下のような方法もなくはないですが、
再帰問合せの本来の使い方ではありません。
やめておくことを強くお奨めします。
(PostgreSQLのgenerate_series()関数なら辛うじてセーフかもしれませんが
賛否の分かれるところでしょう。)
with TEMP (NUM) as (
select 1 from dual
union all
select NUM + 1 from TEMP where NUM < 31
)
select to_char(to_date('201006', 'YYYYMM') + NUM - 1, 'YYYYMMDD')
from TEMP
where to_date('201006', 'YYYYMM') + NUM - 1 < add_months(to_date('201006', 'YYYYMM'), 1)
;
※上記はOracleの場合です。(11gR2以降)
※再帰問合せをサポートするDBMSならこれを適当に改変すれば動きますが
どのみちお奨めしません。
以上、テンプレ終わり
同じデータベース内のあるテーブルが更新されたら、そのテーブルのデータに処理を行って別のテーブルに行を追加したいのですが
このような事をやる場合は他の言語(スクリプト言語など)を利用するしかないですか?
↑PostgreSQL をwebserver上で使う予定です
元のデータ追加にはpython上のプログラムから追加を行ったり問い合わせを行おうと思っています
おとしやがって
ストアド作ってトリガで実行
ありがとうございます
どの項目を勉強すればいいかわかりました
16 :
NAME IS NULL:2013/06/18(火) 22:12:58.28 ID:nx7caqYT
【質問テンプレ】
・DBMS名とバージョン
SQlite3をphpのPDOを使って(ローカルでやるのはいろいろインストール面倒なので@pagesの無料サーバでやってます)
・テーブルデータ
・欲しい結果
テーブルitemに「8 hhh」というレコードを挿入する(手順1)と同時に
テーブルstockに「8 xxx 0」,「8 yyy 0」というレコードを挿入したい(手順2)。
手順1の段階でautoincrementのitemId 8を知る方法はありますか?
もしくは手順1と手順2との間で”重複している可能性のある”「data hhh」から「8 hhh」のレコード1つだけをselectする方法はありますか?
・説明
17 :
NAME IS NULL:2013/06/18(火) 22:14:22.04 ID:nx7caqYT
20 :
NAME IS NULL:2013/06/19(水) 19:22:51.50 ID:9J5TodXQ
ありがとうございます。試してみます
22 :
NAME IS NULL:2013/06/21(金) 04:38:49.90 ID:6QPf6GEU
同一構造のテーブルが二つあり、
二つを見比べて片方にしかない値を抽出したい場合、どう書けばいいでしょうか?
EXCEPT(OracleだとMINUS)とかNOT EXISTSとかNOT INとか
やりようはあるけどそれだけの質問じゃあ
>>23になっちゃうな
まぁ普通にminusだろうな
tbl1 join tbl2(直積)とwhere句の組み合わせと、
tbl1 inner join tbl2 on (列x=列y)と、処理の速さを比較すると違ってきますか。
複数列にnullを含んだテーブル同士があって、
そのnullを含む列をつかって結合させたいんですが、
どうも処理が重たくて困っています。
nullは値がないので、インデックスがつくられないそうです。
nullが多ければ多いほど、処理って遅くなりますよね。
>>26 sql server 2008 r2のexpressなんで、メモリが1GBまでしか有効にならないみたいです。
有料版つかったら、ぱぱぱっと処理されるでしょうか。
30分が経過しました。
行を1行だけに絞って同じ処理をすると、一瞬で終わりました。
これが22万行あるので、時間がかかっているようです。
メモリに展開させられたらもっと処理が速くなるのかなって思いました。
>>26 上のjoinはinner joinのinnerが無いだけじゃないのか?
一般論だが
DBMSにはオプティマイザがあるので、SQLだけでどっちが早いかはわからない
null=nullは真ではない。null=値も真ではない
null可能の項目でも、null以外を選択するのにインデックスは有効
>>28 ありがとうございます
今、インデックスをあわてて勉強しています
ユニーク制約でつくられるインデックスしかなかったんです
すみません。
相関クエリを、通常のテーブルを相関させて書くことはできますが、
相関クエリを、導出テーブルをつかって書くことはできるでしょうか。
外側のテーブルとして導出テーブルを使います。
それを内側の相関クエリ内で使いたいんです。
しかし、as table1 T1 などとして導出テーブルに相関名をつけられません。
select
x
,y
,z
,(select SUM(S) from table2 T2 where T2.k = T1.k) as r
from
)
select x,y,z,k
from abc
) as table1 T1 ←導出テーブルでこのT1という相関名をつけられません
>>30 SQL SERVER 2008 R2 EXPRESSです。
よろしくお願いします。
導出テーブルに相関名ってSQLデフォルトでも普通はつけられないのかな。
それ相関名じゃなくない?
table1ってのが相関名だろ。相関名二つもつけれるか?
>>32 table1だけではエラーになってしまいました。
select
x
,y
,z
,(select SUM(S) from table2 T2 where T2.k = table1.k) as r ←ここで「table1」と指定することになりますが、エラーになって外テーブルと相関しません。
from
)
select x,y,z,k
from abc
) as table1 ←外側テーブルとなる導出テーブルを名づけます。
かといって、as table1 T1と二重に名前付けできません。
導出テーブルを相関クエリではつかえないってことでしょうか。
>>33 試したけど、SQLは問題なく通る
fromの後のカッコのtypo直してもダメなのか?
エラー出てるならエラー内容書いてみ
oracleとかで、外部参照制約かけるとのとかけないのとでは、selectの実効速度に違いは出ますか?
>>34 レスありがとうございます。
すみません、もう一度試してみたいと思います。
外側導出テーブル(as table1)と、スカラ相関クエリ内テーブルと、
相関させてみます。
できるとお聞きして、一度、簡単な例で試してみようと思います。
またレスします。
ありがとうございます。
>>34 ありがとうございました。
「できた」とお聞きして、自分でも簡単な例を実行してみました。
すると、エラーにならずに実行することできました。
次の相関クエリを組み試しました。
select 敬称CD as CD,(select 敬称 from 敬称表 TB2 where TB2.敬称CD = TB1.敬称CD) as 名称
from
(
select 敬称CD
from 敬称表
) as TB1
敬称表
--------
1 様
2 御中
3 殿
--------
意図した結果を得られました。
TB1は導出テーブルのエイリアスです。
また、これは、相関クエリでつかえる相関させるテーブル名としても使えることがわかりました。
>>33では勘違いしていたようです。
何か、別のエラーを生じさせてしまっていたようです。
原因を究明します。
ありがとうございました。
38 :
NAME IS NULL:2013/06/25(火) 00:23:48.21 ID:zEc4TkxA
SQLserver 2008 R2 です
where句の等号不等号の表記で、
where ・・・
and x <= y だと、okで、
where ・・・
and x =< y だと、エラーになります。
これって、標準なんでしょうか。
どっちでも良いように思うんですが、納得のいく説明があれば教えてください。
>>38 納得のいく説明とは、何が納得いかないの?
SQL Server(Transact-SQL)に =< と言う演算子は有りません
したがってエラーになるのは当たり前
標準SQLにあればサポートされるはずなので、標準SQLにもないでしょう
>>39 すみません、
等号不等号を組み合わせた演算子レベルでみることを忘れていました。
副問い合わせによる導出テーブルの各列のインデックスは、
もともとの実テーブルの列インデックスを継承して、
自動的に有効になっているのでしょうか。
それとも、導出クエリでインデックスを作成するステートメントでも必要になるのでしょうか。
ORDER BY句に列を書けばインデックスが有効化されるなどありますでしょうか。
>>41 自分が使っているデータベースの実行計画を見る方法を調べて、それで表示される
内容の意味を調べて、そしてもう一度自分のレスを読み直せ。
43 :
NAME IS NULL:2013/06/27(木) 02:34:19.56 ID:14GM02fv
>>20です。できました。お礼が遅くなってすみません。
mySQL5系の質問です。
2テーブルからデータを取得したいのですが、効率的なSQL文が組めず困っております。
tableA
id name
1 サザエ
2 カツオ
3 ワカメ
4 タラヲ
というテーブルがあり、tableA.idをデータとしてセットする
tableBがあったとします。
tableB
tableA_id key1 key2 key3
4 1 2 3
key1〜key3にセットされる値は、tableA.idの値になります。tableA_idに関しても同様です。
この2つのテーブルからtableBのkey1〜key3にセットされているidに紐づく
実際のnameを取得したいです。
tableBがちょっと妙な気がするのですが、「tableA.idを構成しているのが、key1〜key3という意味」らしいです
データ取得時にtableA_idにセットする値が渡ってくるものとします
SELECT name FROM tableA
WHERE id IN (SELECT key1, key2, key3 FROM tableB WHERE tableA_id = 4);
最初はこのようなSQL文を組んでみたのですが、サブクエリ的にダメなようなので
SELECT name FROM tableA
WHERE id IN (SELECT key1 FROM tableB WHERE tableA_id = 4);
というようなSQL文をkey1〜key3まで繰り返すことしか思いつきません。。
もう少し効率的なSQL文が組めればと思うのですが、どなたかご指導頂けないでしょうか?
5系で纏めんじゃねえよ
EXPLAINしてみた?
ちなみにそのサブクエリだと5.5未満と5.6以降でだいぶ速度変わると思うけど
>>44 試してないけど
SELECT name FROM tableA
WHERE id IN (
SELECT key1 FROM tableB WHERE tableA_id = 4
UNION
SELECT key2 FROM tableB WHERE tableA_id = 4
UNION
SELECT key3 FROM tableB WHERE tableA_id = 4
)
はできないかな。
tableBの設計が明らかにおかしいけど
設計の話はスレ違いだしな
いや、明らかにおかしいというのは言いすぎだな
key1=保証人1、key2=保証人2とかだったらありえるか
>>44 最終的に欲しいデータが解らん
タラヲ,サザエ,カツオ,ワカメ で良いのか?
普通に考えたらtableAを4回joinするだけだが
select t.name,t1.name,t2.name,t3.name
from tableB
join tableA t on t.id=tableB.tableA_id
join tableA t1 on t1.id=tableB.key1
join tableA t2 on t2.id=tableB.key2
join tableA t3 on t3.id=tableB.key3
こんな感じ。mySQLで動くかどうかは知らん
>>44です。
返信遅れて申し訳ないです
>>46さん方式と
>>49さん方式を試してみようと思います。
>>48-49 サザエさんの例がよくなかったのと、自分の説明が雑でした
テーブルAを食べ物、テーブルBを献立とさせてください
テーブルAには食べ物も献立もどちらも入っているのです(ここがよく意味わからないのですが。。。)
例えばサーモン握りであれば、サーモン握りもごはんもサーモンもタマネギも
テーブルAに登録されていて、テーブルBの方には
tableA.id key1 key2 key3
サーモン握りのid ごはんのid サーモンのid タマネギのid
このような形でデータが入っています。
それで、テーブルBの方からidを使ってテーブルAの食べ物名を取得。。らしいです。
ソシャゲ業界に転職したばかりで、ソシャゲはこういうものなのかと思っていたのですが
やっぱり変ですよね。。
お答え頂いた方、ありがとうございました
単に親子関係を持っていて、親は高々3つの個しか持たないっていう要件があるだけでしょう。
何を難しく考えてるのやら
まあ作りが悪いことはたしかw
正規化しろよ
ソシャゲだし、正規化しないほうが速度要件を満たしやすいんじゃない?
あと多分データのメンテがやりやすい(というかツールを作るのが楽)など。
普段SQLには全くご縁が無いのですが、急遽下記の作業をしなけらばならず困っています。
DBMS名とバージョン:SQLServer 2008 R2
説明
データベースAに格納されていたテーブルを新しいwinサーバBにコピーするように言われています。
そのため、外付けのHDDで、圧縮されたMDFファイルを渡されました。
外付けHDDから、サーバのデスクトップ上にデータをコピーし、そこで作業が止まっています。
(圧縮されたまま)
新しいサーバBにはSQL Server 2008R2がインストール済みですが、全く使っていません。
データは外付けのストレージに入れる予定です。
(つまり、サーバBのSQL Serverのmdfの置き場はストレージ上にする)
csvファイルの場合、テーブルを作ってデータを流し込むという作業はしたことがあるのですが、
mdfファイルで渡されたことが無かったので、作業が中断しております。
変な質問だったらごめんなさい。
ご教示頂けますと幸いです。
>>55 MDFファイルならアタッチでいける。
その外付けストレージにファイルを置いてからな。
どう考えてもスレ違い。専用スレにどうぞ。
追加しようとしているレコードを主キーから追加・修正を自動判別して実行させたいんですけど良い方法は無いでしょうか?
今はselect count (*) from tableName where primarykey=fookeyで
1ならupdate、0ならinsertってしているんですがこの方法しか無いのでしょうか?
python2.6.6からsqlite3を使用しています。
SQLiteならinsert or replaceの構文があるだろう
61 :
59:2013/07/06(土) NY:AN:NY.AN ID:???
>>60 ありがとうございます!
こんな便利な構文があったんですね、まさに求めていた理想的な方法でした。
MYSQL5.5
key a b
--------------------
1 3 2
2 1 1
3 5 2
4 2 3
こんな感じでkeyが1〜500万くらいまでの500万行のテーブルなんですが
UPDATE テーブル SET a = a + 1 WHERE key = 5749
UPDATE テーブル SET b = b + 1 WHERE key = 18312
UPDATE テーブル SET a = a + 1 WHERE key = 991127
〜
みたいなUPDATE文を300回くらい同時に実行すると10秒程度掛かってしまい
遅すぎて死にそうです
なにか早くする方法ないでしょうか
>>62 「同時」というのが、厳密にどういうことなのかわからないけど、keyにインデックスが無いなら
インデックスを張れば速くなるよ。
sqlite 3.7.17
* table club_master
club name
--------------
0 名古屋
1 東京
2 横浜
3 大阪
* table match_data
match club
--------------
1 2
2 3
3 1
* table scores
match club scorer
---------------------------------
1 2 山田
1 2 鈴木
1 0 田中
3 0 田中
と3個のテーブルがあって、match_data と scores を結合してそれぞれのテーブルのカラム club から
club_master を参照したいのですがどうしたらいいでしょうか?
select match,
match_data.club as opponent,
scores.club as scorer_club,
scorer
from scores join match_data using(match)
とした場合で、これに加えて club_master を join して、カラム opponent と scorer_club の値でそれぞれ
club_master を参照して以下のようにしたいのです。
match opponent scorer_club scorer
---------------------------------
1 横浜 横浜 山田
1 横浜 横浜 鈴木
1 横浜 名古屋 田中
3 東京 名古屋 田中
サブクエリ使えよって話でしょうか?
65 :
64:2013/07/08(月) NY:AN:NY.AN ID:???
うぎゃー、文字参照使えないのか(´・ω・`)
改めて書き込み直します。
もうだいぶ前に2ちゃん全体で仕様変更になったはずだがw
67 :
64:2013/07/08(月) NY:AN:NY.AN ID:???
改めてお聞きします。
sqlite 3.7.17
* table club_master
club name
--------------
0 名古屋
1 東京
2 横浜
3 大阪
* table match_data
match club
--------------
1 2
2 3
3 1
* table scores
match club scorer
-------------------------
1 2 山田
1 2 鈴木
1 0 田中
3 0 田中
と3個のテーブルがあって、match_data と scores を結合してそれぞれのテーブルのカラム club から
club_master を参照したいのですがどうしたらいいでしょうか?
select match,
match_data.club as opponent,
scores.club as scorer_club,
scorer
from scores join match_data using(match)
とした場合で、これに加えて club_master を join して、カラム opponent と scorer_club の値でそれぞれ
club_master を参照して以下のようにしたいのです。
match opponent scorer_club scorer
------------------------------------
1 横浜 横浜 山田
1 横浜 横浜 鈴木
1 横浜 名古屋 田中
3 東京 名古屋 田中
サブクエリ使えよって話でしょうか?
>>63 単純に
>>62のような文を300回実行するという意味です
INDEXはkeyにのみ張ってます
他には張ってません
>>63 こいつ馬鹿500万行って書いてあるのが読めないのか
>>67 select match,
a.name,
b.name,
scorer
from scores join match_data using(match)
join club_master a on match_data.club = a.club
join club_master b on scores.club = b.club
適当だけど、こんなんでいいんじゃない?
>>68 その300回ってのは、同一のコネクションから順次実行するのか?
(最大300の)複数のコネクションが接続して更新するのか?
環境やスペック書いてないから何とも言えんが、更新そのものが遅いのか
それ以外が遅いのか切り分けろ
>>69 >>63の何がどう馬鹿なのか解説してくれ
俺には言ってる事に間違いがあるとは思えん、
>>72 インデックスがついてなければ10秒で済むはずがないってことじゃない?
>>71 おーおー、できましたできました!
どうもありがとうございました!!
75 :
63:2013/07/08(月) NY:AN:NY.AN ID:???
>>69 1万行だろうと500万行だろうと、インデックスアクセスでは大差ないよ。
ちなみに、手元でPostgreSQLなんだけど、pgbenchで1000万行のテーブルを作って
300回更新する時間を計ったら、大体300ms位だったよ。
つまり、1000万行程度なら、ローカルでレコードを更新するのに1ms/rec程度なんだよ。
300回の更新で10秒かかるということは、33ms/recくらいかかってるということで、
更新対象のレコードを見つけるのにインデックスが使われているのなら、
・レコードがとても長い
・ネットワーク経由でDBアクセスをしていて、ネットワークが遅い
とかなのかな。
あるいは、実行しているPCのメモリがとても少ないとか、CPUがとても貧弱とか、ディスクがとても遅いとか?
>>75 ついでにインデックスつけないで計測してくれ
>>68 MySQLスレに行った方がいいんじゃない?
つかってるDBMSとかわからんけど
毎回テーブルロックー開放してるとか?それでも遅い気はするが
データサイズにも寄るけど、インデックスなかったら10秒程度で終わるわけない。
1回の更新で数百ms位かかると思う。500msだとして、*300で150秒。
なので、インデックスは使われていて、10秒というのが「最も高速に処理が終わる時間」に
比べて遅いのなら、何か別の理由だな。
ただし、「最も高速に処理が終わる時間」というのが10秒であるという可能性も捨てきれない。
>>78 あ−、(connect→begintran->update->commit->close)*300ってやってて遅いのかも。
テーブルサイズにもよるが
たとえば数字3項目で6バイトとして、500万件で30Mバイト
今時のサーバスペックならオンメモリで処理できる
インデックスなしでも数百msもかかるか?
HDDからメモリ移すだけで1秒は掛かりそうだけど
>>82 それははじめの1回だけで済む。あとの299回はオンメモリでいけるだろ
まあDBのバッファに入るか単にファイルキャッシュなのかとかによっても変わるが
84 :
62:2013/07/08(月) NY:AN:NY.AN ID:???
エンジンはInnoDBです
>>62の10秒超というのは
↓のようなストアドプロシージャを実行した時に掛かった時間です
CREATE PROCEDURE test( IN x1 INT, IN x2 INT, IN x3 INT 〜〜 )
BEGIN
UPDATE テーブル SET a = a + 1 WHERE key = x1
UPDATE テーブル SET b = b + 1 WHERE key = x2
UPDATE テーブル SET a = a + 1 WHERE key = x3
〜〜
×300行
今自宅でローカルに同様の構成で10万行のテーブルを作って
100行でプロシージャを実行してみたらやはり3〜3.5秒程掛かります
試しに
UPDATE テーブル SET a = a + 1 WHERE key = 1
を1行だけ実行じてみたら
(クエリの実行時間 0.0474 秒)と出ました
phpmyadminから実行してるのですがこの表示が間違っているでしょうか
MYSQLのUPDATEが遅いというのは色々読んでわかったのですが
1行だけで50msというのは何か問題があると考えた方がいいのでしょうか
やっぱmysqlスレ行け
引数300個のプロシジャか
すげえとしか言いようがないな
以下のようなテーブルがあります。
val priority
---------------
123 2
456 1
456 2
789 1
ここで、val が重複した場合は priority の大きいほうを選ぶにはどうしたらいいでしょうか。
この場合なら
123 2
456 2
789 1
という結果がほしいです。
環境:postgresql 9.1
select val, max(priority) from テーブル group by val
>>88 select val, max(priority)
from table1
group by val
でいけました。ですよねー。
ほんとうは他にもカラムがあるから、こんな簡単じゃないけど。
92 :
NAME IS NULL:2013/07/10(水) NY:AN:NY.AN ID:v+VyPD99
質問をさせて頂きます。
よろしくお願いします。
・DBMS名とバージョン
Oracle 8.05
・テーブルデータ
No ,CTG,TIME
1 , A, 1h
2 , B, 2h
3 , C, 3h
4 , A, 1h
1 , C, 2h
1 , B, 3h
※CTGはC以降もあるが、全10個程度
レコード数は100程度
・欲しい結果
NoごとにCTG_A,B,CのTimeを集計(sum)した結果を
取得したいです
出力結果OKイメージ:
No,CTG_A,CTG_B,CTG_C
1 2, 3, 2
2 , 2,
3 , , 3
下記のような出力はNGです
NO CTG Time
1 , A, 2
1 , B, 3
1 , C, 2
2 , B, 2
3 , C, 3
前任者がなんの引き継ぎもないまま
いなくなってしまい前知識なしにSQLを
使用する立場となってしまいました
どうかご助力ください
情報が不足していれば追記します
>>92 > 下記のような出力はNGです
の結果を出すクエリがかけるなら後は
>>5
94 :
NAME IS NULL:2013/07/10(水) NY:AN:NY.AN ID:v+VyPD99
>>93 素早い返答有難う御座います
Oracle 8ではcaseは全て使えないと
誤って覚えておりました
単純CaseはOracle8でも使えるのですね
本当に助かりました
ありがとうございます
96 :
NAME IS NULL:2013/07/10(水) NY:AN:NY.AN ID:v+VyPD99
>>95 情報提供有難う御座います
DBはOracle 8.0で間違いないです
前任者の方が10年以上一人で
保守・開発をされていたとのことで
更新などは全くされていないようです
select id from ( (select id from table1) except (select id from table2) ) as t
というSQLがあります。このとき、「select id from table1」の部分を、リテラル値を埋め込んだ形にする方法があれば教えてください。
イメージとしては
select id from ( (81, 72, 47, 99) except (select id from table2) ) as t;
とか
select id from ( (select id from (81, 72, 47, 99)) except (select id from table2) ) as t;
みたいな感じです。
(PostgreSQL 9.x)
よろしくお願いします。
リテラルをselectするのをunionでつなげれば出来るだろうけど
そのリテラルはどっからもってきたんだ?何がしたいのかまったくわからんな
VALUESってINSERTでよく使うけどSELECTでも使えたのかw
というかSELECTと同等、か。
そういやINSERTでVALUESのとこにSELECT置くもんなあ
VALUESで複数列書けるのは標準的なSQLなのか?
複数列も複数行も少なくともSQL92ではすでに標準としてある
どのDBMSにいつ実装されたかまでは知らない
insertで書くときは何も思わずに複数行、複数列指定に使われていたりする、そんなvaluesさん。
便利だよね。
それでもOracleくんには頑なに受け入れてもらえない、それがvaluesちゃん
valuesで複数行書けるの標準SQLだとは思ってなかった
SQLServerは2008から出来るっぽい
>>99 まさにこれです!すてきすぎ!
99とPostgresqlにいいことがありますように。
>>101 その考え方いいですね。
>>107 その考え方いいですねって、素敵過ぎると思ったマニュアルを読まなかったのか?
そのマニュアル、翻訳間違ってるな。
> ORDER BY、LIMIT(、これと等価なFETCH FIRST)そしてOFFSET句でVALUESコマンドを使用することができます。
〜OFFSET句「を」VALUESコマンド「で」使用することができます。
だろう。
いや、あってるだろ
そのマニュアルとやらがどれか知らんが、ここで言ってもしょうがないだろうに
【質問テンプレ】
MySQL5.5
key a b c
--------------------
1 3 3 2
1 4 1 1
1 5 2 2
1 2 3 2
2 1 0 5
2 5 0 2
2 2 3 2
2 1 0 0
3 1 2 2
3 2 3 0
上記のような2000万行程度のテーブルに↓のようなSELECT文を投げたいのですが
SELECT abs(a + b - c) AS abs_hoge, key FROM table WHERE key = 2 ORDER BY abs_hoge ASC LIMIT 1;
大体20〜40秒程度の時間が掛かります
インデックスはkeyにのみ張ってます
一つのkeyの値につき2000レコード程あるので
まず2000行フェッチされた後、a+b-cの絶対値でfile_sortされてるみたいなのですが
どうにかして処理を速くできないでしょうか
実際はa,b,cだけでなくd,f 〜 y,zくらいまでカラムがあり
場合によって abs(a - f - k)のように文を変えるので複合インデックスも試そうとしましたが難しいです
よろしくお願いします
order by で limit 1ってmin とか使えないの?
は?
>>112 2000行フェッチするまでが遅いの?それともその後?
感覚的には後者ってことはなさそうな気がするんだけど
>>112 パフォーマンスはまず実行計画見てみないと話にならん
レコードサイズとかにもよるけど、2000行の演算とソートが20秒もかかるとは思えん
となると遅いのはSELECTそのものの可能性が高い
keyにインデックスあるなら、これ以上は一般論では無理
MySQLのスレいって聞け
117 :
NAME IS NULL:2013/07/21(日) NY:AN:NY.AN ID:vvTOE8eP
その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。
その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。
その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。
その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。その目気色悪すぎこっち見んな死ね。
118 :
112:2013/07/21(日) NY:AN:NY.AN ID:???
フェッチ後が遅いようです
100万行程度テーブルなら2000行程度のfilesortも一瞬なのですが
2000万行でやるとなぜか一気に時間が増えてしまいます
mysqlスレで聞いてみます
ありがとうございました
119 :
NAME IS NULL:2013/07/21(日) NY:AN:NY.AN ID:+gxDS+8E
【質問テンプレ】
・DBMS名とバージョン: MySQL ver5.0.95
PHPと組み合わせて使っているのですが、PDOステートメントを使って
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$rows[$row['data1'] = array($row['data2']);
}
という感じに値を$rowsという配列に入れていってます。
このdata1はカラム名です。data2がNULLになってしまってるのですが
data2というのはサブクエリでとってきた値なのです。
このサブクエリにキー名のようなものをつけることは出来ないのですか?
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
echo var_dump($row);
}
で中身を見ると、
array(3) {
["data1"]=>
string(5) "wtb_3"
["(select data2 from 〜〜〜〜)"]=>
NULL
}
こんな感じで入ってます。
サブクエリの結果を表示するには$row['(select data2 from 〜〜〜〜)']とする以外方法はないのでしょうか。
サブクエリ文自体を変数に入れればスッキリはしますが、他に方法があれば知りたいです。
宜しく御願いします。
120 :
119:2013/07/21(日) NY:AN:NY.AN ID:+gxDS+8E
あ、ごめんなさい
["(select data2 from 〜〜〜〜)"]=>
NULL
ではなく、この場合はちゃんと欲しいデータが入ってます。
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$rows[$row['data1'] = array($row['data2']);
}
echo var_dump($rows);
としたときに
["data2"]=>NULLとなるのでした。
スレ違い。
・DBMS名とバージョン:MySQL5.5
SELECT IF(DATEDIFF(NOW(), created)=0, value, 0) FROM TBL1;
このIF文でcreatedという時間データと現在時刻を比較し、1日以上経っているか、それともcreatedと同じ日かという判別をしているのですが
もし1日以上経っていたら、同じ命令文の中でvalueを0にアップデートする方法が知りたいです。可能なら方法をご教授下さい。
何だよ命令文って。更新したいならUpdateしろよ。
>>120 よくわからんけど構文エラーがあるように見える。
それで動くのかな。
>>122 update TBL1 set value = 0 where datediff(now(), created) = 0;
とか?
sql server 2008とADO.NETを使っています
クライアントのアプリからストアドプロシージャに配列を渡すにはどうすれば良いのでしょうか?
スレ違いです。
お世話になります。
複合インデックスの項目を歯抜けにしても効果的にインデックスを効かせるSQLの書き方教えていただけませんでしょうか。
1テーブルのWhere句に入る項目数は最大30位あるんですけど、全部検索条件に指定してもらえるわけもなく困ってます。
『数値型検索列>=0』のようなもので埋めればいいのですか?
DBはSymfowareV10です。
ご教授の程、よろしくお願いします。
>>128 特定のDBMSのオプティマイザ動作をここで聞かれてもなぁ
専用スレ行け。あるのかないのかしらんが
感じわる
みりゃわかるがまともな回答はついてない。
マルチポストを非難する煽りレスかと。
SQL server2012 expressですが
指定したテーブル内の項目名を全て取得するにはどうすれば良いでしょうか?
Googleで検索すると'syscolumns'を検索するば良いみたいですが
それっぽい文字列が見つかりません。
このスレ的には、INFORMATION_SCHEMA.COLUMNS かな。
sqlsrver2008R2なんだが、updateクエリを使って列のデータ型を変更する方法を教えて欲しい。
先輩が言うにはやれるらしいが、調べてもalter tableを使う方法しか出てこない。
無理。
その先輩をゴーモンして口を割らせろ
システムテーブル書き換えるんじゃね
それならできそうw
凌遅刑
update table1 set col1 = 'value1' where id = 111;
update table1 set col1 = 'value2' where id = 222;
update table1 set col1 = 'value3' where id = 333;
これを1文でスマートに実行するにはどうしたらいいですか。
以下のようなのを考えたけど、どう考えてもスマートではありません。
update table1
set col1 = case
when id = 111 then 'value1'
when id = 222 then 'value2'
when id = 333 then 'value3'
end
where id in (111, 222, 333);
update fromを使ったところでスマートかというとな。
求めてるのって、1文かどうかが重要なんじゃないの。
update table1 set col1='value'||substr(to_char(id),1,1);
全件ヒットしちゃうじゃん
問題はそこじゃないだろ
自分でいうのもなんだけど。
1文かどうかなんて重要じゃないと思うが
そもそも1文で処理する必要性がわからん
排他制御がしやすい
複文だとしにくいって言ってる?
うん。
ちょっとだけだけど。
今回は違うけど、id を書き換えるような場合は1行でやらないと
結果が変わってくる
複数行ならtransaction使うだろ。
結果が変わって困るというなら設計がおかしい。
transactionフリーにすると後々様々なメリットを享受できる
トランザクションを理解できなかった奴がよくこういうことを言ったりする
トランザクションを理解出来ないやつほど無駄にトランザクションを使う
一文のSQLはトランザクションじゃないと誤解するのも初心者にはありがち
俺も昔はそうだった
SQL Server 2008
日付と時刻とを date型とtime型と、別々に分離されているものを
datetime型に変換するにはどうしたらいいのでしょうか。
declare @date as date;
declare @time as time;
declare @datetime as datetime;
set @datetime = @date + @time; ← かなぁと思ったら、NGでした
文字列として組み立てて変換すればいいんじゃね?
>>159 型が違うんだからまずdatetimeにしてから足せよ
set @datetime = cast(@date as datetime) + cast(@time as datetime);
型が違うものの演算とか代入とか、型の優先順位や暗黙の変換によって結果が決まる奴は
よっぼど自信があっても使わん方が良いぞ
162 :
159:2013/08/18(日) NY:AN:NY.AN ID:???
cast する方法でバッチリ出来ました
どうもありがとうございました
ポケモンマスターとはポケットモンスターのマスタテーブルであると仮定して
サトシはどのようなクエリ言語でこれを参照しているのでしょうか
構文は○○ゲットだぜだけで大丈夫よ。初心者にもオススメ。
ピカ厨
166 :
NAME IS NULL:2013/08/26(月) NY:AN:NY.AN ID:ar04zqCb
・DBMS名とバージョン: MySQL 5.0.92
・テーブルデータ ・欲しい結果
ID |DOMAIN DOMAIN
- | ----------- -----------
1 |foo.hoge.ne.jp hoge.ne.jp
2 |bar.fuga.ne.jp → fuga.ne.jp
3 |qux.piyo.co.jp piyo.co.jp
テーブル構造
ID integer primary key auto_increment
DOMAIN varchar(255) not null
・説明
DOMAINを like '%.__,jp'で抽出し、
DOMAINのうち右から3番目の「.」以降の文字を、「.」が2個以下の場合全文を列挙したい
よろしくお願いします!
ドメイン名の取り扱いは悩ましいなぁ
FQDNじゃなくてサブドメイン単位のデータを格納するべきなんじゃないかと思ってみたり
しかし取り扱いを考えるとFQDNの文字列で持ちたい
ビューでなんとかすべきか、正規化くずすべきか
ドメイン名自体を管理するならともかく、単に覚えておくだけなら、全部だな。
FQDNとドメインを両方持ったところで、FQDN→ドメインという関係が存在するだけで
正規化どうこうの問題にはならんだろう。
というか逆に、部分文字列の抽出とか文字列の構造に依存した処理を前提とした
DB設計ってのは避けるべきだな。
PHP5+MySQL 5.1.69を使っているんだけど…
id user tag
1 56 hoge
2 24 piyo
3 56 foo
4 12 bar
5 1 hoge
6 2 foo
...続く
って感じのテーブル…要するにuserひとつにタグが最大で8個ぐらい付いているっていうのがある
userとtagの組み合わせはユニークになってる(ひとつのuserが同じtagはつけられない)
これで例えばhogeのtagがついているuserは他にどんなtagがついているか知りたい
それがグループ、オーダーで登録数順になった形式が欲しいんだけど
こんなん
tag sum
foo 26
bar 12
pyo 5
...
簡単かなって思ったけど全然思いつかない
誰かご教授いただけると有難い
tag 毎の登録数が知りたいの?
であれば、select tag, count(*) from table group by tag order by count(*) desc; でいいと思う。
> これで例えばhogeのtagがついているuserは他にどんなtagがついているか知りたい
にどう繋がるかはよくわからんけど。
いやごめんちょっと違う
id user tag
1 56 hoge
2 24 piyo
3 56 foo
4 12 bar
5 1 hoge
6 2 foo
...
って状態で格納されてるけど
要するに
user tag
56 hoge, piyo, foo
1 piyo, bar, hage
23 bar, foo, piyo
4 hage, bar
...
ってphpで出力して使ってる
これで
「hogeを登録している人は○○も登録していますよ」って感じにしたいから
hogeを登録している人が他に登録しているtagを多い順に集計したい
上の4つだと例えばfooを登録している人は…ってなると
tag sum
piyo 2
bar 1
hoge 1
ってなるようにしたいんだ
ああそういうことか、ではこうかな?
※ 手元に環境ないので未検証
select t2.tag as tag, count(*) as sum from table t1 inner join table t2 on t1.id = t2.id where t1.tag = 'foo' and t2.tag <> 'foo' group by t2.tag order by count(*) desc;
それじゃ無理な気がする。
1. fooを登録してるユーザー一覧
2. 1. のユーザー達が登録してるtag一覧
3. 2. のtag一覧からfooを除いたものをGroup By、でいいのかな。
>>171 仕事?
趣味?
まさか仕事じゃないよね?
この程度が解決できないレベルでお金もらえるはずがないよね?
select tag, count(tag) as sum
from table
where
tag <> 'hoge' and
user in (select user from table where tag = 'hoge')
group by tag
order by count(tag) desc;
こんなか?
>>173 そこに書いてあるやつ、上と下でデータ違うじゃねえか
ちゃんと合わせとけよ
select tag,count(*) from テーブル
where user in (select user from テーブル where tag='foo') and tag<>'foo'
group by tag order by count(*) desc
たぶんこんな感じ
>>173 SELECT t2.tag,COUNT(1) FROM tables AS t1 INNER JOIN tables AS t2 USING(user)
WHERE t1.tag != t2.tag AND t1.tag='foo' GROUP BY t2.tag ORDER BY t2.tag DESC;
こんな感じ?
181 :
180:2013/09/01(日) 13:57:25.96 ID:???
182 :
171:2013/09/01(日) 20:58:36.70 ID:M1fx7C6f
うおーありがたい!
どれも上手くいったよ。
どれ使えばいいか迷うなw
>177
もちろん趣味
質問なのですが、レコードが最後に読み出された時間は自分でフィルード作って記録する必要がありますか?
一般的には自分で管理しないと無理
selectにトリガ張れるDBMSは聞いたことないけど、監査機能で実現できるかもしれん
mysqlでのソートについてですが
ソート対象のカラム内にa,b,c,dとはじまる文字列あった場合に
最初をbとしてその後にa,c,dなどのようにすることはできるのでしょうか
>>186 case文でソート用の列をつくればいいんじゃない?
select * from table order by field(left(col,1),'b','a','c','d');
order by には複数条件書けるから
col = b desc, col
ってやればbのときTRUEで最優先、残りはcol順になる
おっと、bで始まる、か
まあ
>>188の例も見ればわかるよね
mysqlでの質問になります
あるカラムの同一データごとからランダムに一つずつデータを抽出することは可能でしょうか。
193 :
NAME IS NULL:2013/09/10(火) 15:31:34.22 ID:u4dYxzY0
ランダムにってどういうこと?
194 :
NAME IS NULL:2013/09/10(火) 15:38:21.21 ID:y1marFjb
>>193 説明不足ですいません。
以下のようなカラムからカラムAの1から一つ、カラムAの2から一つというように取得したいんです・・・
カラムA カラムB
1 a
1 b
1 c
2 a
2 b
2 c
3 a
3 b
3 c
適当
select * from table group by カラムA;
>>195 いくらなんでもそれは適当すぎる
>>194 select
カラムA,
(select カラムB from テーブル where カラムA=t1.カラムA order by rand() limit 1);
from
(select カラムA from テーブル group by カラムA) t1
とかじゃね、mysql手元にないから知らんけど
あ、いらんとこにセミコロン入ってる
m(._.)mド初心者です。 MySQL5.5
テーブル名:売上計
魚 数
はまち 10
かつお 10
いわし 20
テーブル名:売上月次テーブル
魚 数
はまち 1
かつお 0
いわし 5
の2つのテーブルがあるときに、
売上計 に月次のレコードの数をすべて足して、
テーブル名:売上計
魚 数
はまち 11
かつお 10
いわし 25
としたいです。
どうすればよいでしょうか。
UPDATE 売上計 SET 売上計.数 = 売上計.数 + 売上月次.数 WHERE 売上計.魚 = 売上月次.魚 ;
としましたが#1054 エラー UNKNOWN COLUMN 売上計.魚 と出ます。
UPDATE 売上計,売上月次テーブル SET 売上計.数 = 売上計.数 + 売上月次テーブル.数 WHERE 売上計.魚 = 売上月次テーブル.魚 ;
ありがとうございます。
UPDATEで 売上計 , 売上月次
とするんですね。できました。
レコードの値を参照するだけで更新しないテーブルでも、
クエリで触れるテーブルについては、UPDATEで書くんですか。
SELECTで足せばいいだろう、常に使うならVIEW作ればいい
union all してsumればいいんじゃない?
SQL SERVER 2008 R2 - Microsoft SQL Server Management Studio 10.50.2550.0
の質問なのですが、SQL文発行時等のエラーメッセージが日本語にならないのですがどこに設定があるのでしょう
メニューバーその他設定などは全て日本語で、DBの照合順序などもJapanese_CI_ASになっているのですが・・・
別環境では問題なく全て日本語で出るのですが、新しく作った環境では上記のような状態になってしまいます
とても初歩的で申し訳ありませんがご教授お願い致します
205 :
NAME IS NULL:2013/09/19(木) 21:48:14.24 ID:bkFzQmtP
各キーのトップ5を抽出するSQLを教えてください。
206 :
NAME IS NULL:2013/09/20(金) 10:06:54.20 ID:cIRAGCg1
SELECT TOP 5
207 :
NAME IS NULL:2013/09/23(月) 15:28:21.90 ID:Fbkd2zVx
id name num とあって
id: 1 2 3 4 5 6 7 ...
name: tarou hanako tarou tarou tarou hanako tarou
num
となっています。
update table set num = 1 where name = tarou
とすると、tarou全てが1になります。
ですが、idが最大のtarouだけを1にしたいんです。
update table set num = 1 where name = tarou and id = 7
とやれば7のtarouだけを更新することができますが、常に最大のものだけを更新したいので
これではできません。
簡単にできそうに見えるんですがやり方が分かりません。
やり方教えてください!ちなみにsqliteを使ってます。
update table set num = 1 where id = (select max(id) from table where name = 'tarou')
とか?
209 :
NAME IS NULL:2013/09/23(月) 15:41:22.04 ID:Fbkd2zVx
ありがとーーーーーー
できました。
MySQL5.5です。
テーブル構成等
CREATE TABLE `tab` (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
status VARCHAR(12),
created DATE
);
INSERT INTO tab (id, status, created) VALUES
(0,'ENABLE','2013-01-01'),
(0,'DISABLE','2013-01-02'),
(0,'ENABLE','2013-01-03'),
(0,'DISABLE','2013-01-03');
欲しい結果
CREATED ENABLED DISABLED
2013-01-01 1 0
2013-01-02 0 1
2013-01-03 1 1
よろしくお願いいたします。
created毎にGROUP BYしてENABLEDとDISABLEDがそれぞれ何件ずつ登録があったかを
SELECT一発で調べたいのですが、どうもうまくSQL文をイメージすることができません。
お手数ですがお願いできませんでしょうか。
よろしくお願いいたします。
212 :
210:2013/09/30(月) 19:34:12.24 ID:???
Nooo
すみません。
ありがとうございます。
SQLiteを使っています。
同時に更新する可能性のあるデータベースで、
update文を実行したとき、すでに削除されているケースもあり、
その場合エラーをキャッチしプログラム側で例外処理するようにできています。
update文は複数に対して行うことがあります。
そのため1つずつupdate文を実行するのですが、例外処理に移行した場合、
無視して継続というようなことが出来ないため、
トランザクション処理の中で行い、正常に終わってる分も含めてロールバックすることになります。
そこでまず最初にselectして、update対象があるかを確認する方法が考えられますが、
selectしたカラムが存在していたら、update文を実行するみたいな処理はどのように書けばいいでしょうか?
1回のSQLでは無理でしょうか?
update hoge set a='なんたら' where exists (select 1 from hoge h1 where h1.b = 'キー')
SQLiteはupdate側に別名使えないらしいが今環境ないから不明
215 :
213:2013/10/01(火) 21:19:17.09 ID:???
>>214 どうもありがとうございます。
id name emailというuserテーブルとして、
update user set email='
[email protected]' where exists (select 1 from user h1 where h1.id = 3)
という感じでやってみたところ、正常に実行はできたのですが、
全てのカラムのemailが
[email protected]になりました。
もう少しいじればできそうな気がするので、頑張ってみます。
216 :
213:2013/10/01(火) 21:26:48.58 ID:???
update user set email='a@examplecom' where id = (select id from user where id = 3)
正しい文なのかどうかはわかりませんが、こんな感じで行けました。
どうもありがとうございました。
update user set email='a@examplecom' where id = 3;
これじゃだめなのか?
id = 3が複数あれば、それ全部更新する。
無ければ、何もしないはず。
218 :
213:2013/10/01(火) 22:02:06.34 ID:???
>>217 すみませんおっしゃるとおりでした。
firefoxアドオンのSQLite Managerを使っていますが、
update文もdelete文も、存在しないidに対してやっても問題ありませんでした。
エラーが出るものとばかり思い込んでいました。
219 :
NAME IS NULL:2013/10/02(水) 14:50:47.01 ID:eTCIsFeO
初歩的な質問ですみません。UPDATEでINは通常使えるのでしょうか?
IDが5,6,7の人のAGEを20にする
UPDATE MAN SET AGE = 20 WHERE ID IN (5,6,7);
日頃使っているDBでは通るのですが、一般的に使えるものがどうか知りたいです。
INの説明文・例文が、SELECTばかりなものですから・・・。
>>219 通常ってのがどんなものを想定してるのか分からんが
WHEREにIN使えないDBMSの方が少ないんじゃないかね
222 :
219:2013/10/03(木) 09:00:41.99 ID:???
>>220 その構文説明はちょっと違うと思うのですが、リンク先でpostgreSQLは
使えることがわかりました。
>>221 なんていいましたっけDDTとDDA?参照と更新にかかわらず、WHEREは
WHEREちゅうことですね。
使えると思ってよさげですね。更新とか削除とか、いいのかなーとか
思いながら使ってたんで、安心しました。ありがとうございました。
MYSQL5.5です。教えていただけると助かります。
テーブル名:子供
子供番号、名前
1,たろう
2,はなこ
3,じろう
テーブル名:きらい
子供番号,食べ物
1,にんじん
1,ピーマン
2,にんじん
2,トマト
3,ピーマン
この二つを結合して、にんじんトマトどちらも嫌いな子供を出すことはできるのでしょうか。
select * from 子供 left join きらいなもの on 子供.子供番号 where きらい.食べ物 = にんじん and きらい.食べ物 = トマト
これだとだめですよね。
224 :
223:2013/10/03(木) 18:08:33.54 ID:???
すみません。
>>6 でできました。
重ねてで申し訳ないのですが、
たとえば、食べ物カラムに入る値をスペース区切りにして、
テーブル名:きらい
子供番号,食べ物
1,にんじん ピーマン
2,にんじん トマト
3,ピーマン
select * from 子供 left join きらいなもの on 子供.子供番号 where きらい.食べ物 like %にんじん% and きらい.食べ物 like %トマト%
ってやるとトマトもピーマンもきらいな子供を出せると思うのですが、これはダメなんですよね。
第一正規形じゃないのはわかるのですが、なぜだめなんでしょう。
>>223 にんじんが嫌い、かつ、トマトが嫌い って条件なんだから、きらいテーブルににんじんが存在する、かつ、きらいテーブルにトマトが存在する
素直にSQL書けば
select * from 子供 t
where exists (select * from きらい where きらい.子供番号=t.子供番号 and きらい.食べ物='にんじん')
and exists (select * from きらい where きらい.子供番号=t.子供番号 and きらい.食べ物='トマト')
とか
select * from 子供
where 子供番号 in (select 子供番号 from きらい where 食べ物='にんじん')
and 子供番号 in (select 子供番号 from きらい where 食べ物='トマト')
とか
結合でやりたいなら
select 子供.* from 子供
join きらい t1 on t1.子供番号=子供.子供番号 and t1.食べ物='にんじん'
join きらい t2 on t2.子供番号=子供.子供番号 and t2.食べ物='トマト'
とか
MySQLで動くかどうかはしらんが
>>224 それ赤ピーマンあったらどうなるの?
とまとがひらがなだったらどうなるの?
227 :
223:2013/10/03(木) 18:48:21.43 ID:???
>>225 なるほど!そういう書き方もあるんですね。
>>226 確かにlikeだと別のものも出てしまいます!
すごい目から鱗です。ありがとうございます。
さらに質問させてください。
嫌いテーブルと同じ構造で、好きテーブルがあったとして、
--------
名前:はなこ 嫌いなもの:にんじん,トマト 好きなもの:オムライス,肉まん,焼き鳥
-------
のように子供の情報をずらっと表示するときは、1度のSQL文で抽出できるのでしょうか。
3つのテーブルを外部結合するのかなと思ったのですが、
はなこ,にんじん,オムライス
はなこ,にんじん,肉まん
はなこ,にんじん,焼き鳥
・・・
のようになってしまいます。
それとも該当する子供だけ先に抽出して、嫌いなもの、好きなものを子供ごとに抽出するのでしょうか。
>>227 まず良くある質問を見ろ
まあ、その手はホストアプリでやるのが無難
230 :
223:2013/10/03(木) 22:54:49.24 ID:???
>>228 group_concat すごい便利ですね。ありがとうございます。
>>229 PHPで取得したデータを展開するつもりです。
複数のテーブルからデータをひっぱってきて、前述の
名前:はなこ ・・・ 焼き鳥 のようにクライアント側で表示しようとする場合の
一般なやり方というか、どこまでをSQLで担当するのかがわからないのです。
一度で全部のデータをSQLで取得してPHPで表示するのか、
それとも、子供、好き、嫌いそれぞれを別個に取得してPHP側でうまいこと表示するのか。
例に挙げたものよりも列もテーブル数もすごく多くなった場合、どうしたらよいのか
わからないのです。
232 :
223:2013/10/04(金) 20:21:36.78 ID:???
>>231 誘導までしていただいてすみません。
そちらのスレも読んでみましたが、いろいろと奥深い世界ですね!
もう少し自分で調べてみてから設計スレで質問してみます。
レスくれた方々、ありがとうございました!
233 :
NAME IS NULL:2013/10/08(火) 19:31:07.14 ID:q6jVV2Df
ショッピングカートに商品を追加するとき
カートのテーブルが itemID, userID, item_num って構成だったとして
同一商品を時間を置いて2度以上カートに追加する状況が発生した場合の処理がわかりません
同じitemIDの個数(item_num)を+1するupdateするとしたら
最初にitemIDをキーにselectを実行して存在すれば+1のupdateという流れ以外無理でしょうか
(一つのクエリで実現できないものかな、と)
それとも、同じitemIDの「行」をupdateするという考え自体捨てて
どんどん新規にinsertして行った方が良いんでしょうか。
一般的にはどうだ、というものがあれば聞かせてくれると嬉しいです
よろしくお願いします
SQL以前の話なんだが、何がしたいか分からん
要件がわからん
要件も決まってないのにテーブル設計してるのもわからん
SQLの話なら、
updateしたければすればいいし、insertしたければすればいい
どちらかしたいというなら、mergeとかupsertとか調べろ
>>233 そもそもカートにDB使わない。
cookieに入れて処理。
処理速度の部分でたぶんものすごい基礎的なところなんですけど
テーブルA,Bで
A UserID 100件
B UserID , Userの所持品(一人100個) 、各所持品の値段
とあった場合に
両方を結合してからUserIDでGroupするのと
Bをサブクエリで先にGroupしたものを結合するのだとどのような効果になるのでしょうか
>>237 実装に依存する話なのでこのスレはふさわしくない
使っているDBMSのスレで聞こう
239 :
NAME IS NULL:2013/10/09(水) 03:04:48.40 ID:UYLm0PgE
ベンチマークとって速いほうにすりゃいいじゃん
って思ったけどもっと仕様的な事が知りたいのかな?
大前提として、SQLは書いたとおりに実行されるとは限らない
SQLだけをみて、どう実行されるかは分かりません
これ以上は使ってるDBMSのスレで聞いて下さい
SQL server 2008R2です。
補完方法について教えてください。
下記のようなテーブルデータがある場合VAL1=NULLの行に対して、
同じCODEのうち最も日付が近い(後ろ方向に)VAL1がNULLでない値で補完をしたいのです。
テーブルデータ
DATE(int) CODE(varchar) VAL1(int)
201301 AAAB 12
201302 AAAB NULL
201303 AAAB NULL
201304 AAAB 51
201301 AAAC 23
201302 AAAC NULL
201303 AAAC 52
取りたいデータ
DATE(int) CODE(varchar) VAL1(int)
201301 AAAB 12
201302 AAAB 51
201303 AAAB 51
201304 AAAB 51
201301 AAAC 23
201302 AAAC 52
201303 AAAC 52
よろしくお願いいたします。
NULLでない値が必ずあるという前提でいいかな?
select
`DATE`,`CODE`,
case when `VAL1` is null then (
select `VAL1` from T T2
where
T2.`DATE` = (
select min(`DATE`) from T T3
where T3.`CODE` = T1.`CODE` and
T3.`DATE` > T1.`DATE` and
T3.`VAL1` is not NULL) and
T2.`CODE` = T1.`CODE` and
T2.`VAL1` is not null)
else T1.`VAL1` end `VAL1`
from T T1;
>>238-240 そういうもんなのですね
MySQLなんですけど実際にやってみたら
後者が50倍以上早くなったもので何事かと
>>242 お返事遅くなりましたが、無事動作しました。
先頭がNULLのものも存在しますが、
それは放置でもよいので、このSQLで無事で動作できました。
どうもありがとうございました。
>>243 テーブルABを結合してからgroupかけたほうが遅くなる。
基本的なSQLの考え方として、テーブルABの結合したとき、単純に考えてテーブルAの行数が
UserID*アイテム数になったものを一時的に作成してからgroupをかけるから。
もちろんテーブルAの列数が少ない、もしくはテーブルBの行数が少ないならそう変わらない。
しかしまあ、テーブルBをgroup化してまとめたものを結合したほうが、考え方としては処理的に
軽そうっていうのが想像つくんじゃないかな。
ただDBMSによってはその辺微妙なところがある。
結合してからgroupっていうのに最適化しているDBMSがあるかもしれない。
あとMySQLはサブクエリの処理が遅いって言われてるから、group化して結合するほうが遅い場合
がある。これはプライマリキーやindexの貼り方とか設定によって変わってくるとか色々要因がある
ので、これ以上はスレ違いなのでググったり違うスレで聞いてくれ。
>>245 わかりましたー
ありがとうございます
もうちょっと体系的な勉強からしたほうが良さそうですね
SQLServerなんですが、
あるncharの文字列に日付やそれ以外の文字が格納されているのですが
これが日付の時だけ別の処理を施したいのですがどうすればいいですか?
ちなみに、別のフィールドが0の時はその他の文字、1の時は日付か空文字です。
case OTHER_FIELD when 0 then THIS_FIELD else 日付の時の処理 end
の日付の時の処理で困ってます。
SQL ServerってLIKE使えねーの?
あ違った。case when then THIS_FIELD の部分で文字がint型に変換出来ませんとか出ていた
つか日付じゃなかったらどうしたくて、日付ならどうしたいんだ?
単純に区別するだけならcaseでもwhereでもISDATEでも好きなの使え
251 :
NAME IS NULL:2013/10/16(水) 16:56:10.86 ID:Qxpo2MUC
質問していること以外で問題が起きてるの?
case 〜 when 〜 then THIS_FIELD else 〜のTHIS_FIELDは文字列型をSQLServerが何故かint型に変換しようとしててエラーになってる
253 :
NAME IS NULL:2013/10/16(水) 17:39:54.63 ID:j81of1eF
mysqlなんですけどdate型とtime型の値を使って新しく作ったカラムのdatetime型に挿入したいのですができません。
insert into テーブル(datetime) select concat(date,' ',time) from テーブル;
こんな感じでやってみたんですがなんかエラーはでないけどnullのまま。
どうすりゃいいのかわからないので誰か教えてください!
254 :
NAME IS NULL:2013/10/16(水) 18:20:21.98 ID:j81of1eF
select文単体でやると「2009-01-01 10:00」みたいに出ます。
それをdatetime型のカラムにに挿入したいだけなんだが…
255 :
NAME IS NULL:2013/10/16(水) 18:25:19.49 ID:j81of1eF
あっもしかしてupdateでやればいいのかな…俺アホかもしれん。insertじゃ無理か。
concatで文字列が返るからdatetimeにキャストするとか?
257 :
NAME IS NULL:2013/10/16(水) 19:03:38.98 ID:j81of1eF
お騒がせしました。なんとかできましたw
同じテーブルの同じとこに更新か
>>252 CASEのヘルプ見ると
>戻り値の型
>result_expressions およびオプションの else_result_expression の型のセットの中から、最も優先順位の高い型を返します
ってなってるからな
THIS_FIELDがint型なんだろ
ああ、ちがう
elseでもどしてるのがint型だな
いや、
>>247みたらwhen 0か
そこでintで比較してるのかな
thenの後は出力したい物を書くところじゃないのか…
あ、Current_Timestampを置いたらエラーになったな。これがダメなのか。
THIS_FIELDがtext型だからdatetime型はそのまま表示出来なかったり、
int型の結果だったりが変換出来なかっただけだったらしい
次のようにして解決しました。お騒がせしました。
case FIELD_TYPE when 0 then THIS_FIELD else
case isdate(THIS_FIELD) when 1 then
str(datediff(yyyy,CONVERT(datetime,THIS_FIELD),current_timestamp))
else THIS_FIELD
end
end
265 :
NAME IS NULL:2013/10/17(木) 16:10:40.34 ID:zvWiJyP2
逆アクセス解析を作りたいのですが、
1年分のデータを蓄積する場合にテーブル設計はどのようにするのがいいのでしょうか
それとも、ログに書き込む方が理想的なのか・・・・
266 :
NAME IS NULL:2013/10/17(木) 16:14:03.36 ID:+UG0MVbJ
何をやりたいのか、よくわからない
267 :
NAME IS NULL:2013/10/17(木) 16:15:13.11 ID:zvWiJyP2
逆アクセスランキングを作成したいのです・・・
アクセスって何のアクセス?
逆ってなんの逆?
270 :
NAME IS NULL:2013/10/17(木) 16:59:26.76 ID:+UG0MVbJ
こういうことをするにはどういうSQLを書いたらいいか?
そういう質問とはちょっと違うよね?
ランキングならfluentd + redisだな(適当)
272 :
NAME IS NULL:2013/10/22(火) 19:57:31.97 ID:QHt9HIxR
DB: Oracle11g XE
横持ちのレコードを縦持ちに変換する簡単な方法はないでしょうか?
create table yoko (
foo_id varchar2(8) primary key,
val1 number,
val2 number,
val3 number,
val4 number
);
insert into yoko values ('a', 10, 20, 30, 40);
insert into yoko values ('b', 11, 21, 31, 41);
create table tate (
foo_id varchar2(8) primary key,
val_no number primary key,
val number
);
insert into tate values ('a', 1, 10);
insert into tate values ('a', 2, 20);
今はUNIONでつないで全valを変換しているのですが、現在val1068まで来ており今後さらに拡張予定です。
ちゃんと正規化してそれなの?
ちゃんと設計されたテーブルが、カラムが今後拡張予定とかないだろ
今縦持ちに変換したら、すくなくとも今後カラム増やす必要なんてなくなるだろうし
まあ、ホストアプリかストアド組んで変換するしかないんじゃない
11gなら unpivot 演算子で少しは楽できるんじゃないかな
それよりval1からval1068まで歯抜けがないとしたら
カラム数の上限を突破していると思うんだけど、そっちが気になってしょうがない
277 :
NAME IS NULL:2013/10/25(金) 20:32:59.92 ID:4tXZFiaL
ファイルをgmailのようにラベルで管理するプログラムを作りたいんですが
データベースをどういう構造にすればいいか悩んでいます
以下は思い付いた構造と検索方法なんですが、もっといい方法があればアドバイスお願いします
・ひとつのテーブルに <ファイルパス>|<区切り文字で区切ったラベルリスト、たとえばlabel1,label2,label3> として
LIKEやMATCHでラベルリストを検索後、マッチしたラベルリストを区切り文字で分解し、検索とラベルの精査をする方法
・ラベルごとにテーブルを設けてファイルパス(又は他テーブルでファイルパスをインデックス化したもの)を格納する方法
お疲れ様です。山下です。
以下のような内容のSQLの実現方法についてご教授下さい。
フィールドはこのようになっています。
"ID","subID","value"
実データが
1,1-1,A
1,1-2,B
2,2-1,C
2,2-2,NULL
2,2-3,D
3,3-1,E
3,3-2,G
3,3-3,I
3,3-3,NULL
このテーブルからsubIDでユニークな結果を出力する必要があり、value部分での条件分けが必要になります。
@既にsubIDでユニークな場合はそのまま出力をする。
AsubIDが重複する場合は必ず片方のvalueはNULLなのでvalueを持つものを出力する。
※valueがNULLでも既にsubIDでユニークな場合はそのまま出力します。
上記例だと結果が
1,1-1,A
1,1-2,B
2,2-1,C
2,2-2,NULL
2,2-3,D
3,3-1,E
3,3-2,G
3,3-3,I
このよう結果を期待します。
以上、よろしくお願いします。
>>280 >AsubIDが重複する場合は必ず片方のvalueはNULLなのでvalueを持つものを出力する。
同一subIDで複数の異なる非NULL値があった場合はどうしますか?
>>280 group by ID, subIDでmax(value)とか手抜きだろうか?
>>282 俺もそれで良いと思うが
subIDがどういう意味なのかよくわからんな
ID=1でsubIDが2-xとかあったりするんだろうか
subIDだけでグループ化すれば良いんじゃね。設計が悪いってのはあるけど
>>281 重複する場合、"必ず"片方はNULLなのでそのケースはないので除外します。
>>282 それでちょっと試してみます。
>>283 例としてあげるのは良くなかったかもしれないですね。
設計ミスではなく、ログデータに存在する項目を総取りしなきゃならないので、この形で設計されてます。
ID1,subID2-xはないはずで、そういうものがないはずですが例外として存在することも今後あります。
oracle11gですが
<<hoge>>
のように不等号で囲まれているのはなんという名称でしょうか
>>284 >>281はたとえば
2,2-2,X
2,2-2,Y
2,2-2,NULL
ってデータがあったときにどうするって言ってるんだと思うが?
>>286 すいません。
あっても必ず二つまでしか重複しないようになってます。
それとgroup byとmaxで解決できました。
ありがとうございました!
ネット上ではワイルドカード(*)はできるだけ使わないほうがいいとありますが
例えばカラムが10個あって9個必要な場合も*を使わないほうがいいのでしょうか?
当たり前だ
めんどくさがらず必要テーブル名だけ全部書くことにします
ありがとう
カラム名じゃなくてテーブル名を?
いえ、カラム名です すいません
*は後で項目が追加されたときとかに、バグの原因になるからね。
ああ select * のことを言ってたのか
ワイルドカードとか言うから like 'hoge*' みたいなこと言ってるのかと思って意味分からなかった
'*' で like の方が意味わからん。
296 :
NAME IS NULL:2013/11/02(土) 12:00:10.89 ID:EKiJUbY2
*が好き ということだな
外部結合って、where区で T1.NAME=T2.NAME(+)って書くのと、
LEFT OUTER JOINとONを使って書くのだと効率は同じ?
>>297 それだけでは判断できんが、まあ、同じ
SQLは書いたとおりに実行されるとは限らないので、最終的には実行計画みろとしか言えん
【複数テーブルからの累計取得】
ORACLE 11gです。
以下のような2つのテーブルから4/1〜6/30までのamount累計を
取得したいのですがどのようにSQLを書けばよいでしょうか?
月末の累計値は該当する日付、コードがTABLE_Bに存在する場合は、
TABLE_Bから取得し、存在しない場合はそれまでの累計値から取得します。
TABLE_A
day,code,amount
4/1,1,100
4/2,1,100
:
4/30,1,100
5/1,1,200
5/2,1,200
:
5/31,1,200
6/1,1,300
6/2,1,300
:
6/30,1,300
TABLE_B
day,code,amount
4/30,1,2800
欲しい結果
day,code,amount,cum_amount
4/1,1,100,100
4/2,1,100,200
:
4/29,1,100,2900
4/30,1,100,2800 ← TABLE_Bから取得
5/1,1,200,3000
5/2,1,200,3200
:
5/30,1,200,8800
5/31,1,200,9000 ← TABLE_Bに存在しないので累計値
6/1,1,300,9300
6/2,1,300,9600
:
6/30,1,300,18000 ← TABLE_Bに存在しないので累計値
よろしくお願いします。
5/1は3100じゃなく4/30で書き換わったcum_amountから引き継がないと駄目なのか
つかもうデータ引っ張った後に表計算かプログラムかでどうにかしろよと思いたくなるな
TABLE_Aを月別にサマリ、そのうちTABLE_Bに存在しない行とTABLE_Bをunion
そいつを指定月で絞ってサマリ
こんな感じでできるんじゃね
俺ならまずそんな設計してるやつを問い詰めに行くが
>>299 クソ設計乙
with rec(Val,iday,amount,cum_amount) as(
select 0,TO_DATE('2013/04/01','YYYY/MM/DD'),0,0 from dual
union all
select Val+1,
TO_DATE('2013/04/01','YYYY/MM/DD')+r.val,
nvl(t1.amount,0),
nvl(t2.amount,nvl(nvl(t1.amount,0) + r.cum_amount,0))
from rec r
left join table_a t1 on t1.day = TO_DATE('2013/04/01','YYYY/MM/DD') +(r.val)
left join table_b t2 on t2.day = TO_DATE('2013/04/01','YYYY/MM/DD') +(r.val)
where Val+1 <= 365)
select Val,iday,amount,cum_amount from rec
where iday between TO_DATE('2013/04/01','YYYY/MM/DD') and TO_DATE('2013/06/30','YYYY/MM/DD')
and val > 0
;
あんまり良いSQLではない、日付指定は一つにできると思うんだが、、
エロい人、、改善よろしく。
ただ、このSQLは、5/31にTABLE_Bにどのような累計が入るかで
修正する必要あり。
TABLE_B
day,code,amount
5/31,1,9100とかって4月からの累計が入るなら良いんだが、
5月分の累計が入ってると少し変更する必要あり。
それ累計じゃなくてタダの合計ですから
>>303 この人の言っている意味が分からないんですが・・・。
欲しい結果の通り出るんですけど・・・。
再帰SQL知らないのかな・・・。
すいません教えてください。
sqlite 3.8.1 です
select で as 指定した別名を同じ select 内で取得するカラム名として使用する方法はありませんか。
select
count(*) as matches,
sum(goals) as goals,
goals / matches as goals_per_match
from
match_results
のようなことしたいのですがこれだとエラーになります。
このようなことはできないのでしょうか。
sqliteを知らないのですが、、
select
res.goals / res.matches as goals_per_match
from (
select
count(*) as matches,
sum(goals) as goals
from
match_results
) res
これではダメですかねぇ。。
>>306 うぉぉできましたできました!
ありがとうございました!!
sqlite知らんが、普通に考えれば
select
count(*) as matches,
sum(goals) as goals,
sum(goals) / count(*) as goals_per_match
from
match_results
だろ
>>305のようにかければ便利な気はするが、ほとんどのRDBMSで出来ないと思う
あと、ほんどのRDBMSで平均出す関数があると思うぞ
>
>>305のようにかければ便利な気はするが、ほとんどのRDBMSで出来ないと思う
これなんでできるようにしないんだろう?
ちょっとした構文定義してフィールドなのかエイリアスなのか区別できるようにして、SQL パースしたときに
>>308 のように変換すればいいだけなので実装は難しくないと思うんだけど、ニーズがないのかなぁ...
goals / matches の goals がどっちか迷うからじゃないか
同じような話題でちょっと前にpostgresのスレが荒れてたなあ
よく読んだらぜんぜん違った
>>310 それはいくらでもやりようがあると思う。
Oracle の dual 表みたいな感じで、例えば alias 表作って、これは alias を参照するとか。
>>305 なら
select
count(*) as matches,
sum(goals) as goals,
alias.goals / alias.matches as goals_per_match
from
match_results
みたいな感じ。
お前dual 表ってなんだと思ってるんだ
人生…かな
ヅアル
PostgreSQL 8.4.11で
table1
name id(ユニーク)
a 1
a 2
a 3
b 4
b 5
c 6
から、
name name出現個数 id(最大2個までsort表示させる)
a 3 1 2
b 2 4 5
c 1 6
のような結果が欲しいのですが、どうすればよいでしょうか?
無理なら最小idを一個ずつでもいいです。
後者なら普通に、
select name, count(*), min(id) from table1 group by name order by count(*)
でいいんじゃないのかな。
二つ出す場合は、相関サブクエリの結果とくっつけることになるかな。
もしかしたらうまい方法が他にあるかもしんない。
>>317です。
>>318さま早速のレスありがとうございます。
すみません、簡略化ミスで、idは数字でなく文字列になります。
PostgreSQL 8.4.11で
table1
name id(ユニーク)
a あ
a い
a う
b え
b お
c か
から、
name name出現個数 id(最大2個までsort表示させる)
a 3 あ い
b 2 え お
c 1 か
のような結果が欲しいのですが、どうすればよいでしょうか?
無理なら最小idを一個ずつでもいいです。
>>320さま早速のレスありがとうございます。
明日、dbで試してみます。
できればid最大2個までsort表示させる方もよろしくお願いします。
functionを使ってみた。一度登録したら、最後のSQLだけで結果は出ます。
drop function top2(varchar);
create function top2(varchar) returns text as
'
declare
param alias for $1;
cu cursor for
select id from table1 where name = param order by id limit 2;
ret text := '''';
rec record;
begin
open cu;
loop
fetch cu into rec;
if not found then
exit;
end if;
raise debug ''id = %'', rec.id;
ret := ret || rec.id || '' '';
end loop;
close cu;
return ret;
end;
'
language 'plpgsql'
;
select name, count(*), top2(name) from table1 group by name order by name;
oracle9i環境です。
以下の木構造sqlを9iで再現するにはどうしたらよいでしょうか。
select
ID,
NextID,
sys_connect_by_path(to_char(ID),',') as path,
connect_by_IsCycle as IsCycle
from
RosenMap
start with ID = 10
connect by nocycle prior NextID = ID;
レコードはループしています。
ID NextID
10 20
20 10
ループしてるなら木構造じゃないと思うが
nocycleを9iで実現する方法を聞いているならたぶん無理
>>320さま
min,maxが数字のみ対象と思い込んでいたので、min(id)も入れて、
select name, count(*), min(id), max(id) from table1 group by name order by count(*)
で対応できました。ありがとうございました。
>>322さま せっかく作って頂いたのですが、利用しているDBは読み込みのみ可だったので、
ユーザ定義関数ではERROR: transaction is read-onlyで
使えませんでしたがユーザ定義関数というのがこういう場面で使えることが分かり参考になりました。
もし、
>>319の結果ページのidにて任意の個数を出力させる方法が分かる人がいれば
教えて下さい。
>>318さんの言われるように相関サブクエリを使えばできそうな気はするんですが、なかなかできません。
>>325 たとえば2個なら
select t.*,(select min(id) from table1 where name=t.name and id>t.min_id) as min2_id
from (select name,count(*) as name出現個数,min(id) as min_id from table1 group by name) t
order by t.name
こんな感じでできる
3個とか4個とか、固定ならこの調子で出来なくはない
>>325 posgresql8.4だとarray_aggっていう関数があるらしいから、
select
t1.name,
t1.count(*),
t2.id[1],
t2.id[2]
from (
select
*
from table1
group by t1.name
order by count(*)
) t1
left join (
select
name,
array_agg(id)
from table1
order by id
) t2 on t1.name = t2.name
みたいな感じでいけるんじゃないかなと。
idのnullは配慮していないのと環境が無いからテストしていない。
あーたしかに。配列を使うことで簡潔に書ける場面をもっと知っておかないとなぁ
posgresqlしらんしそのarray_aggとやらがどんなものか知らんが
group by 書いてるselectに*とか
joinする両方のサブクエリにorder byとか
それホントにちゃんと動くの?なんだか無茶苦茶な気がするけど
Postgres(にかぎらずDBの)の配列は使いにくいよ
アプリケーション側で処理したほうがよっぽど楽
331 :
328:2013/11/14(木) 00:51:48.67 ID:???
array_aggつかえば?という言葉だけで納得してたわ。
せっかくなんでクエリ。
>>325 select name, cnt, ids[1], ids[2] from
(select name, count(*) as cnt, array_agg(id order by id) as ids from t1 group by name) t1
order by cnt desc
332 :
328:2013/11/14(木) 00:56:50.14 ID:???
こうも書けたけど、どっちもいまいちかっこよくないね…
select name, count(*) as cnt, (array_agg(id order by id))[1], (array_agg(id order by id))[2]
from t1 group by name order by cnt desc
333 :
327:2013/11/14(木) 01:20:40.95 ID:???
>>329 動かねぇよ!!(逆ギレ)
すみません書き直しました。
けどテスト環境ないんで動くかどうか自信ありません。
select
t1.name,
t1.cnt,
t2.id[1],
t2.id[2]
from (
select
name,
count(id) as cnt
from table1
group by name
order by cnt
) t1
left join (
select
name,
array_agg(id) as id
from table1
order by id
) t2 on t1.name = t2.name
>>330 それ言ってしまうと。大半の質問がアプリでやれって回答になるんだぜ……。
>>332 id order by idってそこでも書けるの知らなかった……。
そっちのほうが短くていいですね。
SQLって、予約語やデータ型は大文字で書くのが主流なんでしょうか?
今までずっと小文字で書いていたんですが、「予約語とそうでない語の区別ができるように、前者は大文字で、後者は小文字で書きましょう」と言われて、ちょっと驚いたので。
みんなどうしてますか?
>>335 order byは別名使えるでしょ。SQL標準(たぶん92あたり)の範囲だったような。
んで、サブクエリのorder byは指摘のとおり不要。というか、無意味。
エラーにこそならないが、順序が結合後も保たれる保証はないはず。
あと、array_aggを調べるつもりがないことを散々主張してる理由って、標準じゃないから?
sql:2008には盛り込まれてるようだけど。
337 :
325:2013/11/14(木) 19:54:31.87 ID:???
group化した要素idを任意の個数だけ表示する
>>319,
>>325の件につき、色々なアイデアありがとうございました。
>>332さんの方法で、うまくいきました。 (array_agg(id order by id))[2]でnullがあるケースではエラーにならず、
何も表示されずという状態になります。COALESCEを使えばより安全なのかもです。
>>326さんの方法が汎用性がありそうなので、3個表示を目指し、下記2つをやってみたのですが、うまくいきません。
オリジナルの2個表示は上手くできました。
select u.*,(select min(id) from table1 where name=u.name and id>u.min_id) as min3_id
from (
select t.*,(select min(id) from table1 where name=t.name and id>t.min_id) as min2_id
from (select name,count(*) as namecount,min(id) as min_id from table1 group by name) t
order by t.name
) u
order by u.name
select t.*, (select min(id) from table1 where name=t.name and id>t.min_id) as min2_id,
(select min(id) from table1 where name=t.name and id>t.min2_id) as min3_id,
from (select name,count(*) as namecount,min(id) as min_id from table1 group by name) t
order by t.name
正解を教えて下さい。
そもそも任意の数を横に表示しようという考え方をやめた方がいいぞ
id>u.min_id じゃなくて
id>u.min2_id だと思うが
つか何やってるか理解してる?
341 :
325:2013/11/14(木) 20:42:12.78 ID:???
>>339さま ありがとうございました。これでうまく行きました。
select u.*,(select min(id) from table1 where name=u.name and id>u.min2_id) as min3_id
from (
select t.*,(select min(id) from table1 where name=t.name and id>t.min_id) as min2_id
from (select name,count(*) as namecount,min(id) as min_id from table1 group by name) t
order by t.name
) u
order by u.name
この方法はいま使っているDBでは2分かかり、
>>332さんの方法では、2秒で終わります。
DBが大きく、クエリをたびたび出したり、大きなデータをそのまま取り出せない状況ですので、こんなことになってます。
皆様色々とありがとうございました。
>>330 アプリケーション側で処理したほうが楽っていうけど、擬似コードでいいから書いてもらえる?
コストもメモリ使用量も酷いものしか思いつかないんだ。
連投ごめん。
>>341 ついでにこれも試してみてもらえると嬉しいな。
array_aggの回数が半分で済むから速度は上がると思うんだ。
それに、3 4 と増やすときも楽かなと。エラーにならずにNULLが出力されるのは仕様だから安心していいよ。
with t as (select name, count(*) as cnt, array_agg(id order by id) as ids from t1 group by name)
select name, cnt, ids[1], ids[2] from t order by cnt desc
相関サブクエリの方の速度を上げる方法はちょっと思いつかず。
さらに連投。。。
最終出力、出現個数の多い順にソートするものだとばかり思い込んでたけど、よくみたら違った。
まぁ、それはたいした違いじゃないけど、一応。
DBとの回線の太さとかにもよるけど、速度求めるならホストアプリで
合計と、それぞれのトップ2行(もしくは任意の行数)別にとる方が早いし汎用的だろうに
>>345 クエリは select name, id from table1 order by name, id で、
あとはアプリでやれってことでいいのかな。
一般的にありがちな、nameの昇順に10レコード表示したいというシナリオの場合でも同じクエリ?
俺なら、2、3個程度なら
>>326でやる
任意に数個ってなら、ホストアプリで
select name, count(*) from table1 group by name order by name
を発行して、このレコードセットをループしながら
select id from table1 where name=???
をtopなりoffsetなり指定して発行する
固定数でも数が多いなら、
select name,id,(select count(*) from table1 where name=t.name) as cnt from table1 order by name,id
を発行して、どうしても横表示したいならアプリで縦横変換かな
何にしてもnameにインデックス張っとかんと早くはないだろうけど
OLAPサーバー扱ってる人いないですかね・・・
>>347 たとえば10レコードほしいっていう場合、前者は1+10回クエリ発行することになる。
で、クエリ発行回数が増えるのを嫌って後者を出したのかと思うけど、
その場合はLIMITなりTOPなりをつけることなく、全件取得するの?
それとも小難しい計算をはさめば必要なデータだけ抽出できたりする?
>>348 いようがいまいが質問を書かないことにはどうにもならんでしょ。
>>349 予想されるnameの件数やnameあたりのid数と必要件数、処理の内容等によりけり
つまり、ケースバイケース
固定数で縦持ちなら1文でできる
nameあたりのid数が多くて必要数の上限が少なく、処理時間が問題になるなら固定で1文で絞るSQL書くかもしれんが
あんまりそう言う想定が浮かばん。バッチ処理ならどうせ全行いるだろうし、対話なら画面に収まる行数なんてしれてるだろ
・DBMS名とバージョン
SQLight
・テーブルデータ
table1
_id|year|month|day|・・・・
ーーーーーーーーーーーーーーーー
‥‥‥|‥‥‥‥.|‥‥‥‥‥‥‥|‥‥‥|・・・・
‥‥‥|2013|11 |15 |・・・・
‥‥‥|‥‥‥‥.|‥‥‥‥‥‥..|‥‥‥‥|・・・・
table2
_id|year|month|day|・・・・
ーーーーーーーーーーーーーーーー
‥‥‥|‥‥‥‥.|‥‥‥‥‥‥‥|‥‥‥|・・・・
‥‥‥|2013|11 |15 |・・・・
‥‥‥|‥‥‥‥.|‥‥‥‥‥‥..|‥‥‥‥|・・・・
・欲しい結果
上記のようなテーブルが2つあって
yearとmonthとdayが一致する行のデータ
をtable2から取り出して処理したいです。
・説明
自分はDB自体初心者でAndroidアプリを作成するうえで
SQLightを使うことになりましたが、ネットを参考に
手探りでやってるレベルです。
SQLightのスレにも書いたのですがこちらのほうが良い
と、思い書き込みました。
どなたかご教示願います。
idは不一致でいいの?
テーブル1に日付があるレコードをテーブル2から取り出すってことで合ってる?
353 :
351:2013/11/15(金) 12:28:35.92 ID:???
>>352 はい
日付のみが同じ部分を取り出す
という処理がしたいので
_idは、気にしなくて良いです。
それならselect year,month,day from table2 where exists(select X from table1 where table1.year =table2.year and (省略) )
SQLightでもしサブクエリ使えなかったらselect distinct table2.year,table2.month,table2.day from table1,table2 where table1.year =table2.year and (省略)
でいけると思う
試してないけど
355 :
325:2013/11/15(金) 21:00:58.42 ID:???
>>343さま ありがとうございました。試してみたのですが
>>332 と同じでした。CGIを作っている訳ではないので、2sで充分満足です。
SQLightて…
>>355 With句つかうのは許されるの?
SQLに制限はありますか?
SQLightでググったら、上位は全部SQLiteの記事だったんだ
何が起こってるか俺にもわからねぇ
>>357 対象RDBMSで使える機能は使えばいいと思うよ
360 :
357:2013/11/16(土) 14:47:26.91 ID:???
>>359 with v1 as (
select
Row_Number() over(partition by name order by id) as jid,
name,id
from table1
)
select v2.name,v2.cnt,l1.id,l2.id
from (
select count(1) cnt,name from table1 group by name
) v2
left join v1 l1 on l1.name = v2.name and l1.jid = 1
left join v1 l2 on l2.name = v2.name and l2.jid = 2
これでどうですか?
ジョインを増やせば任意の個数を増やせる
後はIDをCoalesceで文字列結合するだけ。
361 :
351:2013/11/17(日) 06:28:03.54 ID:???
>>354 ありがとうございました。
大変参考になりました。
もっと独学をして知識を積むようにも心がけていきます。
質問です
・MySQL5
要件
・並び替え、集計
・主キーは注文番号
注文番号 商品 都道府県
-------------------------------------
1 みかん 東京都
2 りんご 東京都
3 りんご 大阪府
4 りんご 埼玉県
5 なし 北海道
6 なし 北海道
7 なし 東京都
のように膨大な注文番号+注文商品+都道府県が取得できるとき、
みかんが一番売れている都道府県、
りんごが一番売れている都道府県
なしが一番売れている都道府県
を取得するにはどのように設計、クエリを発行すればいいんでしょうか。
結果をどういう形で出したいかによるな
>>5の応用でもできるし
みかんを注文した後に、みかんを一番買っているのは東京都です!
なしを注文した後に、なしを一番買っているのは北海道です!
って出したいんです。
なしを選択した場合、
select count(都道府県), 都道府県 from table where 商品 = なし group by 都道府県 order by count(都道府県) limit 1
とか?
訂正。
select 都道府県 from table where 商品 = なし group by 都道府県 order by count(都道府県) desc limit 1
MySQLは本当自由だな
そんなことできちゃうんだ・・・
>>364 ところで
> みかんを注文した後に、みかんを一番買っているのは東京都です!
なんて表示してなにか嬉しいのか?
どちらかと言うと.、東京都の人がみかんを注文したら、「東京都の人が一番買っているのは りんご です」とか表示した方がいいと思うが。
>>366 ありがとうございます!
大変勉強になりました
GROUP BY ORDER BYをこうやって使うんですね
高速化させるために都道府県カラムのデータを数字の1-47にして、TINYINT型にしました
phpの側で都道府県名に変換することにしましたが、
この程度の違いでも効果はあるんでしょうか
それで体感できるぐらい速度差が出るようなら、サーバ替えた方がいいよ
とりあえず遅いなら、(商品)か(商品,都道府県)にインデックス張れ。話はそれからだ
そこで玄人さんが華麗なテクニックを披露してくれるんじゃないんですかー
一度言ってみたかっただけじゃないの?
素人も玄人もそこは都道府県マスタつくりなよってツッコミをいれる場面じゃないの
例がその場限りっぽすぎて
そういう具体的な答えは出しにくい
377 :
NAME IS NULL:2013/11/22(金) 07:05:55.23 ID:RnJw9fzF
phpmyadminでカラムの非表示ってどう解除するんでしょうか
カラム 'id' と 'syutoku' があるとします
select * from table
でカラム'syutoku'が表示されなくなり、更に追加したカラムも表示されません。
なぜか
select id,syutoku from table
では表示されました。何が原因なのでしょう?
テーブルをコピーし、名前を変えると元に戻りました。
378 :
NAME IS NULL:2013/11/23(土) 10:17:12.94 ID:hfIPaKQw
>>378 設計はスレ違いなんだが
タイプが表すのは子の種類
つまり子の属性なんだから、子のテーブルに持つのが普通じゃないか
>>378 idとtypeの関係を保証するため。
これがないと、同じidを異なるsubに登録できてしまう。
381 :
378:2013/11/23(土) 16:59:42.53 ID:???
ありがとうございます!
アプリケーション側に一任せずに、設計上でもちゃんと制限したほうが良いという感じでしょうか
そしてスレ違いごめんなさい。
制約で保証するかアプリで保証するかは好きにすればいい。
foreign keyだって別に必須じゃないわけだし。
mysql5系の質問です
DBを作る時の「MyISAM」と「InnoDB」の違いがよくわかりません。
ゴミでもわかりやすいように教えて頂けないでしょうか?
>>383 少なくともMySQLスレがあるんだからそっちで聞け。
ググれアホで終わる気がするが。
すいません。質問スレだったのでここでいいかと思ってました
SQLの質問であってMySQLの質問じゃないんだなこれが
>>386 ありがとうございます
ググってみたらわかりました
sqlserver に newid() というユニークな32バイトバイナリを返す関数がありますが
あれの long 版の関数を作りたいです。
newno() みたいな風で、関数を呼ぶたびに +1 しながら値を返すという風で
それ自体は採番テーブルを使って簡単にできると思いますが
呼び出し元のトランザクションとは別の独立したトランザクションで動かしたいのですが
どうやってやるんでしょうか。
つまり、呼び出し元が
insert into ××× values(newno(), ×,, ×, ×, ×);
みたいに利用したあとで rollback しても newno() の採番テーブルは戻ってほしくないのです。
ついでにsqlserverでもうひとつ
SELECT 〜 と結果セットを返すストアドAがあって
ストアドBの中でストアドAを呼ぶと、ストアドBの結果セットにストアドAの結果が出てきますが
内部で他のストアドを呼んだときに戻ってくる結果セットを無視させる(読み落とす)ことはできないですか?
どちらもスレ違いです
SQLの質問スレであってSQLServerの質問スレじゃないんだなこれが
そっちへ移ります。すみません。
シーケンスの使えないバージョンなんじゃないか
SELECT 何か
FROM テーブルA
というクエリに、テーブルAのidで検索して、テーブルBの中にデータがあるかどうか(true / false)をSELECTに加えたいんですが
どうすればいいのでしょうか
DBはPostgreSQLです
SELECT
A,
B,
C,
EXISTS ()
ってビルト通るのでしょうか・・・
397 :
396:2013/11/29(金) 22:39:29.12 ID:???
通りましたがまだよく分かりません
SELECT
テーブルA.id,
EXISTS(SELECT テーブルB.id FROM テーブルB WHERE 外部キー = テーブルA.id)
FROM
テーブルA
WHERE
条件
これって条件に一致したテーブルAのidがEXISTSに送られて、そこでTRUE/FALSEが評価されてるのでしょうか?
>>397 結果の列ごとの評価だから、期待した結果になると思うよ。
私だったら、テーブルBを外部結合かな。
select a.id,
case
when max(b.id) is null then true
else false
end
from a, b
where a.id = b.id (+)
group by a.id
とか。
399 :
396:2013/11/29(金) 23:59:10.59 ID:???
>>398 ありがとうございました
whereで絞ったあとの1行1行に対してselectで更に評価するんですね
> DBはPostgreSQLです
>
> SELECT
> A,
> B,
> C,
> EXISTS ()
これに対する
>>398の回答は
・PostgreSQLでは使えない方言
・複数カラム抽出したそうな意向を無視したgroup byへの変更
・条件判定ミス
となっている。ここまできたらネタ回答としか思えない。
select tableX.A,tableX.B from tableX; と打ったらこんな結果が出てくるテーブルがあるんですが
A |B
あああ|んんん
かかか|ををを
さささ|わわわ
これに、各検索結果のtableX.AとtableX.Bの値を使い
select count(*) from tableY where tableY.A=tableX.A and tableY.B=tableX.B;
の結果の項目を追加するにはどうしたら良いのでしょうか
A |B |追加項目
あああ|んんん|1
かかか|ををを|0
さささ|わわわ|0
>>400 ORACLE信者をいじめないでください
>>401 select tableX.A,
tableX.B,
count(*)
from tableX,
tableY
where tableY.A = tableX.A
and tableY.B = tableX.B
group by tableX.A, tableX.B
;
>>400 ん?SQLスレだから、方言による差異を気にする必要あったのかな。
意味が通ればいいだろうと思ってざっくりで書いたんだがなぁ。
そもそも質問主の質問内容を見れば、そこまで求めてないと思うのだが・・
>>401 最近はOracleが多かったので(+)で表現したけど、Oracleは嫌いだ。*にすればよかったかな。
ただ結合条件をWHERE句で書くよう指導されていた世代なのでJOIN句は今でも苦手。
(+)って外部結合演算子って言うのですね
はじめてみました
標準規格にはないみたいですが、知っとかないとまずいですか?
会社でOracleとSQL Server扱ってますが、今のところ見たことないんです
どっちもOUTER JOINで出来るっぽいが使わないなら使わないでも全く問題ない
用途結構限られてるし
>>401 select tableX.A,tableX.B,
(select count(*) from tableY where tableY.A=tableX.A and tableY.B=tableX.B) as 追加項目
from tableX
>>406 古いORACLEはその書き方だったから、ORACLE扱うなら覚えておいて損はない
今はその書き方はしない方がいいけど
>> 408
スレチだけど・・・
プロジェクト内の11gR1での検証で、Oracle任せの抽出ではJOIN句の方が遅かった。
検証前の想定ではオプティマイザが吸収するので同じ結果になるのでは・・・くらいかんがえていたんだけどな。
結果、コーディングルール上は、(+)を推奨することになった。
できるだけ使わないのが正解ではあるが。
なんだかんだ言いつつも、where句での解析の方が判断しやすいのではと推測している。
>>409 オプティマイザを出すならバージョンを書いてくれ
>>409 Oracle 9iのときはバグもあったし速度も遅かったから
うちも非推奨にしてた。
10gからは変わらないから(+)を使わないルール。
もうオラクルはオワコンだろ、どう見ても
>>410 11gR1って書いてあるぞ
11gR1だと同じだと思うんだけどな
>>410 ここで細かいVersion出して掘り下げても意味なくないか?
サポートも動かしての検証なので、精度的には間違いないと考えているし、11gR1の頃なので、仮に今更、間違いだったと指摘されても寒い。もう、リプレイス計画進めているし。
>>412 Oracleがオワコン?
商用RDBの中では、Oracleはまだ頑張っているほうだぞ。
12cもカタログ通りだったら、面白い製品になりそうだし・・・
ただ、あそこのスペックは8の頃からの伝統があるしなぁ。
商用RDBオワコンという話であれば、ベンダサポートも含めて商用以外を選択しにくいケースがあるので、どうだろう。
ただ、無条件に商用RDB一択という時代は10年以上前に終わってる。
RDBがオワコンというのであれば、用途次第というところじゃないかな。
いずれにせよスレチなので止めるね。
次からは、論点がずれないように標準的なSQLで答えるようにするわ。
おれの周りだとSQLServerに急速シフトしとる
Oracleじゃなきゃって信者と官公庁くらいじゃないか
早いとか遅いとかじゃなくて、どういう実行計画だったか見ないと意味ないし
>>415 参考に理由教えてもらえるかな?
やっぱ価格?
・安い(Expressでもかなりのことが出来る)
・クライアントソフト不要
・チューニングしなくても、そこそこパフォーマンス出る
・ストアドが行を返せる
・T-SQLの中で .Net の言語が書くこともできる
・T-SQLの中でメール送信を書ける(保守に便利)
等々。
シビアなレコードロックはオラクルが上手だけど、それが必要な場面って意外に少ない
Oracleなんて無駄にお布施してるだけで使いこなせてないとこが殆ど。
SQL Serverで十分だと馬鹿もやっと気付いたのさ。
DB死んだときに生き返らせてくれたからOracle信者続けるわ
金はらっときゃいいんだもの
うちの周りでよく話に出るのは
> ・チューニングしなくても、そこそこパフォーマンス出る
これ。
Oracleのチューニングのために人を呼んで高い金払って
やっとSQLServerとほぼ同じ速度になる
まぁ、速度以外でOracle優位になる部分もあるんだけど、それを必要とするかどうか、だよね。
そう考えると、速度を求めるためにOracleを選択する時代ではなくなったのかなと思う。
あ、そんなことを書いてる俺はPostgreSQLばかり使ってます。
まるでチューニングとかをしないとOracleは使い物にならんような言い方だな
使ったこともないやつがちょっと聞きかじった話を信じこんでる間抜けさが…
SQLServerだとミラーリングで待機側はライセンス要らない
それだけで半額だ
ObjectBrowserも買わなくていいな、SQLだと
sqliteに3DCGを埋め込みたいのですがどうやればいいんですか
また必要なソフトとかありますか
基礎的なことで申し訳ないんですが、
WHERE句である条件を完全一致させたいときは
普通に「ID = '00001'」みたいにしますけど、
それを「ID LIKE '00001'」としても、完全一致になりますよね?
%付けなければ。
なります。あとアンダースコアに気をつければ。
ワイルドカード文字とエスケープ文字、比較してるカラムの型あたりに気をつけないと
思わぬ結果になるかもしれんぞ
サンコス ナイスガイs
ある表の並び順をユーザーが任意に指定できるフィールド sort_key があります。
例)
id,sort_key
1, 3
2, 4
3, 2
4, 5
5, 1
…
この表の任意の行をアプリ側でユーザーが sort_key を変更したあと、
全行の sort_key を振り直すにはどうしたらいいでしょうか?
言わんとすることは分かったけど、状況によるよ。
・入れ替えなら、入れ替えればいい
・追加で割り込ませたいのなら、それよりも大きいものを+1
・削除のときにつめたいのなら、それよりも大きいものを-1
>>436 言葉足らずですみません。
入れ替えではないです、そんなのなら問題ない。
+1、-1 の方法だと、
update table set sort_key=(sort_key + 1)
と 同 (sort_key - 1) の両方が必要になりますよね?
なので困ってます。
つまり、
update table set sort_key=(sort_key + 1) where sort_key > n
と
update table set sort_key=(sort_key - 1) where sort_key < n
みたいなのが二つ
sortkeyでもなんでもいいから前レコードのid入れろ
つまり現在のsort_keyと更新値のsort_keyの間にあるsort_keyを持つレコードのsort_keyを1上げるなり下げるなりするってこと?
>>435のテーブル例に、id=3(現在のsort_key=2)のsort_keyを4に変更しようとしたときは、
2〜4の間にあるid=1(sort_key=3)とid=2(sort_key=4)のsort_keyを1減らした後にid=3のsort_keyを更新値である4に変更し、
id,sort_key
1, 2
2, 3
3, 4
4, 5
5, 1
にするってことでいいのかね?
というか俺の読解力がないだけなんだろうけど、どういうUPDATEを作りたいのかさっぱりわからん
>>440 はい、ずばりそのとおりです。
それを一回のupdate文でできないかなって…
アプリ側でやろうとすると結局行数分ループ回してインクリメントしなくちゃならないし、
そんなの数百行ならまだしも、数百万行とかなったら…
間にあるやつを、上か下にずらせばいいだけじゃん。
なんで2回発行しないといけないとか言い出すのかわからん。
5を2に移したいなら、2 3 4 を+1すればいいし、
1を5に移したいなら、2 3 4 5 を-1すればいい。
>>442 間にあるものを+1や-1した後に目当てのidのsort_keyを更新するの忘れてないか
それにしたって2個のSQL流せばいいだけで、すくなくとも
>行数分ループ回してインクリメント
なんてアホなことする必要ない
445 :
NAME IS NULL:2013/12/14(土) 21:29:07.01 ID:4Nkx3/nr
>>441 sort_key 2 のデータを 4 にし、他を順次繰り上げる場合
update `table`
set sort_key = (
case
when sort_key = 2 then 4
else sort_key - 1
end
)
where sort_key between 2 and 4;
上げるときと下げるときで分岐させる必要あるな
2→4だと-1で4→2だと+1にせな
sort_keyが2と4って入れられるんであれば、「sort_key - 1」の1の部分もSQL作る時点で入れたらいいんじゃね?
「sort_key +」を固定にして1か-1をどちらか入れる感じ。
なんでリスト構造にしないの?
>>448 RDBとリスト構造って相性悪い
てか、不倶戴天の敵w
>>448 要件次第。
隣が欲しいだけならリストは便利だけど、一覧でソートのようなことをするときは実に面倒
ある意味、リスト構造を駆逐するためにできたのがRDB
プログラミング言語から入ってきたばっかりで問い合わせ言語(SQL)の本質を正しく理解してないと、どうしてもそうゆう発想(リスト構造やツリーで処理する等)になっちゃうね
>>435 です。
色々とありがとうございました。
二つupdate文がいるっていうのは間違いでした。
該当行を前にもっていく場合と後ろにもっていく場合をcase文で振り分けて
インクリメントする場合とデクリメントする場合の両方を記述できました。
ありがとうございました。
でも、こうゆう処理(任意の並び順)ってけっこうあると思うんだけど、
あんまり例文がなかった。どうやるのが正しい?のかなぁ
あと、アプリ側で必要全行分ひとつづつupdate処理するのも試しましたが、
数千行程度なら一瞬ですね、何万何十万だと不安だけど
俺なら通番にしないで、10ごととか100ごととかに入力してもらうが
間が詰まったときだけメンテでごっそりずらす
>>455 では、スマートな方法よろしくお願いいたします。
457 :
NAME IS NULL:2013/12/16(月) 10:22:53.97 ID:qjREM8Gx
商品テーブル、商品ID、商品名、…
売上テーブル、商品ID、日時、…
こんな感じのテーブルで指定期間に売れた商品名だけを抽出したい場合
SELECT 商品T.商品名
FROM 商品T
WHERE EXISTS (SELECT 売上T.日時
FROM 売上T
WHERE (売上T.日付) Between #01/01/2013# And #02/01/2013#);
ってやると全商品名が出ちゃうのですが、何が間違ってるのでしょうか?
これだと何の商品が売れたのか分からないから
SELECT 商品T.商品名
FROM 商品T
WHERE EXISTS (SELECT 商品T.商品名
FROM 商品T INNER JOIN 売上T ON 商品T.商品ID = 売上T.銘柄ID
WHERE (売上T.日付) Between #01/01/2013# And #02/01/2013#);
ってやっても全商品名が出てダメでした
SELECT 商品T.商品名
FROM 商品T
WHERE EXISTS (SELECT 売上T.日時
FROM 売上T
WHERE (売上T.日付) BETWEEN #01/01/2013# AND #02/01/2013# AND 商品T.商品ID = 売上T.商品ID);
これで行けましたが、速度はOrderByやDistinctと大して変わらなかったです
他の方法考えます。どうもお騒がせしますた
×OrderBy
○GroupBy
↓だとスピード変わる?
SELECT 商品T.商品名
FROM 商品T
WHERE 商品T.商品ID IN (SELECT 商品T.商品ID
FROM 売上T
WHERE (売上T.日付) BETWEEN #01/01/2013# AND #02/01/2013#);
失礼、コピペミス
SELECT 商品T.商品名
FROM 商品T
WHERE 商品T.商品ID IN (SELECT 売上T.商品ID
FROM 売上T
WHERE (売上T.日付) BETWEEN #01/01/2013# AND #02/01/2013#);
>>461 変わるかどうか自分でSQLの実行時間を計測しろよ
あほなの?
>>456 評論家ってのは評論するだけ
実演とか求められないのよ
>>463 なにあほなこといってるの。
>>457氏は10万の売上レコードの用意が
あるかも知れないんだ。まず計測を依頼するのが自然だろ。
>>466 ごめん、全部同じ人のレスが続いているのか。
>>462 ありがとうございます。あまり変わらないですね
結局別のアプローチを取りました
全商品IDを総問い合わせで期間中の売れた商品名を抽出
スマートとは程遠いですが、一番速かったです、、、
>>464 ごめんね、ここ技術板だから役に立たない評論家は要らんよ。
聞くだけのやつも役に立ってない
>>468 select大量発行にしたら速くなったってこと?
単なる興味でだけど、前後の速度を知りたい。
インデックスに難があるんじゃないかと思うけど。
普通に商品と売上をJOINして絞れば良いと思うんだが
そのうえで速度は実行計画みて考えれ
>>471 商品テーブルは8000レコード(商品IDにPK)
売上テーブルの1300万(オートナンバーPK、商品IDと日付に複合Index)
全商品IDは勿論一瞬で出るので8000回ループで拾って完走まで5〜7秒
SELECT 売上T.商品ID
FROM 売上T
WHERE (売上T.商品ID)="8000回" AND (売上T.日付) Between #01/01/2013# And #02/01/2013#)
ORDER BY 売上T.商品ID, 売上T.日付;
>>459や他に商品Tと売上Tを含めると必要分だけ回せるのですが
26〜30秒くらい掛かります
日付に#って、まさかMDB?
>商品IDと日付に複合Index
>WHERE (売上T.日付) BETWEEN #01/01/2013# AND #02/01/2013# AND 商品T.商品ID = 売上T.商品ID);
これ、たぶんインデックスサーチ効いてないよ
日付のみキーのインデックス作って
>>459 >>462 を再試
>>470 あなたのレスで、役に立ったものを教えて下さい
8000回ループで拾ってとか、必要分だけ回せるとか、意味不明なんだが
なぜ素直にJOINしたSQLでやらないの?
なんで実行計画確認しないの?
>>474,477
凄いです。ドンピシャでした。
全商品目検査と同じくらいの速度になりました
こうしてまた一人、インデックスの魅力に憑かれた男がうまれたのであった。めでたし。
SQLightで
テーブルA
ID | DATE01|DATE02| DATE03| DATE04| DATE05|etc・・・
( DATE01,DATE02,DATE03, DATE04,DATE05は、それぞれ
違う日付のtext型の値が入っています。)
テーブルB
ID | DATE|etc・・・
ていうテーブルがあって
B.DATEとA. DATE01, A. DATE02, A. DATE03, A. DATE04, A. DATE05
を、比較して、同じ日付があった時、テーブルBから
その行のデータを取り出すという処理をしたいのですが
or文を使って実行したら、その行のデータを5回取り出して
しまいました。
自分の書いたsql文が間違っていると思うので
適切なsql文をどなたかご教示願います。
(初心者の質問ですみません)
またlight君か
484 :
NAME IS NULL:2013/12/18(水) 11:25:33.48 ID:EewOgcA5
>>482 まず、自分が書いたsql文をここに晒してみる
textを、比較する時
= 文字列
ではなくて
='文字列'
ですか?
そりゃSQLでの文字列は '文字列' だからな
487 :
NAME IS NULL:2013/12/20(金) 22:17:33.87 ID:7DjcGZuA
次のようなデータがあります。
tozai nihon
関東 関東
関西 関西
−− 関西
関西 関東
−− 関東
−− −−
関東 関東
関西 関西
(−−)は空のデータ
tozaiとnihonではtozaiが優先されます。
例えば、tozai=関西,nihon=関東となっていた場合、tozaiが優先されるので「関西」と見なされます。
この条件で、関東と関西のデータがそれぞれ何件あるか調査する為に次の3つのSQL文を出しました。
これらを一つの文にまとめたいのですが、どのようにしたらよいでしょうか?
select count(*) from hoge where tozai='関東' or (tozai='' and nihon='関東');
結果=3
select count(*) from hoge where tozai='関西' or (tozai='' and nihon='関西');
結果=4
select count(*) from hoge where tozai='' and nihon='';
結果=1
つ union all
select
sum(case when tozai='関東' or (tozai='' and nihon='関東') then 1 else 0 end) as col1,
sum(case when tozai='関西' or (tozai='' and nihon='関西') then 1 else 0 end) as col2,
sum(case when tozai='' and nihon='' then 1 else 0 end) as col3
from hoge
>>487 試してないけど
select x,count(*) from
(select case when tozai is null then nihon else tozai end as x from hoge) t
group by x
ああ、空のデータってnullじゃなくて空文字列なのか
nullと空文字列を区別できないDBMSじゃなければ
tozai is null をtozai=''に
null にしておけば coalesce とか使えるのにね
SQLServer2008R2です.
テーブルデータはDATE(YYYYMMの6けたのint型),CODE(varchar型),VALUE(float型)
の3カラムからなります.各DATEの各CODEに対して過去3か月分の総和を算出したいと思います.
元テーブル
DATE, CODE, VALUE
....
200101, AAA, 1
200102, AAA, 2
200103, AAA, 3
200104, AAA, 4
200101, BBB, 1
....
欲しい結果
200103, AAA, 6
200104, AAA, 9
.......
下記のようなSQLを書いたのですが,同じ結果の行が12か月分でてきます.
何処を修正すればよろしいでしょうか?もしくは全然違うSQLでしょうか?
SELECT A.DATE, A.CODE, SUM(B.VALUE) OVER (PARTITION BY B.DATE, B.CODE)
FROM TABLE A, TABLE B
WHERE A.CODE=B.CODE AND B.DATE>=A.DATE AND B.DATE>=(A.DATEの3か月前←計算式が長いので省略です)
ORDER BY A.DATE, A.CODE
よろしくお願いいたします.
>>493 手元に環境無いんでSQL自体は書けないけど、それは再帰SQLでいける。
>>493 FROMで結合するのにOVER句とか、どういう覚え方したらそんなSQL書くようになるんだろう
俺ならこう書くけど
select DATE,CODE,
(select SUM(VALUE) from [TABLE] where CODE=t.CODE and [DATE]<= t.DATE and [DATE]>t.DATE - 3)
from [TABLE] t order by DATE,CODE
結合でやりたいならこうじゃね
SELECT A.DATE, A.CODE, SUM(B.VALUE)
FROM [TABLE] A, [TABLE] B
WHERE A.CODE=B.CODE AND B.DATE<=A.DATE AND B.DATE>(A.DATE-3)
GROUP BY A.DATE, A.CODE
ORDER BY A.DATE, A.CODE
join使えよと思うが邪魔くさいので書きなおさない
DATE-3は3か月前のことな←計算式が長いので省略です
>>494 累計じゃないからこの程度で再帰とか要らんぜ
> A.DATEの3か月前←計算式が長いので省略です
これって、ついでにこれも教えてくれよってことなんだろうなぁ。
さすがにそれは深読みし過ぎ
回答と質問の区別がついてないだけかと
>>499 質問を読んですらない人が口を挟むのはちょっと勘弁
>>501 ?
>>493 > WHERE A.CODE=B.CODE AND B.DATE>=A.DATE AND B.DATE>=(A.DATEの3か月前←計算式が長いので省略です)
503 :
493:2014/01/15(水) 21:22:36.77 ID:???
>>495 お返事遅くなりました.
すいません.SQLはあまり詳しくないもので..
webで調べてたら上記のSQLにたどり着きました.
1つ目のシンプルな方法で十分ですね.無事意図した結果を得ることができました
ありがとうございました.
因みに3か月前は
CONVERT(int, CONVERT(nvarchar(6), DATEADD(month, -%d, CONVERT(datetime, CONVERT(varchar, A.DATE) + '01')), 112))
でやってます.長かったので書きませんでした.
もしもっと簡単な計算方法があれば教えていただければ幸いです.
Nヶ月前を算数的にやるならこんな?
A.DATE - N - (A.DATE % 100 <= N) * 88
0<=N<=12。
ただ、見てのとおり気持ち悪いし、一番いいのはA.DATEをDate型にすることだと思うよ
Oracle10 です
sqlでTというテーブルにある1000個の項目の内
990フィールドの値をそのまま使いたい時、
(残り10個は別テーブルUとJOINしてそっちのテーブルの値を使いたい)
select
T.AA
,T.AB
,〜
,U.ZZ
と1000項目全て書くのと、
select
Y.*
,U.X
,〜
,U.Z
*で全部取って10コだけ別に取るのでは
どちらが良いものなんでしょうか…?
1000ってすごいなぁ。
僕なら単にめんどくさいから後者にする
1000個も書いてるとSQL文の長さ制限に引っかかるんじゃないか
それにSQLのコンパイルも遅そう
てs
質問です。
userlistテーブル
userid |name
1|aaa
2|bbb
titleテーブル
titleid|title
1|ccc
2|ddd
testテーブル
userid |title|test|tst
1| 1| qwe|asd
1| 2| asd|zxc
2| 1| oiu|lkj
上記のテーブルから下記を出力したい
name |title|test|tst
aaa| ccc| qwe|asd
aaa| ddd| asd|zxc
bbb| ccc| oiu|lkj
どのように書けばいいのでしょうか。初歩的な質問で申し訳ございません。よろしくお願いします
書き込みミス
testテーブルのところ
userid |title|test|tst
ではなく
userid |titleid|test|tst
です。よろしくお願いします
製造業〜サービス業〜金融〜通信と色んな分野の業務に携わってきたけど、
一つのテーブルに千個もフィールドがあるなんてちょっと想像がつかない。
なんか特殊な分野なのかなぁ?
現実の世の中の仕組みの投影としてはありえないでしょ?
>>509 初歩的な質問だと自覚してるんだったら、まず、初歩的な勉強をして下さい
513 :
509:2014/01/16(木) 23:17:21.61 ID:???
>>512 joinってやつ使ったら余裕でできたわ
じゃあなw
管理的な意味で普通はテーブル分けるしな
>>511 正規化されてないまま運用され、それが拡張され続けた結果かもしれない。
というか、そうとしか考えなかったけど、実際どうなんだろうね
1テーブルに千個の列とか(笑)
まったくRDBMSを理解してないシロートだな
いやいくらシロートでもちょっとはおかしいと気づくよなぁ?
どんなテーブルか気になるっ
>>516 まさかとは思うがアイテム(商品とか会員とか)の数が数百とかあって、
それを列に当てはめてるとか?
それはともかく、列があまりにも多いとパフォーマンスが極端に下がるよね?
まあ実際に1000カラムのテーブルがあるわけじゃなくて
どんなにカラム数が多くなったとしても*は避けるべきなのか聞きたかったんでしょ
>>519 1000個の項目の内990フィールドの値をそのまま使いたい
残り10個は別テーブルUとJOINしてそっちのテーブルの値を使いたい
って言ってるんだから実際に千個あるんだろ
>>516 いつもの何も回答しないけど、他の人のレスを見て煽れると思ったときだけ煽る人?
DWHを見て「正規化知らねーのかよw」ってのはよくある話。
PHP+mysqliで、csvを読み込ませて中身の値がMySQL側に存在するかを確認したいのですが、
$query = "SELECT * FROM tablename where column 123456;
$result = mysqli_query($link, $query) or die('Error querying database.');
524 :
NAME IS NULL:2014/01/17(金) 08:55:01.17 ID:IZ+FJS2e
済みません、間違えました
PHP+mysqliで、csvを読み込ませて中身の値がMySQL側に存在するかを確認したいのですが、
$query = "SELECT * FROM tablename where column 123456";
$result = mysqli_query($link, $query) or die('Error querying database.');
で、指定のテーブルの特定のカラムのデータを検索して、resultの中身が空かどうか、
つまりMySQLに検索を掛けて、指定の値が存在しなかった場合を判断するにはどうすればいいでしょうか?
値が存在すると、その行のデータを引っ張ってこれるのですが、存在しなかった時の返り値の判定でつまづいています。
525 :
505:2014/01/17(金) 09:36:57.43 ID:???
遅くなりました
>>505です
>>506 そうなんです。そうしたいんですけど基幹なんでちょっとでも
パフォーマンス追求しといたほうがいいのかなあと…
>>515 そうですね。恐らくそういう設計だったんだと思います…
多分大昔コボルあたりのシステムを拡張拡張してきたような匂いがします
>>519 そうなんです。聞きたかったのはまさにこれでした
(実際には500項目中450ちょっとがそのまま出力。5個がjoinって感じ)
で、結果ですけどやっぱり指定して書いたほうが速いですね
面倒くさいなあ…
基幹で500カラムのテーブル作ってパフォーマンスって
まずテーブル設計が正しいのか検討するべきじゃないのかね
つか*使うだけで速さに差が出るとは思えんが
むしろ解析とコンパイル時間は短くなる気がするんだが
結局はフェッチの時間で、それは単純にデータ量に比例してるだけだろ
>>525 なんで面倒くさい?
手打ちするわけじゃあるまいし
500でも1000でも一緒
視認性も悪くなるしそういう意味では面倒くさいな
こんなのにつきあうほうが面倒くさいわ
・MySQL5.6.15 MacOSXサーバ10.7
・説明
SQLの勉強をはじめまして、Macにインストールして、ターミナルでコマンドラインで打ち込んでます。
参考書によっては、テーブル名や列名が日本語になっているものがありますが
ex. 商品 登録日
半角英数字で打ち込みたいと思ってます。
ex. Shohin torokubi
質問ですが、データーはShohinと打ち込むのですが、それが日本語で「商品」であることが、解るように、どこかに入力しておくことはできないでしょうか?
プログラム言語であれば、ソースにコメントをいれられますから、Shohin #"商品"などとアンチョコを加えていけるのですが
ターミナルでコマンドラインを逐一入力して行く中で、同じようなことができるのか
調べてもなかなか難しいです。
別名 エイリアス というものがありますが、私のやりたい事とは違ったようです。
こんなことでつまづいてるのか、と思われるかもしれませんが
どうかご教授おねがいします
MySQLならcreate tableやalter tableでcommentをつけられる
詳しくはマニュアル(
>>2)参照
ディスティンクト オン (なんやら)
と
ディスティンクト なんやら
の違いがよくわかりません
何を聞いているのか
よくわかりません
>>535 エスキューエルがわからない人はむだなレスしなくていいです
ウスラバカは質問しなくていいです
真性はタヒんでください ↑
>>535 分からなかったら恥をしのんで質問してみましょう
初心者だからと言って馬鹿にする人ばっかりじゃないですよ
あなたさえ素直に「自分は馬鹿だ」と認めさえすれば
>>534 distinctはともかくとして、それにonなんて付いたかとおもってググってみたら
ポスグレの独自拡張か
DBMS名も書かないしまともに質問する気はないとみた
自分でググって調べろ
541 :
NAME IS NULL:2014/01/29(水) 22:06:28.81 ID:4wS/0iyz
質問です教えてください
データベース = access
テーブル名 = T_DATA
SQLで取得したい結果は、KEYごとに日数を取得したいのですが
重複する日数はカウントから除外したいです。
どんなSQLを書けばいいですか?
・キーは、日数=5日
・キーは、日数=1日
----------------------------------
キー, 開始日, 終了日
----------------------------------
1, 2014/01/01, 2014/01/01 |→ 日数=1日
1, 2014/01/02, 2014/01/02 |→ 日数=1日
1, 2014/01/02, 2014/01/02 |→ 日数=0日(重複)
1, 2014/01/03, 2014/01/03 |→ 日数=1日
1, 2014/01/04, 2014/01/05 |→ 日数=2日、合計=5日
---
2, 2014/01/01, 2014/01/01 |→ 日数=1日
2, 2014/01/01, 2014/01/01 |→ 日数=0日(重複)、合計=1日
↓これだと重複がカウントされてしまいます。
SELECT
キー
,SUM(DATEDIFF('d', 開始日, 終了日)+1) AS 日数
FROM
T_DATA
GROUP BY
キー
GROUP BY
キー, 開始日, 終了日
開始日、終了日とも一致するものだけ除外するなら簡単だけど
例えば
1, 2014/01/01, 2014/01/05
1, 2014/01/03, 2014/01/07
というデータがあったときはどうしたいんだ?
>>543を7と数えたいなら
カレンダーテーブル(日付を列挙しただけのテーブル)を
別途用意してJOINだな
select A.キー,
count(distinct B.日付)
from T_DATA A,
カレンダーテーブル B
where A.開始日 <= B.日付
and A.終了日 >= B.日付
group by A.キー
;
545 :
NAME IS NULL:2014/01/30(木) 13:33:51.25 ID:e3L2IJPl
返信が遅くなってすみません
>>542 SQLを覚えてから日が浅く、間違ってたようですね。
訂正ありがとうございます。
>>543 1, 2014/01/01, 2014/01/05
1, 2014/01/03, 2014/01/07
キーが同じで開始〜終了間が跨るデータは
存在しませんの大丈夫です。
必ずこんな感じになります。
1, 2014/01/01, 2014/01/05
1, 2014/01/05, 2014/01/05
1, 2014/01/05, 2014/01/08
>>544 やっぱり簡単にはできないんですかね。
SQL実行前にテーブルを作成して終わったら削除する
しかないんですかね。サクっとはできないみたいですね。
初心者には難しいorz
> SQLを覚えてから日が浅く
> 簡単にはできないんですか
> 初心者には難しいorz
役満でもねらってんのかと思った。
カレンダー作るのが考え方からも、SQLの見やすさからも簡単だと思うが。
> 必ずこんな感じになります。
を信用するなら、1行前のレコードとの比較を行えばできるけどサブクエリになるよ
>>541 重複を除去するクエリをつくる
そのクエリももとに、日数を計算するクエリをつくる
そのクエリをもとに、日数をカウントするクエリをつくる
頑張れば1つのSQLで出来なくもないんだけど
合計三つクエリ作れば、一つ一つは簡単にできるだろ
DB
MySQL 5.1
テーブル
date (datetiem) | value(double)
------------------|----------------
2014-02-02 14:28:00 | 20.1
2014-02-02 14:29:00 | 20.1
2014-02-02 14:30:00 | 20.1
時間とデータが格納されたテーブルがあり、1分ごとにデータが追加されます。
ここから最新24時間分のデータを取りだし、1440個の値でグラフを描画しています。
where date > (now() - INTERVAL 24 HOUR)
としています。
毎分データが更新されている間は問題ないのですが、データ更新が止まって
結果が1440個取れない時にグラフ描画が抜けてる分の時間を詰めて書いてしまいます。
グラフを書いているプログラムは手を入れるのが難しいため、SQLでどうにかしたい
と思っています。
取得する時点で、1440固定にして、抜けている間はたとえば99999.99と帰って
くる様なSQLは掛ける物でしょうか?
よろしくお願いします。
>>548 >>8 存在しないデータを生成するのはSQLの正しい使い方じゃない
そもそもプログラムに手を入れれないのに、そのプログラムが発行するSQLは修正できるのか?
グラフ書く前にプログラム1本かまして、抜けてるデータ補完すればいいんじゃね
抜けてる部分は補完して1440にすればいいのか、抜けたまま1440取ればいいのか分からん
たとえば1,2,3,4,5とあって大きい順3つ取ったときに3,4,5になるだろうが1,2,3,NULL,5になったときに2,3,5を取るのか3,NULL,5を取るのか
抜けているところを詰めないグラフの描き方にするほうが簡単だと思うが
Excelで言う散布図
1分ごとにデータが追加するプログラムに手を入れてで何とかするとか
553 :
505:2014/02/02(日) 16:05:23.92 ID:???
描く側で1分以上空いてたら99999.99扱いにする方がいいんでない
554 :
548:2014/02/02(日) 16:58:17.47 ID:???
>>549-553 やっぱりプログラムに手を入れるのが正しいですよね。
SQLとプログラムは切り離したとかでSQLが外部定義
されているため、そこだけでどうにかなればと思ったの
です。
プログラムの修正が出来なかった場合は、毎日日替わり前に
翌日の1440個分のレコードを追加するバッチ処理を走らせて
外部定義のSQLはINSERT〜ON DUPLICATE UPDATEで
逃げることも検討します。
ありがとうございました。
555 :
NAME IS NULL:2014/02/06(木) 18:43:16.33 ID:TQ+RMbfO
556 :
NAME IS NULL:2014/02/07(金) 17:43:12.64 ID:6HCqv+Ve
SQLという高レベル言語を使うことで生産性を高めたはずなのに
実際にパフォーマンスを出すためには低レベルの内部実装を知らなければならず
不必要に抽象化されているために逆に生産性が落ちるという矛盾
どうやってこの矛盾を解決したらいいでしょうか?
この世から解脱すれば良い
プログラマーを辞めれば解決
>>556 > 不必要に抽象化されているために逆に生産性が落ちる
ここを解決する。というか、大抵の人はそうならないから、解決するまでもなく矛盾が発生していない
>>556 Oracleなんて化石DBを使うからいけない
>>556 まさかとは思いますが、この「抽象化」とは、あなたの想像上の存在にすぎないのではないでしょうか。
563 :
NAME IS NULL:2014/02/10(月) 18:06:21.15 ID:OQp1mlVB
>>556 元々、無謀なほど冗長な実装をされているDBだからだと思う。
SQLの問題ではない。
565 :
NAME IS NULL:2014/02/13(木) 09:43:09.66 ID:jLeG5sV2
今日、生まれて初めてUNIONを使った
感激したよ!
mysql 5.5.19
update教えてください^^;
stock_masterのcomment_textカラム(varchar(50))に
株式分割割当日 yyyy/mm/dd
の形式で入っているものを
権利付最終日 yyyy/mm/dd
に訂正したいと思い
update stock_master
set comment_text = "権利付最終日%"
where comment_text like "株式分割割当日%";
としたら
権利付最終日%
になってしまいました
これ、"株式分割割当日"だけを訂正したいのですが。
適当に書いたけど、使うのはREPLACEじゃね
UPDATE stock_master
SET REPLACE (stock_master,"株式分割割当日","権利付最終日")
>>566 文章が超絶に読みにくいな…ソースも汚そう
>>567 ありがとうです〜 replace初めて知りました
update stock_master
set comment_text = replace(comment_text,"株式分割割当日","権利付最終日");
で修正出来ました。
ブログで、とある記事を読んだ人が他に読んでいることが多い記事をレコメンドしたいのですが、
どうすればいいのでしょうか。
あるセッションのユーザーが読んだ記事の主キーを記録。
ユーザーAが記事1,3,4,5を読む。
ユーザーBが記事2,4,5を読む。
ユーザーCが記事1,4,5を読む。
これをこんな風に1レコードずつ記録していって
記事1→記事3
記事1→記事4
記事3→記事5
記事3→記事4
記事3→記事5
記事4→記事5
としたらよく共に読まれている記事が、評価するのは相対値でもいいですし絶対値でもいいんですが、
決められると思います。
問題は
・煩雑過ぎる
・レコードがあっという間にたまる
ということです。
何か他に良いテーブル設計はないのでしょうか?
セッション毎に貯めておいて、一気に一連の閲覧履歴を書き込んだら?
>>570 どんな規模のサイトか知らないけど、記事を読むたびにリアルタイムでDBに記録しようとしたら
相当重くなるんじゃないかな。
そういう何かをカウンして表示するみたいなのってリアルタイムで処理する必要性はほとんど無い。
だからまずはテキストデータか何かに保存しておいて、10分に1回とか決めて
>>571が書いてあるように
一気に閲覧履歴を書き込んでいけば良いと思う。
あと閲覧記録が溜まりすぎるのを防ぐため、今度は1日1回くらいの感覚で古いのを削除していくとか、
データをまとめていくとかしていけば良いと思う。
>>572 (人間が)ブログを読む程度の頻度のDB更新が重いわけないじゃんw
574 :
NAME IS NULL:2014/02/14(金) 14:48:05.80 ID:HP3AcTSH
>>572 WordpressのWhere did they go from hereっていうプラグインが同じようなことしてるから参考にしてみれば
ただしこれはオススメ表示じゃなくて管理人が参考にするためのデータ取りプラグインな
>>570 思いつきで書くけど
記事が読まれる都度、アクセス元IPと記事番号、タイムスタンプをアクセスログに記録
レコメンドは、当該記事番号に一致し、今回のアクセス元に一致しないIPをアクセスログから取得し
アクセスログから、取得したIPリストで絞込み、記事番号とアクセス数上位N番までを表示する
アクセスログは適当なタイミングで古いものを消去
とか
576 :
570:2014/02/16(日) 20:10:14.60 ID:???
皆さんありがとうございました。
定期処理バッチみたいなものを作ることを視野に入れてみます。
こんなSQLがあります。
select id, name, utime
from something
order by utime desc;
このとき、idが、ある指定された値までは読み飛ばし、それ以降のレコードを取得するにはどうしたらいいですか。
ポイントは、
* id順とutime順とで順番が異なること
* ソートキーは utime だが、読み飛ばす条件は id を使っていること
whileループなら簡単な処理ですが、SQLだとどうするのでしょうか。
(使用DB: PostgreSQL 9.3)
select s.id, s.name, s.utime
from something as s
where s.id > XXX
order by s.utime desc;
>>578 それ以降のレコードに、指定したidより小さい値があったら表示されないんじゃ?
>>579 はい、そうなんです。だから困ってるんです。
where句の中で変数を設定できるといいんですが。
select id, name, utime
from something
where utime < (select utime from something where id = XXX)
order by utime desc;
>>580 where s.id > 指定した値
order by s.id, s.utime desc;
idはint、utimeはtimeでいいんよな?
>>581 これって、速度的には大丈夫なんでしょうか。
副問い合わせが何回も実行されてしまいそうですが。
あと、utime が同じレコードがあると使えないような。
>>582 ソートキーは utime です。idは使わない。
>>577 同じ時刻があるとおかしくなるけど、これが一番近い結果が得られるかな?
utime にINDEXを貼れば実用的な速度で動くはず。
SELECT id,name,utime FROM something WHERE utime>=(SELECT utime FROM something WHERE id=2) ORDER BY utime DESC;
>>584 まず、元のやりたいことの説明が下手すぎる。
> 副問い合わせが何回も実行されてしまいそうですが。
ない。不安なら計画見れば。
> あと、utime が同じレコードがあると使えないような。
whileループならできるんでしょ。それならできる。
なんでもかんでもSQLでやることないだろ
AP側でやれば何にも問題ない
>>587 1億件あって、対象のidが99999990件目にあるとしても同じようにAPでやればいいというのだろうか。
>>588 極端なやっちゃなぁ
なんでもかんでもAP側でやれ、とも言ってないだろ
>>589 全部でレコードが1億件あったとしても、
抽出したレコードに対して何らかの処理をAP側でやるわけだろ?
その(抽出した)レコードが10件とは限らん。
結果として99999990件抽出されて、捨てられる側が10件になるかも知れんし
まぁ、読み直したが、別に上で例が示してあるように、
副問い合わせでidで絞り込んで、utimeでソートするだけのこと
何にも特別な処理じゃないだろ
>>588 いいんじゃね?
一億件ぐらいなら、当然 b-tree なりのアルゴリズム使うだろうしり。
まさか、線形サーチしか知らんと言うオチなの?
使うだろうしり?
お前らってアルゴリズムとか楽しくてやってるの?
それとも仕事だから嫌々?
仕事であればできあいのライブラリを選ぶわ
596 :
NAME IS NULL:2014/02/22(土) 17:38:06.49 ID:wcM5HXSQ
>>588 人の揚げ足取りばっかやって楽しいか、この糞野郎
>>592 対象のIDではソートされてないんだよ。
まぁ別途ツリー作ればいいだけだけど
ウワァ。
>>589 どういう基準でAPでやれといっているのかわからんが、この場合はクエリでやるべきでしょ。
質問者の理解度ならそういう、APでやったほうが速いみたいな考えにもなるのかもしれんが。
>>590 君はwhere句を使わない主義なのか?富豪的プログラミングの極地にいるのか?
捨てられる側が何件かによらず、行える絞込みは行っておくべきだろう。
>>591 うん。それだけの話。
>>581をかいたら
>>584をいただいた。
>>592 さすがにそのオチはないけれど、通常b-treeインデックスを作成してDBMSにやらせるよね。
質問者の理解度ならインデックス相当のツリーをAPで抽出のたびに構築するようなことを考えるのかもしれんが。
こういうSQLがあって、
select groups.name as "group", members.name as "member"
from groups
join members on groups.id = members.group_id
order by groups.id, members.id;
実行結果はこうなっています。
group | member
--------------------+-----------------
麦わら | ルフィ
麦わら | ナミ
麦わら | チョッパー
木ノ葉隠れの里 | ナルト
木ノ葉隠れの里 | カカシ
ここで、memberに対してグループごとの連番をつけるにはどうしたらいいですか。
希望する出力結果はつぎのとおり
group | num | member
--------------------+-----+--------------
麦わら | 1 | ルフィ
麦わら | 2 | ナミ
麦わら | 3 | チョッパー
木ノ葉隠れの里 | 1 | ナルト
木ノ葉隠れの里 | 2 | カカシ
なおPostgres 9.2です。よろしくお願いします。
>>599 自己レス。
Postgresでは「row_number()」という関数でできるそうです。
select groups.name as "group"
, row_number() over (partition by groups.id order by members.id)
, members.name as "member"
from groups
join members on groups.id = members.group_id
order by groups.id, members.id;
>>598 おまえなに偉そうに上から目線で評論家か採点者みたいに
いちいち1つずつをまとめてレスしてんだ?
お前が一番うっぜーやつだな
>577
select id, name, utime from
(select * from something where id>指定値) t
order by utime desc;
じゃないのか?
だから、こんな別になんでもないSQLになんで大騒ぎしてるんだ?
>>603 いまさらで、さらに全く違う結果吐くクエリ書いて何がしたいの?
>>577 idとutimeがユニークなのかどうか示されてないから考える気にもならん
idって列に対してある条件で読み飛ばした結果に対してutimeって列でソートするだけなのに、こんな質問してるってことは前提条件がそもそも何かおかしいんだろ?
エスパーの俺が想像するに
>>609 >>605じゃないが例を書こう。
ID name utime
10 太郎 2014/02/23 14:00:00
20 二郎 2014/02/23 15:00:00
30 三郎 2014/02/23 16:00:00
15 花子 2014/02/23 17:00:00
例えばID20以降に登録されたレコードが欲しい時、ID15も欲しい対象となる(
>>580参照)から、
>>603のSQLは意図しているものとは全く違う結果となる。
つかそれって()で括らなくても普通にwhereで書いてるのと同じじゃね?
>>610 そんなの、id がユニークじゃなかったら破綻するじゃん。
そもそもだけど、なんらかの条件で id が割り当てられてるんだろ?
その条件のときの utime を素直に記録しておくべき。
前提となるシステムの考え方がクズすぎる。
SQLを解くパズルだったら別だけど
613 :
NAME IS NULL:2014/02/25(火) 16:53:43.94 ID:aF4ND4bJ
ユニークにしないシステムがあるのか?
メンテが大変そうだな
>>612 著しく本題から外れたレスをするのもエスパーならではなのかい?
616 :
NAME IS NULL:2014/02/25(火) 17:25:45.69 ID:aF4ND4bJ
普通はidはユニーク、nameはユニークではない
になるんじゃ?
PostgreSQLでidにserialを使わない奴は変態
IDの意味を考えたらユニークにするわな、普通
おいおい、いつからSQLの列名は"意味"まで定まるようになったんだよ?
何らかのアイテムそれぞれに割り振る用途の「ID」といえば一般に「Identifier」の略。
ユニークじゃなかったら identify できない。
SQL関係ない。言葉そのものの意味の話。
ほう、文学青年()がいるな
だが、技術者としては失格だな
id だから UNIQUE って、もうメチャクチャやなw
あんたら、たとえばサイトにログインする時、
ID と パスワード 入力するやろ?
その ID って UNIQUE と思ってんのか?
常識の通じない技術者って困るよな
普通はIDはユニークだよ。むしろユニークでない例を挙げてみたらいい。
小中学校とかの出席番号はクラス内だけではユニークかもしれないけど、
学年・学校とおしてはユニークではないね
UNIQUE ( 年次, クラス, 出席番号 )
とかしないとね
>>625 IDに相当するのは学生番号とかじゃないの?
出席番号だと進級したら変わってしまいそう。
おまえら名前や見た目で人を判断しちゃいけないって言われてきたろ?
>>622 そっか、じゃあ僕がパスワードを間違えたらたまたま他のユーザでログインできちゃうかもしれないのか。
お前らいつまでIDがどうとか見当違いな話してんの?
次の質問が来るまで
まぁ、暇つぶしみたいなもんかな
分かっててやりあってるだろ、おまえらwww
妙にかみつき気味の人はたぶん本気でわかってないと思う。
もう終わってる話なのにね
id がユニークでなかったら破綻するじゃん、とどや顔で書いたから引っ込みつかなくなってるだけだろ (w
早速おでましです (w
idは非ユニークだろうと予想してるのはたぶん一人
後学のためにも、idを非ユニークとして使うシステムにどういうものがあるか知りたい
マジレスしてやろう。
ユーザーとかそういうのを認識するのには確かにユニークなIDが必要。
けど一つ一つのテーブルにユニークなIDが必要なわけではない。
例えばアクセスログを溜め込むテーブルとか。
>>577のも多分そういうのだろ。
で、なんでシステムの話してんの?
639 :
「ガスライティング 集団ストーカー カルト」で検索を!:2014/02/27(木) 01:31:37.85 ID:nmwQAF0x
★マインドコントロールの手法★
・沢山の人が偏った意見を一貫して支持する
偏った意見でも、集団の中でその意見が信じられていれば、自分の考え方は間違っているのか、等と思わせる手法
・不利な質問をさせなくしたり、不利な質問には答えない、スルーする
誰にも質問や反論をさせないことにより、誰もが皆、疑いなど無いんだと信じ込ませる手法
↑マスコミや、カルトのネット工作員がやっていること
TVなどが、偏った思想や考え方に染まっているフリや常識が通じないフリをする人間をよく出演させるのは、
カルトよりキチガイに見える人たちを作ることで批判の矛先をカルトから逸らすことが目的。
リアルでもネットでも、偽装左翼は自分たちの主張に理がないことをわかっているのでまともに議論をしようとしないのが特徴。
,,...
>>607 ちょっと違う
順不同なidをソートされたものとして考えてる質問者に対して
できねーよタコと答えない全員がおかしい
>>638 Id が非ユニークなものの話してるのに、Id 無しのテーブル持ってきてどや顔でマジレスしてやろうとか、うけるわ〜
>>640 > 順不同なidをソートされたものとして考えてる質問者
ダウト
>>638 そういうのじゃない。
>>577のテーブルにおいてidがユニークであることはある程度容易に想像できる。
>>577だけじゃわからなかったとしても、その後の流れで気づけそうなもんだけど。
ユニークじゃないケースも容易に想像できるぜ。idとutimeの複合キーとか。
ユニークである必要なんて元々ない話でしょ。
お騒がせしてます。
元々の質問者の
>>577 です。
質問中の ID はUNIQUEではありません m(_ _)m
MySQL 5.5.28を使用しています。
テーブルAとBを対象として
以下の出力結果を取得したいと考えているのですが、
どのようなSQL文を記述すればよいでしょうか?
どなたかお知恵を拝借させてください。
1.テーブルAの「item_cd」と「use_date」を抽出。
2.テーブルBから、以下の条件で「status」を抽出。
“「item_cd」が一致”
“「use_date」を起点とした直近の「chg_date」”
※条件に該当するレコードがない場合はNULL。
3.1〜2により、テーブルAの各レコードについて
「item_cd」の「use_date」時点における「status」を出力。
【テーブルA】(キー:id)
------------------------------------------
id item_cd use_date
------------------------------------------
1 111 2012-04-01
2 111 2013-04-01
3 111 2014-04-01
4 222 2014-04-01
5 333 2014-04-01
【テーブルB】(キー:item_cd + chg_date)
------------------------------------------
item_cd status chg_date
------------------------------------------
111 11 2013-01-01
111 12 2014-01-01
222 21 2012-01-01
【出力結果】
------------------------------------------
id item_cd use_date status chg_date
------------------------------------------
1 111 2012-04-01 NULL NULL
2 111 2013-04-01 11 2013-01-01
3 111 2014-04-01 12 2014-01-01
4 222 2014-04-01 21 2012-01-01
5 333 2014-04-01 NULL NULL
以上です。
よろしくお願いします。
>>647 本人か?
本人なら、複数あった場合にどの Id (普通は最初か最後だろうが) まで読み飛ばしたいか書かないと答えは出ないぞ。
>>645 Id が無いテーブルの話してるのは君だけ
誰でも知ってるようなことなので、いちいち書かなくてもいいよ
>>648 >「item_cd」の「use_date」時点における「status」を出力。
(2で該当した)chg_date時点、じゃないのか?
(chg_dateが)use_date時点で、ってなら
出力結果の4行目は
4 222 2014-04-01 NULL 2012-01-01
じゃないとおかしいぞ
とりあえず動くかどうか知らんが、こんなクエリ書いてみた
select
x.id,
x.item_cd,
x.use_date,
y.status,
x.chg_date
from
(select
id,
item_cd,
use_date,
(select max(chg_date) from テーブルB where item_cd=a.item_cd and chg_date<=a.use_date) as chg_date
from テーブルA a ) x
join
テーブルB y
on x.item_cd=y.item_cd and x.chg_date=y.chg_date
もうちょっと綺麗に書ける気がするけど、まあしらん
あ、inner joinじゃだめだな
left outer joinにしといてくれ
>>651 >(2で該当した)chg_date時点、じゃないのか?
ご指摘のとおり、
3.1〜2により、テーブルAの各レコードについて
「item_cd」の(2で該当した)「chg_date」時点における「status」を出力。
と書くのが適切でした。
出力結果もばっちりで、SQL文も理解できそうです。
ありがとうございました。
・DBMS名とバージョン
MySQL 5.5.27
・テーブルデータ
現在のところ無し
・・欲しい結果
ブログのシステムに酷似しているシステムを構築しようとしています。記事の検索システムも実装しようかと考えております。
全てのページはPHPページで,、処理の分岐などもPHPによって行うつもりです。
・質問
データベースにテキストとhtmlタグを保存しようと考えているのですが、この場合、
もし自分がこの先MySQLを用いた検索機能を実装して検索の時に、
中のhtmlタグをも検索対象にしてしまうのではないかと危惧しているのですが、どうでしょうか?
自分の考えたこの問題の解決する方法では、
検索したくない特定のhtmlタグをあらかじめ指定しておき、検索結果から弾くなどの方法を考えていますが、この方法は可能でしょうか?そして合理的でしょうか?
何かこの件に関して知っている事がある人に何かしらご教授頂けたら幸いです。
宜しくお願い致します。
>>データベースにテキストとhtmlタグを保存
って1フィールドに生のhtmlぶち込むって話?
それとも本当にタグだけ分けてんの?
>>655 >>>>データベースにテキストとhtmlタグを保存
>>って1フィールドに生のhtmlぶち込むって話?
はい、その通りです。ですが、あくまで記事の本文のみです。
日付やタイトルの部分にはデータベースから該当するデータを読み込んで、
それらのデータを、htmlタグの書かれたテンプレート(PHPページ)の各部位、に読み込んで表示させる予定です。
ただ記事本文には途中で画像を入れたり、特定の文字列をハイパーリンク化したりしたいので、
やはりデータベースにテキストとhtmlごと入れざるを得ないのかな、と考えています。
>>656 検索用にタグを取り除いたものを用意するとか。スレ違いだけど。
>>657 なるほど。それも選択肢の一つとして持っておきたいと思います。
どうやら聞くスレを間違えてしまったようなので、別のスレで聞いてみようかと思います。
有難うございました。
659 :
NAME IS NULL:2014/02/28(金) 07:31:36.68 ID:7u/9HN+D
すいません、少々お聞きしたいのですが、
テーブル X(更新用の情報)
ABCD
テーブルY (更新対象のテーブル)
ABCDEFG.....
上記のようにテーブルがあった場合、XのA列とYのA列、XのB列とYのB列を紐付けて、
YのC列、D列の値をXのC列、D列の値へ変更したいのですが、どのようなSQLを組めばよいのでしょうか。
660 :
NAME IS NULL:2014/02/28(金) 07:35:50.68 ID:7u/9HN+D
Update Y y
SET
y.C = (
select C from X x
where
y.A = x.A
and
y.B = x.B
),
y.D = (
select D from X x
where
y.A = x.A
and
y.B = x.B
),
想定としてはこんな感じで考えてはいるのですが、これだとうまくいかない気がするため、
ご指摘をお願い致します
どのDBなのかも書かず、オマケに「いかない気がする」ってw
662 :
NAME IS NULL:2014/02/28(金) 08:41:20.19 ID:7u/9HN+D
失礼しました。
oracleです。
まだ実際に動かしてみることが出来ないので、
想定で必要なSQLを組んでいる状況です。
666 :
NY:2014/03/09(日) 01:20:10.31 ID:TmYJmE4Z
select id from table1 where .... ;
というselect文では複数のidが返ってきますが、これを「,」で連結して、1つの文字列として取得することは可能でしょうか。
JavaScript でいうところの ['1', '2', '3'].join(',') というイメージです。
DBはPostgreSQL 9.2です。よろしくお願いします。
うん。array_to_stringね。
横からそれるけど、そういう関数がなければストアドファンクションで連結って事になるんだろうか?
うちはいつもアプリでがんばってた。
縦持ちしてる複数のフラグを横並びチェックボックスにするとか、そういう状況のときに。
再帰SQLで無理やり書いたことあるな
単に縦横変換するだけならそういう命令があるDBMSもあるけど
文字列にして連結とか普通はアプリでやるんじゃね
アプリの表示の問題以外で連結する理由がみつからんし
上位2件を連結するのなら前に作った
limit 外せばそのまま全件になると思う
>>322
なんかその辺見覚えある流れだなぁと思ったら
>>332 が俺だった。
テーブルにある全ての行数を取得したいんだけど
COUNT(テーブル名);はできないよね
たぶん以下のどちらかだと思うんだけど(1)の方がよいよね?
(1). COUNT(主キー) FROM テーブル名;
(2). COUNT(*) FROM テーブル名;
677 :
>>675:2014/03/14(金) 20:10:43.75 ID:???
データベースの種類はHSQL ver2.3 です。
外部結合すると主キー項目でもNULLで戻ってくる気が
最適化考えてもCOUNT(*)の方が良いような
外部結合するなんて
>>675のどこにも書いていない
ね。
エスパー様かもしれないよ。
中身は問わず純粋にレコード数を知りたいなら、SELECT COUNT(1) でいいと思うけど。
>>681-682 そのへんはほとんど過去のバッドノウハウだと思うが
気になるならまずは実行計画確認しろと
オプティマイザ信じてやれよ
テンプレ
>>4を下記のようにした場合、
IDごとの最新日付レコードではなく、全IDのうち最新日付を持つレコード1つが
抽出されるのは何故でしょうか?
SELECT Sheet1.ID, Sheet1.ストック, Sheet1.調査日
FROM Sheet1
WHERE (((Sheet1.調査日)=(select max(Sheet1.調査日)from Sheet1 )))
GROUP BY Sheet1.ID, Sheet1.ストック, Sheet1.調査日;
そこから GROUP BY 外して結果見てごらん
その結果を GROUP にまとめてるわけ。
テーブルPersonが参照している複数のPersonを取得したいのですが助言ください。
「テーブル」
Person { id, name }
Friend { from, to } // from, to ともにPerson.id
「データ表」
id | name |
--+-----+--
1, "A"
2, "B"
3, "C"
4, "D"
5, "E"
from | to |
----+---+--
1, 3
1, 4
1, 5
2, 4
3, 1
4, 1
4, 2
5, 1
[クエリ結果]
1, 3, "C"
1, 4, "D"
1, 5, "E"
2, 4, "D"
3, 1, "A"
4, 1, "A"
4, 2, "B"
5, 1, "A"
SQL SELECT p1.id, p2.* FROM Person p1, Friend , Person p2 WHERE p1.id = Friend.from and Friend.to = p2.id;
途中でポストしちゃったんじゃないのか、、、w
同じテーブルを複数回参照するのは JOIN して別名付けるんだけど
そういう話、なのかな?
689 :
687:2014/03/19(水) 12:42:50.14 ID:???
SQLは大体こんな感じかなと適当に書いたのですが、
まず大筋の流れとして正しいのかな。
とりあえず目的としては、Javaでこんな感じのクラスにマッピングしたいのですよ。
class Person {
List<Person> friends;
}
PersonとFriendをLEFT JOINじゃダメなん?
691 :
687:2014/03/19(水) 13:07:05.77 ID:???
WHEREをJOIN ONに置き換えられますね。
それよりもまず上記に書いた[クエリ結果] (予定)が出るのか心配です。
SELECT friend.from, friend.to, person_1.name
FROM (Person INNER JOIN friend ON Person.id = friend.from)
INNER JOIN person AS person_1 ON friend.to = person_1.id
accessで適当につなげただけだが
>>691 ああ、あのような結果が、そのクエリで得られるのかどうかってこと?
ならおk。
あんまりテーブル並べて書くこと無いんだけど
これって、「Person 1さんの友人一覧だけ表示」って時
いちいちwhに2つ条件書かないといけないん?
695 :
687:2014/03/19(水) 13:47:38.81 ID:???
このケースならもっと簡単に出てくることに気づきました。。。
SELECT f.from, p.* FROM Person p INNER JOIN Friend f ON p.id = f.to;
>>695 まぁ基本的にはそれで後はwhereで絞り込むのが一般的だろうな
さらに【○○さんの友人は】って言うのまで出すなら
>>692
つか、from to なのに最初と最後だけとかで良いのかよ
まあ複数必要ならfrom toでもつ設計がどうって話もあるけど
なんだって?
699 :
687:2014/03/19(水) 16:24:59.00 ID:???
友達の友達、友達の友達の友達...は毎回クエリやるしかないよね
無限ループしそうだし
元カノの元カレの元カノの元カレの元カレの元カノの…的な
ウホ、いいリレーショナル
>>699 再帰SQLが使えるDBMSなら1回で出来なくはない
>>702 部品みたいに親子が決まってる奴はいいけど、友達関係だと辿ってると無限ループに陥りそう。
定番の回避方法とかあるんだろうか...
まあ、だいたいは何層までって限定いれるんじゃね
実際にユニークだったとしても、数万の友達リレーとか必要な場面ないだろ
2層とか3層ぐらいなら別名で普通にSQL書く方が楽かもしれんがw
>>703 そのやり方だと同じ友達が無限に出てくることになるね。
だから、そうしない。
調べ済み友達リストを作業テーブルに吐いていって
2度目は弾く、くらいか
友達の友達はアルカイダ
708 :
NAME IS NULL:2014/03/20(木) 14:13:24.98 ID:SUsezco5
SNSでよくある、特定の人の日記を開いたとき、
友達の、その友達の、みたいな繋がり表示かな?
709 :
NAME IS NULL:2014/03/21(金) 15:14:41.41 ID:HdJsM8El
友人としての距離(何人ジャンプするか)を数値化できるといいね!
ちゃんとやれば無限ループになんてならないってだけじゃね
だからそのちゃんとやる方法の定番ってなによって話なんだが...
713 :
NAME IS NULL:2014/03/22(土) 03:00:40.98 ID:9SJ3/olA
ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。
ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。
ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。
ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。
ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。
ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。ひんがら目気色悪すぎこっち見んな死ね。
>>712 定番が何かわからんが、状態が飽和したら終わりでいいじゃん。
とりあえずアプリでやれば?
>>714 申し訳ないけど、スレの流れを読めない奴には用はないわ
> 再帰 SQL
>>715 状態が飽和したことを再帰で記述できないならそういえよ馬鹿。
別にアプリでもクエリでも再帰を使うならやることは同じじゃない?
>>715は再帰自体に慣れてないだけかもしれない。ということは無限ループを生みやすい人かも。
>>718 どこがわからないか書けないってこと?
条件なら、新しい友達がそれ以上存在しなくなったときに偽になればいいわけだから、
exists 既存 except 新規 ってするだけだよね。
オゥ逆だ。新規(既存込み) except 既存 ね。
>>719 ダメだこりゃ
新規とかどっから出てきたんだよ (w
>>721 そりゃ友達の友達を発見しないといけないからな。
再帰って知ってる?
できるもんなの?
>>722 ちょっと意味わからんから SQL で書いてくれない?
ゴタクはいい。クエリを書け。
再帰SQLでUNION ALLでなくUNIONで結合してしまえば簡単じゃね?
再帰と言うからにはファンクション作るのかな?
idを渡してFriendテーブルからfrom=idのto一覧を取得
to一覧を一時テーブルに登録
to一覧の各要素をキーにしてファンクションを呼び出す(再帰)
取得したtoに一時テーブルにない新規を見つける
なければ終わり
あれば、一時テーブルに登録し、ファンクションを呼び出す(再帰)
ファンクションから呼出元に、一時テーブルを返す
こんな感じ?
SQLの文法の話じゃなくてもいいですか?
自分なりググって説明を読んだつもりなんですが、
ハッシュ結合がネステッドループやソートマージより優秀な(事が多い)
理屈がよくわかりません。
なぜハッシュ値にするとソートやループをしなくてよくなるのでしょうか?
ハッシュ値のメッセージが異なればハッシュ値が同じになる確率は
極めて低いっていう性質は理解しているつもりなんですが。
クエリ書けって言われてるのに方法論書いたりマニュアルのURL出すやつは実は何もわかってないんだろうなぁ。
postgresqlを使うことが前提でいいの?
>>731 マニュアルに答えが出てるレベルの内容だからだろ
>>729の「有向グラフの探索」なんてずばり答えではないか
>>730 それぞれ長所短所があってどんな場合にも優れているっていうものはない
(そんなものがあればそれだけが実装されるはず)
ハッシュジョインはソートはしないまでも「ハッシュテーブルを作る」という
一手間がかかるので他の結合方法より遅い場合もある
>>730 ハッシュ値生成コストとループコスト、またはソート+二分探索のコストの差。
そういうわけで、場合によってはネステッドループのほうが優秀なこともある。
>>731 日本語を読めないorクエリを読めないor応用できないor同じことだと理解できていない
>>732 SQL標準にしたがって実装されていれば別にどれでもいいよ。
>>734 ありがとうございます。
ケースバイケースで優秀な結合方法が変わるというのは分かるんですが、
例えば 売上.顧客ID と 顧客.顧客ID で結合する場合、顧客IDそのままの
テーブルを作るよりハッシュ値のテーブルを作った方が早いというのが
よくわからなくて・・
>>735 すみません。新着みてませんでした。
ハッシュ値を出してしまうとその後が楽になる、つまり、
ハッシュ値同士の探索は生値同士の探索より速くなるという
事だと思うのですが、そこの理屈がわかってないです。
そもそもネステッドループと言っても、インデックススキャンとテーブルスキャンじゃ
天と地だから実行計画を見てみないと一概には言えないが、ハッシュジョインが
選択されるのはたいがいテーブルのほぼ全域を読む必要があって、かつジョインに
使用できる適切なインデックスが見つからない場合じゃないかな。
そういうケースではインデックスページを読む必要がない分ハッシュジョインが速い。
>>737 >>736の例だと、どちらも顧客IDにインデックスをはっておけば、そのインデックスがハッシュと同じように低コストで動作するよ。
ループになるとすれば、インデックス外の項目を使用し、かつ、顧客テーブルのレコード数が十分少ない場合など。
> ハッシュ値同士の探索は生値同士の探索より速くなる
ここに限定するなら、ハッシュ値を求めて、それを元にテーブルを構築するわけだから、
ある値が合った場合に、ハッシュ値を求めればテーブルの該当行を抜いてくるのは容易。
プログラミング言語を勉強したことがあるなら、構造体配列があって、配列インデックスが判明すれば、
構造体を抜いてくるのが容易なのと同じといえばいいか。
743 :
730:2014/03/22(土) 17:49:08.11 ID:???
>>739-742 ありがとうございます。
ハッシュテーブルを作る≒その場限りのインデックスを作る
というイメージですかね?
さらに(まだ
>>742さんのPDFは理解しきれてないですが)、
リニアハッシュという仕組みで 顧客ID ではなく ハッシュ関数h(顧客ID) の
方が早く探索できるという事でしょうか。
>>743 ハッシュテーブルにせずキー値をそのままメモリ上に展開しただけの場合、
そこから特定の値を探すには一々メモリ上のすべてのデータを舐める必要がある。
一方、ハッシュテーブルにしておけば値をハッシュ関数にかけるだけで
ダイレクトにメモリ上の位置を特定できる。
キー値を探索する回数が少なければハッシュテーブルを作る手間の分だけ
ハッシュのほうが不利だが、回数が多ければ多いほどハッシュのほうが有利になる。
745 :
730:2014/03/22(土) 20:29:15.54 ID:???
>>744 >ハッシュテーブルにしておけば値をハッシュ関数にかけるだけで
>ダイレクトにメモリ上の位置を特定できる。
勉強不足でした。
これがキモなんですね。すっきりしました。
IDが出ないので別の方なのか分かりませんがレスくれた
みなさんありがとうございます。
mysql 5.5.15
table testunique
id int primary key,
author varchar(30),
fname varchar(100),
genre int not null,
folder varchar(100)
)
1,'a1','test1',10,'dddddddd',
2,'a1','test1',14,'dddddddd1',
3,'ab','test2',16,'dddddddd',
4,'ac','test3',1,'dddddddd',
5,'ac','test3',4,'dddddddd'
とあると気に author, fname の組み合わせで重複なしを出したい
上記の例で言えば
a1 , test1
ab , test2
ac , test3
の3件を取り出したいのですが…
distinctって複数列に対しては出来ませんよね。どう書けば良いんでしょうか
>>746 group by author, fname
select distinct * from testunique
group by concat(author,'##',fname); <- ## は適当に
748はまずいね
>>746を見て、distinctが複数列に対して使えないはずがないと思ったら
MySQLはだめなんね。しらなかったよ
そうなんだ。不便だな。
といっても、PostgreSQLも昔はdistinctよりもgroup byのほうが速かったりもしたし、実装面倒なんだろうか。
いや、やっぱり普通に出来るんじゃないの。
出来ないことのソースが見つからん。
select distinct author, fname from testunique;
でなにがだめなの。
753 :
746:2014/03/25(火) 07:56:53.14 ID:???
皆さん、夜遅くにつきあっていただきありがとうございました
出来ないって単純に思い込んでいただけなのか、752さんのであっさり出来ました
勿論、747さんのgroup byでも出来ましたが。
時間が経ってしまったけど、687の友達の友達〜
mysqlでやってみた
DROP PROCEDURE friend_level;
DELIMITER //
CREATE PROCEDURE friend_level(IN _d INT)
BEGIN
DECLARE not_found INT DEFAULT 0;
DECLARE _id1 INT;
DECLARE _id2 INT;
DECLARE _path TEXT;
DECLARE _name TEXT;
DECLARE _dist INT;
DECLARE _ext INT;
DECLARE _cnt INT;
DECLARE cur CURSOR FOR
SELECT f.`from`, t.`to`, t.path, p.name FROM Friend AS f
INNER JOIN tmpF AS t ON (f.`to` = t.`from` AND f.`from` <> t.`to` AND t.dist = _d)
INNER JOIN Person AS p ON (p.id = f.`from`)
ORDER BY `from`,`to`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found = 1;
SET _dist = _d + 1;
SET _ext = 0;
OPEN cur;
loop2: LOOP
FETCH cur INTO _id1, _id2, _path, _name;
IF not_found THEN
SET not_found = 0;
CLOSE cur;
LEAVE loop2;
END IF;
SELECT COUNT(*) FROM tmpF WHERE `from`=_id1 AND `to`=_id2 INTO _cnt;
IF _cnt = 0 THEN
SET _ext = 1;
INSERT INTO tmpF VALUES (_id1, _id2, _dist, CONCAT(_name, '->', _path));
END IF;
END LOOP;
IF _ext = 1 THEN
CALL friend_level(_dist);
END IF;
END;
//
DELIMITER ;
DROP TABLE IF EXISTS `Person`;
CREATE TABLE `Person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(4) DEFAULT NULL,
PRIMARY KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `Friend`;
CREATE TABLE `Friend` (
`from` int(11) DEFAULT NULL,
`to` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Person` VALUES (1,'A'),(2,'B'),(3,'C'),(4,'D'),(5,'E'),(6,'F'),(7,'G'),(8,'H'),(9,'I');
INSERT INTO `Friend` VALUES (1,3),(1,4),(1,5),(2,4),(3,1),(4,1),(4,2),(5,1);
/*INSERT INTO `Friend` VALUES (1,2),(2,3),(3,4),(4,5),(5,4),(4,3),(3,2),(2,1);*/
CREATE TEMPORARY TABLE IF NOT EXISTS tmpF (`from` INT, `to` INT, dist INT, path TEXT);
TRUNCATE TABLE tmpF;
INSERT INTO tmpF (`from`,`to`,dist,path) SELECT `from`, `to`, 0, CONCAT(p1.name,'->',p2.name)
FROM Friend INNER JOIN Person p1 ON (p1.id=`from`) INNER JOIN Person p2 ON (p2.id=`to`);
SET max_sp_recursion_depth = 255 ;
CALL friend_level(0);
SELECT `from`,p1.name,`to`,p2.name,dist,path FROM tmpF
INNER JOIN Person p1 ON (p1.id=`from`)
INNER JOIN Person p2 ON (p2.id=`to`)
/* order by `from`,`to` */ ;
長いからまだ読んでないけど、テンポラリ・テーブルに書き込んで
重複無限ループを回避しながら検索?
ほしがってる階層にもよるけど、ストアド作るくらいならアプリで解決したほうが
メンテナンス性が高いことの優位性が勝つような気がするよ。
ループして1行ずつ検査してるあたりが回りくどく見える。
新しい友達の情報をtmpに入れればいいんだから、集合的に扱えると思う。
カーソルのクエリでパスを作成するようにして、where句に not exists (select * from tmp where 〜〜) をつけて、
insert into tmp カーソルのクエリ ってやれば、tmpの更新は完了。
再帰終了条件はinsert件数が0件かどうかで判断すれば、
再帰1回あたりのクエリ発行回数は1度で済むとおもうんだけど、どう。
>>758 コメントありがとう。前半のselectで力尽きてたw
tmpの更新については、ご意見参考にして見直してみます
>>760 うん。
言葉を変えると、「まだ入ってなければ入れ、すでに入ってるなら何もしない」ということをするなら、
まだ入ってないものだけ抜いてくれば無条件で入れられるよねってことです。
mysqlのパフォーマンス特性には明るくないけど、
fetch into 自体のコストも、積み重なると地味に邪魔になることが多いし、
集合を扱うというSQLの強みを最大限活用するとよいはずです。
-- こうやって文章で書いてると、いいからクエリ書いてみろよどうせ書けないんだろって
-- 言われるかと思ったけど、そうでもなくてよかった。
762 :
NAME IS NULL:2014/03/28(金) 00:04:38.09 ID:4fFGVIXN
SQL初心者です
かなり低レベルの質問で申し訳ないのですが
DBにOracleやその他いろいろあると思うのですが何が違うのですか?
ブラウザの違いを聞くのと似ている。
本質的には同じだけど、あちこち違う。
764 :
NAME IS NULL:2014/03/28(金) 01:27:13.90 ID:3SLinpcT
oracleもsqlserverも無料版がでてるし、最初からフリーなのも沢山ある
どれでも良いから自分のPCに入れて触ってみればよろし
初心者な質問ですが、無料でubuntu系の鯖で動いて1000万件のデータを管理できて一番CPU/HDDに負担の少ないDBソフトは何ですか?
やることは基本的な事です。
くだらん事で悩む前にmysqlでもpostgreSQLでも何でもいいから実際に動かして自分の頭で納得したほうがよろし
DBMS は PostgreSQL 9.2 です。
tableA, B , C, ... があります。
それぞれに関連があり、例えば以下のように SQL 文を書いて各テーブルにまたがったデータ抽出を行っています。
select a.ID as id, a.col1 as data1, b.col1 as data2, c.col1 as data3
from tableA a, tableB b, tableC c
where b.ID = a.ID and c.ID = a.ID
ここに tableB と新規の tableZ への関連を追加したいと思います。
ただし tableB には tableZ と関連づけるキーのすべてがあるわけではないので、外部結合としたいと思います。
外部結合でない普通?の書き方はわかるのですが、すでに複数のテーブルが関連づけられている SQL に
新規に外部結合を追加する方法がわかりません。教えていただけないでしょうか。
外部結合に使用したいキーは tableB.ID - tableZ.ID と tableB.ID2 - tableZ.ID2 (仮)です。
当然、以下のように書いてしまうと tableZ に対応するキーのないデータが表示されなくなってしまいます。
select a.ID as id, a.col1 as data1, b.col1 as data2, c.col1 as data3, z.col1 as data4
from tableA a, tableB b, tableC c, tableZ z
where b.ID = a.ID and c.ID = a.ID
and b.ID = z.ID and b.ID2 = z.ID2
SQL は読めはするのですが、複雑な SQL はほとんど書いたことがありません。
上に書いた用語もおかしいところがあるかも知れませんが、ご容赦ください。
よろしくお願いします。
よくわからんが inner/left/right/outer join の話し?
>>769 select a.ID as id,
a.col1 as data1,
b.col1 as data2,
c.col1 as data3,
z.col1 as data4
from tableA a
inner join
tableB b
on a.ID = b.ID
inner join
tableC c
on a.ID = c.ID
left outer join
tableZ z
on b.ID = z.ID
and b.ID2 = z.ID2
>>769 where句は外部結合ではなく検索条件。
外部結合はjoin句。
774 :
769:2014/04/06(日) 00:01:44.92 ID:???
>>770 はい。
ただ、外部結合なのでやっぱり inner join とか使うんだろうな、、、くらいにしか分からなかったのですが。
>>771 すばらしいです。
なるほど。部分的にやるのではなくて全部を from 句で条件付け?するように書くべきだったのですね。
まったく発想が追いついてませんでした。
これでなんとか行けそうです。ありがとうございます。
>>772 そのあたりもよく分かっていませんでした。
773 さんと同じなのですが、どういった違いが結果として出るのでしょうか。
inner joinなら意味的にはともかく、結果に違いは出ないはず
外部結合すると、結合の順序によって結果が不定になったはず
776 :
772:2014/04/06(日) 01:55:14.96 ID:???
>>774 言葉が足りんかった。
>>769の文を見る限り、検索条件と外部結合の意味がよく分かってないのかと思った。
だからそれぞれ正確にはこういう意味っていうことを書きたかった。
あと個人的になんだけど、テーブルの個数が2個程度ならともかくそれ以上の場合は、
外部結合はjoin、検索条件はwhereできっちり分けて書いた方が、SQL文を見直したときに
意図が分かりやすくて良いと思う。
where句で外部結合が書けるのってOracleだけ?
SQL Serverでも昔はできたけどできなくなったし
>>774 > 当然、以下のように書いてしまうと tableZ に対応するキーのないデータが表示されなくなってしまいます。
だから right join の意味調べなよ
ググれば親切に説明してるページいくらでもあるし、ここをちゃんと理解してないと RDB のメリット半減するし
>>778 解決後の上になぜright?
rightってよほど事情がないと気持ち悪くて使わないんだけど
right が気持ち悪いとか...大丈夫?
rightはあまり使ったことがないw
通常はどちらかに統一するな
LEFTだと思うけど
rightで統一されていたらそれはそれで悪意を感じる
right
必要に応じて使い分けるもんだと思うが
結果として left が多いと言うならわかるけど
複雑なSQL書いたら、どうしてもletfとrightが混在することはあるだろ
どっちかに統一する(できる)ならleftに統一する方が俺の好みではあるが
rightに統一する方が好みの人もまあいるかもしれん
なんで統一する話しになってるんだ?
788 :
769:2014/04/06(日) 20:01:10.57 ID:???
>>775 ありがとうございます。
外部結合の場合の順序について気をつけます。
‥‥お勉強します。
>>776 ありがとうございます。
了解です。
そうですね。後から見たときのわかりやすさって大切ですものね。
いや、今回のの改造前の SQL 文を見るとしみじみ思うのです。。
>>778 お勉強します。
789 :
NAME IS NULL:2014/04/06(日) 23:53:38.30 ID:zId7D2Ra
phpMyAdminでテーブルをインポートしようと思ったのですが、
メニューに「インポート」の項目がないのは何故でしょうか?
phpMyAdminのバージョンは2.11.9.5
MySQL クライアントのバージョンは5.0.77
です。
SQLの質問じゃないね
MySQLスレですらスレチギリギリだと思うけど、教えてくれるんじゃない
PHPの質問でしょ、これ。 MySQLのどこがメニューの問題になるんだかw
ツールの問題で
MySQLのツールなんだから、PHPに聞きに行っても困るでしょ
MySQLスレが妥当。
けったいなツール使わんのがいちばん
MySQLならmysqldumpがあるでしょ
phpMyAdmin使う人ってSSL入れているのだろうか
797 :
NAME IS NULL:2014/04/13(日) 13:43:10.49 ID:UmjXMXiN
>>795 mysqldumpは出力だろ。
>>789が言ってるのはインポートでmysqlへの入力だろうが
MySQLにはPostgresのpsqlみたいなツールはないの?
SQLをGUIで扱うメリットが全く理解できんのだが?
あるよ
おいらはそれしか使ってない
>>798 ものによるけど、select の結果が見易いとか、フィールド定義で型をリストから選択できたりとか
黒画面に抵抗がある人もいましてね
GUIって言っても、SQLは自分で書くんだぞ
コマンドプロンプト画面のことなら、プロパティいじれば何色にでもできるだろう
流石にhttp経由でDBの管理はできないわぁ
>>802 Visual Studio とかなら、マウスでちょこちょこやってると create table 文作ってくれたり (SQL 直すと GUI 側も合わせて変わる) 、Access とかは select 文も作ってくれたりするよ
まあ、それが便利かどうかは人によるけど...
>>798 PostgreSQLんもpgAdminIIIがあるじゃない
psqlとpgAdmin併用がいいよ
mysqlはCUIの補完が微妙でGUIあるといいなと思うけど使ってないや
postgresqlはCUIの補完が優秀だからGUI使いたいと思ったことないや
>>806 pgAdminIIIは試しに使ったことはあるけど、何が便利なのか分からん。
psql ではできないことでもあるのかな?
EXPLAINの解析でグラフィカルな図が見られたりするよ
あと現在動作してるバックエンドの一覧とか
管理に使うには便利すぎる
mysqlです
testテーブル
id int(11) PK
col varchar(10)
とあるときに最大のidを得たい
そしてそれが未登録状態なら0を返したいと思って
select case max(id)
when max(id) is null then 0
else max(id)
end as Nid from test;
としたんですが、0件の状態でNULLが返ってきます
これを0にしたいんですがどう訂正すればいいんでしょうか
810 速攻ですいません
select case max(id) の max(id) が余計でした
GUI使わない俺カッケーってだけでしょ?
全部コンソールでやってる人はアホだと思うわ
GUI使わないとカッケーの?
初めて知った
>>812 カッケーじゃなくて、それしか知らないだけかも。
分かってるだろうけど、CUIも便利だよ。
どちらも便利な点があるんだから、適材適所で使えばよいだけ。
CUIで全部作ってる人はGUIではSQLを打つんじゃなくてドラッグアンドドロップでSQLが自動生成されると思ってる人だよ
シェルを使わせない代わりにGUIが使えるというレンタルサーバーはあるな
>>810 select
case when max_id is null then 0 else max_id end as Nid
from
(select max(id) as max_id from test) t
とかでどうだ?
まあ、俺ならそんな操作はホストアプリ側でやらせるがな
SQLは存在しないデータを生み出すためのものじゃないから
idの取りうる範囲次第では0とunionしてmax取るとかでも行けるかも
>>812-817 いい加減スレチな話題はやめろ
>>818 なんで解決してる話題にドヤ顔で回りくどいクエリを?
スレチ指摘するより先にやることがあるだろ。
SQLインジェクション対策したいんですが、
$test = $_GET['data'];
//エスケープ
$test = mysql_real_escape_string($test);
$result = mysql_query("select * from aaa where name = '{$test}'");
このようにmysql_real_escape_stringでエスケープしてれば、SQLインジェクションって防げますよね?
防げない場合どういうパターンがあるのか教えてください
↑は解決したんで無視してください
A,1,3
というデータを持つ3カラム1レコードのテーブルAから
A,1
A,2
A,3
という2カラム複数レコードに展開したテーブルBを作る方法を知りたいです。
元テーブルの第2カラムが連番FROM、第3カラムが連番TOなので
展開後のレコード数はこれらの値により変化します。
DBMSはAccess2010を想定しますが、なるべく汎用的なSQLがよいです。
>>822 Accessなら素直にVBAで回せば簡単で後々も楽ですよ
>>822 Access (のエンジンである Ace) は再帰をサポートしてないようなので、SQL だけでは無理と思う。
Access だけでやりたいなら、
>>824 が言うように VBA でやるのがお勧め。
エンジン替えていいなら無償の SQL-Server 入れて
With T (Value, [From], [To], Offset) as (
select Value, [From], [To], 0 from A
union all
select Value, [From], [To], 2 * Offset + 1 from T where [From] + 2 * Offset + 1 <= [To]
union all
select Value, [From], [To], 2 * Offset + 2 from T where [From] + 2 * Offset + 2 <= [To]
)
select Value, [From] + Offset from T;
でいける。
1,000,000行でも 10秒ちょい。
サンクスです。
連番作成はSQLには向かない仕事だったのですね。
VBAはまだ身についていないのですが参考にします。
827 :
NAME IS NULL:2014/04/17(木) 01:57:59.92 ID:1elrg/bJ
@テーブルデータ
A|B|C
-+-+-
1|3|-
2|-|5
3|-|8
4|2|-
-はnullとします
A期待値
1|3
2|5
3|8
4|2
Bやりたいこと
Aは必ず入っており、BとCは片方のみ入っています。
その場合、AとBCの入っている方を出したいです
Aは昇順ソートもかけたいです
select T1.A, T1.B from aaa T1 where T1.B is not null
select T2.A, T2.C from aaa T2 where T2.C is not null
これで片方ずつは抽出できると思うんですけど
合わせてソートする方法がわかりません
>>827 select
A,
case when B is null then C else B end as DATA
from TABLE
order by A
829 :
NAME IS NULL:2014/04/17(木) 02:20:26.93 ID:1elrg/bJ
>>828 回答ありがとうございます!
・・・しかし理解できていないので
これから読みといてみます
早く終わらせて寝たい・・・
select A, coalesce(B,C) from TABLE:
理解出来ました! CASE文は知りませんでした。
一つ勉強になりました、ありがとうございます!
すいませんsageが抜けてました
おやすみなさい!
>>831 あれーすごく短いコマンドでできているような…
寝ないでも少し調べますっ。回答ありがとうございます!
COALESCEも理解出来ました!
こちらのほうが短くてよさそうですね!
おふたりともありがとうございました!
ねます!おやすみなさい!
ほっこりした
おなじくほっこりした。
select A, B from aaa where B is not null
union all
select A, C from aaa where C is not null
order by A
に到達してもよさそうな状況だったけど、その前にcoalesceに出会えてよかった。
質問1: left outer join や right outer join って、cross joinとwhere句の組み合わせで実現できる?もしできるなら教えて。
質問2: カラム数が可変なクエリって定義できる?やりたいことは、チーム数が可変の対戦表をつくりたい。
チーム1 点数 チーム2 点数
------------------------------------
Japan 1 England 2
Spain 2 Mexico 3
Mexico 0 England 1
↓
England Mexico Spain Japan
England - ○ - ○
Mexico × - ○ -
Spain - × - -
Japan × - - -
「列の数が可変なクエリは書けない」って
>>7に書いてあったorz
>>836 >質問1: left outer join や right outer join って、cross joinとwhere句の組み合わせで実現できる?もしできるなら教えて。
これ教えてください
>>838 unionとnot exists使えばできる。cross joinは使ってもいいがinner joinで十分。
>>839 質問を理解してから回答してください
>>840 ありがとうございます。こんなかんじでしょうか。
(select emp.*, dept.*
from emp, dept
where emp.dept_id = dept.id
)
union
(select emp.*
from emp
where not exists (select * from dept where dept.id = emp.id)
)
これだと、select emp.*, dept.* と select emp.* が違うので、union はできませんね。
2つ目のselect文で、select emp.*, dept.* 相当にするにはどうしたらいいでしょうか。
質問してる立場なのに上から目線でレスするやつの神経がマジ分からない。
そりゃ
>>839があまりにも不親切だからでしょ
ググれで済むなら質問スレなんて要らないんだし
ググるワードまで教えてもらって不親切はないわ
>>1のテンプレすら守れないときついわな
>質問するときはDBMS名を必ず付記してください
841はググったのだろうか
外部結合演算子を勘違いしている可能性が一番高そうなんだな
ム板に多いが、質問者よりバカなくせに上から目線でとんちんかんな回答する奴はイラッとくるな。
今回のはどこに落ち着くかね
DBMS名を書くのと
何故にcorss joinが必要なのかを明記しないと回答はつかないだろうな
外部結合演算子を使うとcross joinとは言えないから難しいところ
>>847 普通にスルーすればよいかと
PostgreSQLスレにも似た口調のダメな質問者が湧いてるな
回答にならないキーワードを教えて回答したつもりになっている、自称上級者が集まっているのがこちらです
>>841 2つめのselectでNULLを補えばいい。
>>838 >質問1: left outer join や right outer join って、cross joinとwhere句の組み合わせで実現できる?もしできるなら教えて。
これがもとの質問。外部結合がクロス結合とWHEREで実現できるかを聞いている。
>> 839
> 外部結合演算子でぐぐれ
的はずれ。外部結合が何かを聞いているんじゃないのに、これで教えた気になっている。
>>840 > unionとnot exists使えばできる。
こっちは質問の答えになっている。
>>841 > 質問を理解してから回答してください
バカを煽るな。バカはスルーするのが一番。
>>848 この質問だとさすがにDBMSによって変わるような内容とは思わないが、
どうしてもDBMSが必要なら、「標準SQLの場合なら」と断って書けばいい。
>>853 848だけどさ
何故にクロスジョインにした結果を知りたいかが不明でさ
SQLの初歩的な理解のためってならわかるけどさ
>>841を見ると、その線が濃厚か
>>839は外部結合演算子を使うと
クロスジョインのjoin句の書式で外部結合書けるからだと思うよ
outer joinをわざわざDBMS方言の外部結合演算子で書き換えることが元質問者の求めている
回答だと思ったんだとしたら、ちょっと頭が足りないんじゃないか?
だろうね
DBMS は PostgreSQL の 9.2 です。
たとえば次のようなテーブルがあったとします。
id col1
---------
1 1
2 1
3 2
4 3
このようなテーブルの、col1 の持っている値の種類と、その種類ごとの出現件数を
1回の SQL 実行で取得することは可能でしょうか。
この場合では、 col1=1 が 2 回、2 と 3 が 1 回ずつなので、これを知りたいと思います。
いまは SQL を思いつかなくて、条件に一致するレコードをすべて取得して for ループで
col1 の値ごとの出現回数を取得してますが、もっと上手な方法がありそうに思えました。
col1でgroup by してcount すれば良いんじゃないの?
ほっこり→イライラ→ほっこり
次の質問はイライラかぁ
これからデータベースの勉強をしようと思っているのですがどのデータベースを主に使えばいいのか悩んでいます
選択候補はSQLserver,oracle,postgreの3つを考えているのですがそれぞれのメリットやどんな企業が導入しやすいとかみたいなものはありますか?
個人的に oracle は最初に候補から脱落させて良いと思う
linux を触る機会が少なければ sqlserver 一択かな
無料版 express でも、個人で使う範囲ならほぼフルスペックだ
以前触った時の感想だけどSQLServerはヘルプが読みやすかった (BooksOnlineだったか)
勿論SQLを勉強した上でないとダメだけど。
postgreは触った事ないから知らない
oracleは、、、資格を取るためとかってならそれもいいんだろうけどなぁ
個人的には861さんの意見に同意
インデックスは 張るものですか? 貼るものですか?
はるものだけど
貼るではないから張るだろうな
>>860 お金をかけたい企業はOracleかSQLServerを使う
お金をかけれない企業はPostgreSQLと(MySQL)を使う
性能はMySQLだけ異質で他はあまり変わらない
すれちとは言わないんだ(笑)
>>865 >性能はMySQLだけ異質で他はあまり変わらない
その異質ってのは何?
868 :
857:2014/04/21(月) 21:41:37.72 ID:???
>>858 それでした。なんでか思いつきませんでした。。
ありがとうございました。
スレが和やかだと読んでて楽しい
870 :
NAME IS NULL:2014/04/24(木) 00:31:34.81 ID:VMhPPiZ3
人物を扱うテーブルがあり、そのテーブルの列には、人物テーブルの主キーを外部キーとして自己参照する列があります。
Persons
id
name
descendant_of
こういう構成になっており、 descendant_ofはPersonsテーブルの主キーが入ります。
id=1にAさんがいます。
id=2にBさんがいて、BさんはAさんの子孫です。
id=3にCさんがいて、CさんはAさんの子孫です。
id=4にDさんがいて、DさんはCさんの子孫です。
この状況で、
http://www.hoge.com/persons?id=*というURLがあり、*に則した人物と、それに関係する人物を「全て」見せたいとします。
つまり、
http://www.hoge.com/persons?id=1にアクセスしてきたときは、Aさんのidをもとに、BさんとCさんとDさんの情報も拾ってくる。
http://www.hoge.com/persons?id=4にアクセスしてきたときは、Dさんのidをもとに、AさんとBさんとCさんの情報も拾ってくる。
そういう場合に書くクエリーは、どうすればいいのでしょうか?
SELECT * FROM persons WHERE id = 引数 OR descendant_of = 引数;
これだとAさんの場合、つまり自分が子孫関係のトップにいる場合にしか使えません。
サーバー側で何度もクエリー発行すれば幾らでも可能だと思います。
SELECT * FROM persons WHERE id = 引数 OR descendant_of = 引数;
まず、このクエリで取得して、次にサーバー側でdescendant_ofの値を見て値が存在すれば、
SELECT * FROM persons WHERE id = descendant_ofの値 OR descendant_of = descendant_ofの値;
というクエリを流します。これを何回も繰り返していけば、やがて全件取得できると思います。
しかし、明らかに効率が悪いと思います・・・。
もっといい方法はないのでしょうか?
873 :
NAME IS NULL:2014/04/24(木) 13:42:56.94 ID:uvJm+LdL
>>870 標準SQLの再帰クエリで簡単に処理できるよ
875 :
870:2014/04/24(木) 20:29:51.40 ID:VMhPPiZ3
大変失礼しました
DBはMySQLでした
再帰クエリは対応してないようです・・・。
>>875 MySQLだと泥臭いことやるのが基本かと
PostgreSQLだと思うけど
insert into 〜〜〜(〜〜) values(int, '〜')みたいなのでデータ追加するとき
intの値の範囲によって分けたいんだがどうしたらいいの
〜〜〜 values (1〜30, '小')
〜〜〜 values (31〜60, '中')
〜〜〜 values (61〜90, '大')
みたいに
878 :
NAME IS NULL:2014/04/25(金) 17:34:52.72 ID:+Fb19Efw
質問です。
MySQL5です。
テーブルデータはDATE(YYYYMMの6けたのint型),CODE(varchar型),VALUE(varchar型) の3カラムからなります。
各日付順の降順にしたいのですが、スレッドのように、同じコードの場合、その下に日付順でソートしたいです。
言っていることが、よくわからなくてすみません。
元テーブル
DATE, CODE, VALUE
....
20140401, 11, A
20140402, 12, B
20140403, 11, C
20140404, 13, D
20140405, 12, E
20140406, 11, F
....
欲しい結果
20140401, 11, A
20140403, 11, C
20140406, 11, F
20140402, 12, B
20140405, 12, E
20140404, 13, D
宜しくお願い致します。
>>877 どうも質問が明確じゃないけど、
insert into tname select 〜
の形式にすればとりあえず解決しそうな話に見える。
>>878 order by code, date ということ?
880 :
NAME IS NULL:2014/04/25(金) 17:47:38.30 ID:+Fb19Efw
879
分かりずらい
欲しい結果にしてしまいました。
第1キーは、日付です。
元テーブル
DATE, CODE, VALUE
20140401, 13, A
20140402, 11, B
20140403, 12, C
20140404, 13, D
20140405, 12, E
20140406, 11, F
欲しい結果
20140401, 13, A
20140404, 13, D
20140402, 11, B
20140406, 11, F
20140403, 12, C
20140405, 12, E
宜しくお願い致します。
>>880 それでもやっぱりよくわからないけど。
select t1.* from tname as t1 join (select min(date), code from tname group by code) as t2 using (code)
order by t2.date, t1.date
とか?
(ずっと昇順だけどそこは気にしてない)
882 :
NAME IS NULL:2014/04/25(金) 18:32:13.82 ID:+Fb19Efw
ありがとうございます。
その通りでした。
>>879 俺も何が何だかなんだすまない
分類(年収 int, 階級 char(20), primary key (年収))
があったとして
年収 〜300万は下流階級 300万〜800万は中流階級 800万〜上流階級
ってのをinsertしたいとしたとき
valuesだと1万刻みでinsertしていかなきゃいけない気がするんだが
それだとキリがないからどうしたものかということなのです
>>883 SELECT "年収",
CASE WHEN "年収" <= 300 THEN '下流階級' WHEN "年収" <= 800 THEN '中流階級' ELSE '上流階級' END "階級"
FROM (SELECT generate_series(1,1000) as "年収") AS sal
>>883 その 階級 とやらはデータベースに入れる必要あるのか?
まあ、あるならご愁傷様でした。
>>886 スレ違い。
あとpostgreSQLにそのバージョンのものはない。
>>883 階級入れないで、あとでUPDATEした方が速そう
890 :
NAME IS NULL:2014/05/02(金) 20:02:09.57 ID:yPuMCXLM
質問させてください。MySQLです。
上位100件を抽出してその中から10件をランダムに抽出したい。
SELECT文はどう書けばいいですか?1行でできますか?
「Mysql」「ランダム」
>>890 select * from (select * from ranking order by rankno limit 100) sa a order by rand()
ミス
select * from (select * from ranking order by rankno limit 100) sa a order by rand() limit 10
saってなんだよ
なんやろな。
select * from (select * from ranking order by rankno limit 100) as a order by rand() limit 10
896 :
NAME IS NULL:2014/05/04(日) 13:27:58.62 ID:DCyCq8w9
質問です。
PostgreSQL9.3
テーブル
DATE, VALUE
20140401,-13
20140402,-11
20140403, 12
20140404, 13
20140405, 12
20140406,-11
欲しい結果
DATE, VALUE ,COUNT
20140401,-13, 1
20140402,-11, 2
20140403, 12, 1
20140404, 13, 2
20140405, 12, 3
20140406,-11, 1
このように、VALUEの値の正負の連続数をCOUNTし出力するようなSQLは書けるのですか?
答えです。
書けます。
898 :
NAME IS NULL:2014/05/04(日) 14:55:09.03 ID:xQR76yAx
横から失礼します。
>>896を実現するクエリを思いつかないので、クエリ内容を教えてください。
できれば
>>897さんにお願いしたいです。
恥ずかしい人だな
>>896 横から失礼するけど
なんでもかんでもSQLでしようとせず受けたプログラム側で処理したら?
ぽすぐれサーバの負荷も考えたほうがいい
横から失礼します。
横入りはお止め下さい、シナ人や朝鮮人じゃあるまいし
どっちが簡単かによる
>>901 プログラム側で処理するにしても、一旦はDBだけで出力する方法を試してみるよ
その上でどっちがベストか考えたらいいし
SQLはDBから受ける結果の絞り込みにだけ要いて、
処理やら加工やらは受けるプログラム側でするのが良策。
基本的にDBサーバは1つ、そこへ集中してアクセスがくるのだから、
負荷とかを考えれば自ずとそうなるだろ。ってかそうしろ。
バカかコイツ
そんなもん状況によるだろうが
>>905 おいおいそんな低レベルな話を人に押し付けるな
DBサーバ1つって
絞り込みにだけって
はい、そーでちゅね
>>905 ありがとうございました。クライアント側のプログラミングも出来ないくらいの低レベルなので、とりあえずSQLだけでなんとか出来ないかな?と思ったものですから。確かに分けて考えるべきなのかもしれません。
>>909 Window関数では無理っぽいな……、と思ったのですが……。
プロシージャとかいうのを使えば実現できますかね?
>>896 こうかな?
select T1."DATE",
T1.VALUE,
COUNT(*)
from TableName T1
inner join
TableName T2
on T1."DATE" >= T2."DATE"
and ((T1.VALUE > 0 and T2.VALUE > 0) or (T1.VALUE < 0 and T2.VALUE < 0))
where not exists (
select *
from TableName T3
where T1."DATE" > T3."DATE"
and T2."DATE" < T3."DATE"
and ((T1.VALUE > 0 and T3.VALUE < 0) or (T1.VALUE < 0 and T3.VALUE > 0))
)
group by T1."DATE", T1.VALUE
order by T1."DATE"
;
912 :
896:2014/05/04(日) 17:29:19.64 ID:???
>>911 おおっ、すごい!!出来ました!!!
どうなっているのかさっぱり解りませんが、じっくりと見て勉強させて戴きます、ありがとうごさいました。
SQLって奥が深いんだなぁ〜〜。
913 :
NAME IS NULL:2014/05/04(日) 20:29:26.57 ID:xQR76yAx
where句が秀逸ですね。ありがとうございます。
>>910 Window関数だけだとダメだった。再帰付き
WITH RECURSIVE R AS (
SELECT
"DATE", "VALUE",
row_number() OVER(ORDER BY "DATE") AS "ROW",
lag("VALUE", 1, 0) OVER (ORDER BY "DATE") * "VALUE" <= 0 AS FIRST
FROM TableName
), S AS (
SELECT
R.*, 1 AS "RANK"
FROM R WHERE FIRST
UNION ALL
SELECT
R.*, S."RANK" + 1 AS "RANK"
FROM S, R WHERE R."ROW" = S."ROW" + 1 AND NOT R.FIRST)
SELECT "DATE", "VALUE", "RANK" FROM S ORDER BY "DATE";
>>896 出力のここの部分がどうして連続数と看做されているのかわからない。単純な間違えかな。
20140401,-13, 1
20140402,-11, 2
>>915 ごめん。意味がわかった。正の集合の連続数。負の集合の連続数ということか。
>>915は取り消し。
>>916 すみません。またまた訂正。正の一つだけを含む連続した組と負の一つだけを含む連続した組にそれぞれ連続数を与える。ですね。
918 :
896:2014/05/05(月) 09:31:00.17 ID:???
>>914 Lag関数を使うと歯抜け日数に対応することが出来ないと思っていたのですが、row_number()関数からの自己結合でうまくいくのですね!!勉強になります。
ただ、Lag関数の3つ目の引数0は何を意味するのですか?PostgreSQL9.3では対応していないようです。
再帰部分が理解不能なので良く見て勉強させて頂きます。
ありがとうございました。
>>918 lagの2個目がステップ、3個目は初期値
PostgreSQLで対応してるよ
920 :
896:2014/05/05(月) 09:47:51.48 ID:???
>>917 はぁ〜〜、なるほど、そういう風に考えるのですか!??
直前の行の自己出力列を比較して連続数として+1するようなイメージだったのですが……
921 :
896:2014/05/05(月) 09:58:47.74 ID:???
>>919 わ、わかりました!?……動きました。
ふぅ〜…、むずかしいな…。
SELECT句の中で比較演算子が使えるのも初めて知りました!!
ありがとうございました。
そのレベルじゃ自分で書けないSQL使っても後で苦労するぞ
と書いてみる
923 :
NAME IS NULL:2014/05/05(月) 15:29:58.19 ID:tGrX0Jlt
質問失礼します。
たとえば文字列(VARCHAR2)で定義された計算式(足し算や掛け算など)から、
計算結果を取得するにはどうすればいいでしょうか?
925 :
NAME IS NULL:2014/05/05(月) 15:37:32.29 ID:tGrX0Jlt
>>924 私sql developerを使用しているのですが
計算式が書いてあるテキストを読み込んで
その読み込んだ式の計算結果を取得したのですがTO_NUMBERでは
演算子があると使えないので悩んでいます。
926 :
NAME IS NULL:2014/05/05(月) 15:39:16.54 ID:tGrX0Jlt
>>925 誤 式の計算結果を取得したのですが
生 式の計算結果を取得したいのですが
eval関数作るしか、、、
一旦アプリ側で読み出して動的SQL組み立てて流せばいいような。
セキュリティは気をつけなきゃだけど。
>>923 アプリ側でeval
DB側でfunction定義してeval
長文失礼postgreSQLです
たとえばですがある大会で1位3P・2位2P・3位1P・4位以下は0Pという風な加点があって
それぞれのチームの競技結果がデータとしてあるとします
というわけでテーブル
・競技結果
順位,チームコード,競技コード
・加点
順位,得点
・チーム
チーム名,チームコード
このとき大会後の各チームの総得点とチーム名を出力させたいわけですが0点のチームがうまく出せません
select チーム名, sum(得点) as 総得点
from (チーム join 競技結果 using (チームコード)) join 加点 using (順位)
where 順位 <= 3
group by チーム名, チームコード
こうすると総得点が0点のチームはチーム名すら出なくなってしまうわけですが上手い方法はありませんか?
超初心者なため色々とツッコミどこがあるかと思いますがなるべく単純にお願いします
>>930 外部結合(OUTER JOIN)使え
SUM(NULL)はNULLだから、NULLを0に置き換えるのも必要かもしれん
select チーム名, coalesce(総得点, 0) as 総得点
from チーム
left join (
select チームコード, sum(得点) as 総得点
from 競技結果
left join 加点 using (順位)
where 順位 <= 3
) 総得点テーブル using (チームコード)
group by チーム名, チームコード
933 :
NAME IS NULL:2014/05/25(日) 17:19:45.43 ID:cvRaurYJ
2chはファイルシステムベースでログを管理しているようだけどデータベースシステムを採用していないのは何故ですか?
管理上RDBMS使った方が良さそうな感じがするのですが
直った?
・DBMS名とバージョン Oracle11gR2
PL/SQLのプログラムを作ってるのですが期待通り動作しておらず、その理由を知りたく思ってます
テーブルA
a1 | a2
---------
100 | 1
100 | 2
200 | 3
というテーブルにて、a1='100'のレコードについては、a2に100を加算、といった処理をしたく思っており、
以下のようなPL/SQLのプログラムを作りました
set serveroutput on
declare
cursor c1 is SELECT A1, A2 FROM A WHERE A1='100';
aa1 number;
aa2 number;
aa3 number;
sql1 varchar2(1000);
begin
open c1;
loop
fetch c1 into aa1, aa2;
exit when c1%NOTFOUND;
aa3:=100;
-- NG
-- sql1:='UPDATE A SET A2=A2+:3 WHERE A1=:1 AND A2=:2';
-- execute immediate sql1 using aa1, aa2, aa3;
-- OK
sql1:='UPDATE A SET A2=A2+100 WHERE A1=:1 AND A2=:2';
execute immediate sql1 using aa1, aa2;
if (SQL%FOUND) then
dbms_output.put_line('updated');
end if;
end loop;
commit;
end;
/
exit
ここでコメントに「OK」と「NG」とありますが、「OK」部のようにSQLに「A2=A2+100」と記述して
execute immediateすると期待通り動作するのですが、「NG」部のように「A2=A2+:3」と
バインド変数を使うと、エラーは出ないけど、何かの処理もされてない、という状態となります
execute immediate後にsqlcodeやsqlerrmを見ても、エラー類も出力されていません
なぜ「NG」部のような書き方だと、うまくいかないのでしょうか?
また、最終的には後者のようなバインド変数を使ったコードにしたく思っているのですが、
バインド変数を使っても前者のように動作させる方法はありますか?
PL/SQLってこのスレの範疇か?
>>935 バインド変数は名前に関係ないから
:3,:1,:2に対してaa1,aa2,aa3の指定だと
:3=aa1
:1=aa2
:2=aa3
って展開されてると思われ
結局whereに一致する条件がないから何も更新されない
つかこれ、この程度でPL/SQL使う必要ないよな。例として上げてるだけ?
>>936 情報ありがとうございました
いただいた情報を基に、バインド変数を並び替えたところ、期待通りの動作をしました
ありがとうございました
なお、PL/SQLのスレが無かったので、SQLでいいのかな?と思って書き込んでしまいました
また、実際には、もうちょっと色々なデータの加工をする処理となっているのですが、
書き込んだコードは事象を端的に示したく思って作った例です
失礼いたしました…
938 :
NAME IS NULL:2014/05/29(木) 22:34:28.70 ID:IEd/ec0c
SQLserverのSQLについて質問させてください。
仕事上困っておりまして、どうしても本日中、又は明日の朝までに
回答が欲しいので、SQLserverのスレにも質問させてもらってます。
派遣なので質問する人がいないので何卒お願い申しあげます。
テーブルBにカラム1に”1”、カラム2に"CODE='12345'"が入っています。
※カラム2は条件式が入ってます
やりたいことは、テーブルAをSELECTしたときにテーブルBをINNER JOINして
テーブルAのカラム1とテーブルBのカラム1が一致した場合
WHERE句の条件にテーブルBのカラム2の文字列条件式を条件として使いたいのですが
うまくいきません。
ご教示ねがえませんでしょうか?
SELECT * FROM テーブルA as A INNER JOIN テーブルB as B
ON A.カラム1=B.カラム1
WHERE
---ここからがわかりません
CASE A.カラム1 WHEN B.カラム1 THEN B.カラム2 END
カラム2に"AND CODE='12345'"を条件に追加したいのですが
どうすればできますでしょうか
発行したいsqlは以下になります
SELECT * FROM テーブルA as A INNER JOIN テーブルB as B
ON A.カラム1=B.カラム1
WHERE
CODE='12345'
テーブルBに入った文字列条件式を
現実の条件にしたいのです。
テーブルA、Bのカラム1同士が一致した場合
困ってます
なにとぞよろしくお願いします
>>938 SELECT 'SELECT * FROM テーブルA as A INNER JOIN テーブルB as B
ON A.カラム1=B.カラム1
WHERE ' + A.カラム2
FROM テーブルA
INNER JOIN テーブルB
ON テーブルA.カラム1=テーブルB.カラム1
WHERE A.カラム1=B.カラム1
みたいにSQLを出力するSQL書いて、その出力をT-SQLに食わせりゃいいんじゃね?
940 :
NAME IS NULL:2014/05/29(木) 23:25:54.07 ID:IEd/ec0c
>>939様
回答ありがとうございます
机上だけではいけるか判断できないので
明日さっそく会社でSQL作ってみます
できるといいのですが・・・
マイナージャンルかもしれないけど質問させてくれ。列指向DBについて。
今まで行指向のDBしか触ったことがなかったんだが、SELECTが早くなるという話を聞いて
なんとなく列指向のDBに手を出してみたんだが、いまいち早くなった気がしない。
というか、INDEXを使わない機構のせいでだいたい列指向のほうが遅いように思える。
行指向の場合はINDEXを使うようにチューンしてやれば早くなる、という常識はあったけど、
列指向の場合は〇〇するようにすれば早くなるよ、というのはあるんだろうか?
曖昧な問いかけで申し訳ない。
SybaseIQとかか?
どっちにしろスレチだと思うが
列指向DBって、従来のRDBMSだと糞遅いDWH向けだろ。
列指向DBを速くしたいというなら、それに向いた問題を持ってこなきゃいけない。
>SELECTが早くなるという話を聞いて
限られた条件だけだよ
1年目のDBAですが結合とか副問い合わせの理解が乏しいです。
SQLをマスターするためにオススメの書籍あれば教えて欲しいです。データベースはOracleがメインです。
>>946 Oracle Master Bronzeの参考書
俺のチンポをしゃぶってれば副問い合わせは分かるようになる
結合は、俺がチンポはめながら教えてやる
>>946 よくDBA名乗ってるな
どんな基準だろ?
Database Assistantか
>>948 図書館に行ってSQLの入門書片っ端から借りて読めよ
結合とか副問い合わせ云々言ってるレベルだったらOracleとか関係ないだろw
てかOracleの管理者って、AWRレポート作ってサポートに投げる、
サポートに言われたSQLをコピペし結果をコピペする、を
無駄なく速やかにこなすことが一番重要なスキルなのではないか
いや、AWRレポートぐらい自分で読めよ
DBMSのセットアップやチューニングの本はたくさんあるけど、
クエリの書き方や、スキーマの設計に関わる本の鉄板って知らないなぁ。
以前読んだ SQLアンチパターン って本はなかなかおもしろかったけど、
得られるものはあまりなかったし、かなりピンポイントだからなぁ。
>>954 現場での独自の判断が、初動のまずさのきっかけとなり、システムの復旧が遅延した、という
始末書を書く破目になるか
それともサポートベンダの対応の遅れにより、システムの復旧が遅延した、という報告を
ベンダの始末書添付してまとめる側となるか
その違いは大きい
後々の残業時間的に
おいやめろ
さすがOracler
959 :
nntarou:2014/06/01(日) 18:20:32.53 ID:otWRvot4
>>943-945 いやDB2なんだ…
ありがとう。条件限られてるんだな。もっと調べてみるよ
mysql 5.5です
コードマスター codeMaster
code int(11) not null primary key,
weeklymake int default 0, ←週間累計データ作成対象は1
dat1 varchar(20) default null
週間累計データ weeklydata
code_w int(11) not null,
date_ws date not null,
date_we date not null,
ruikei int default 0,
PRIMARY KEY (code_w,date_ws)
となっているんですが、コードマスターのweeklymakeが1となっていて週間累計データにデータが無いコードを出したいのですが、どのように書けば良いのでしょうか
codeMasterには日付情報がないのか?
>>961 select code where weeklymake = 1 and code not in (select code_w from weeklydata);
>>962 codeMasterには日付に関する情報は入れてません。例えばデータの登録日付とかですよね?
今後考えてみます。
>>963 ありがとうございます。
codeMaster.code と weeklydata.code_w が同じものであるという記述がないから混乱を招いたのです。
ところで、 not in だとパフォーマンスが悪いかもしれない
(というか、データが増えるにつれ、よくない結果を招く場合がほとんどな)ので、
そのあたりは随時プランナとにらめっこしながら検討してみてください。
まずは直感的に分かりやすい not in からと思いそうしてます。
直感的にわかりにくいものを選ぶとは
そう?
not existsのような相関サブクエリって最初は苦手だったよ。
それとも外部結合やexcept?
個人的にはexceptが次点ではあるけど。
ともあれ、主観を伴うので、直感的に分かりやすいものを書いてあげるとよいのでは。
>>963のはdistinctをつけたほうが良い気がする。
>>963 from書いとけよw
>>968 メインのクエリはcodeが主キーなんだからdistinct意味なし
サブクエリは結果に影響しないから、distinct意味なし
っていうか、ホントにdistinct処理されたらその分遅くなる可能性が高い
mysqlがどうか知らんが、いまどきのオプティマイザならこのぐらいのnot inは綺麗に展開するんじゃないかな
まずはわかりやすいSQLでnot inからって
>>965の意見には同意する
not inを綺麗に展開できるオプティマイザがあれば教えて欲しい
EXPLAIN結果もな
not existsはmysqlは綺麗に展開できないらしいが
他の有名どころは展開できるな
直感的にはどっちでもいい。
code_wにnot nullついてるし、処理順番の違いだけ
相関サブクエリじゃないnot inって展開のしようがないかもしれんな
SQL Server2008でテーブルだけつくって試したらどっちも
codeMasterスキャンしてネステッドループでweeklydataのインデックスシークだったわ
not inが相関サブクエリじゃなくてもちゃんと親のcodeでシークしてる
weeklymakeにインデックスないからcodeMasterフルスキャンは妥当?
codeMasterがそうとうな件数とかじゃないとこのプランじゃないかなぁ
オラクルマスター12cブロンズのSQLは合格しましたが、
12cDVAで何を参考書にすれば良いか分かりません。
テーブル設計の質問です
・MySQL 5.1.66
・テキスト管理の掲示板のツリー構造を一つのテーブルに格納
1,16,23,3 (1から始まるスレッド)
220,325,459,23,125 (220から始まるスレッド)
一行が掲示板の一スレッドとなるデータがテキストで保管されています
番号はユニークな発言番号です
例では220を親として325→459→23とつながります
順番を入れ替える必要性があり、必ずしも昇順として保存されません
この場合どんなテーブル構造が望ましいでしょうか?
ユニーク番号/先頭の番号/スレッド内の位置
こういう形でしょうか?
よろしくお願いします