このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。
SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。
質問するときはDBMS名を必ず付記してください。
【質問テンプレ】
・DBMS名とバージョン
・テーブルデータ
・欲しい結果
・説明
前スレ:
SQL質疑応答スレ 7問目
http://pc11.2ch.net/test/read.cgi/db/1223525474/
よくある質問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
;
7 :
NAME IS NULL:2009/03/07(土) 00:30:17 ID:lFENR4eI
ちょっとSQLとは離れてしまうのですが、テーブルのなかにテーブルを作れる DBMS ってあるのでしょうか?
id | table | data
--+----------+-----
1 | sub_tb1 | aaa
2 | sub_tb2 | bbb
こんなかたちで、普通のデータとテーブルを混合して扱えるといいのですが、
>>7 少なくともOracleではできるけど激しくお勧めしない
今すぐデータ構造を見直したほうがいい
>>7 何故それをやらなければならないのか、それが問題だ。
10 :
NAME IS NULL:2009/03/07(土) 02:33:50 ID:lFENR4eI
>>8 >>9 一つのプロジェクト情報を1レコードで管理しようと考えていまして、こんな感じのデータ入れようと思っています。
主キーはプロジェクトコードになります。
A工程作業 10人の氏名や単価などなど5カラムくらい。
B工程20人...
C工程30人...
となると、1レコードあたり300カラム以上になってしまい、また委託先がバラバラなので外注マスタみたいなものを
作るのが困難なため、こんな方法にしようかと、、、なにかいい方法はないでしょうか
>>10 一つ確認なのですが、300カラム以上と言うのは、
(10人 x 5カラムぐらい) + (20人 + 5カラムぐらい) + (30人 + 5カラムぐらい)
という計算で良いのでしょうか?
13 :
NAME IS NULL:2009/03/07(土) 10:40:24 ID:lFENR4eI
>>11 はいそうなんです。こんな形で考えてみましたのですが、ありなのでしょうか?
|A名前1|A単価1|A期間1|A社名1|A備考1|・・・|A名前10|A単価10|A期間10|A社名10|A備考10|B名前1|・・・|B備考20|C名前1|・・・|C備考30|
>>12 なにか根本的に間違っているのでしょうか、、
>>13 根本的に間違ってるからまずリレーショナルデータモデルを勉強したほうがいい
15 :
NAME IS NULL:2009/03/07(土) 11:40:31 ID:lFENR4eI
>>14 なんか根本的に間違ってる気がしてきた、、項目が多い部分は、外部のテーブルにしろってことですかね。
□主テーブル
|プロジェクトコード|プロジェクト名|予算|工期|・・・・
□外部のテーブル
|プロジェクトコード|工程種別|No|名前|期間|備考|
こんな形にしてプロジェクトコードで結合。この場合、正規化する必要の無いテーブルを分割しているのですが、それはありですか?
主キーとか正規化とか知ってる割には... 釣りとしか思えん。
釣りじゃないと言うなら、
>>12,
>>14 が言ってるように本屋に
行ってデータベース関連の本買ってきて勉強した方がいい。
釣りじゃないですよ。もう少しちゃんと勉強しないとまずそうですね。
スレ汚しみたいになってしまってすみませんでした。本買ってきます。
なんて偉そうなw
純粋にデータベース理論に基づく議論として、
>>13のスキーマがダメで
>>15のようなスキーマの方がよい理由って何でしょうか。
ここは SQL なスレであって、テーブル設計のスレではないことに
そろそろ気づこうな。
21 :
NAME IS NULL:2009/03/07(土) 23:08:49 ID:lFENR4eI
本から調べてみましたが、正規化するする必要がないテーブルを分割するのは設計上ありえない、もしくは仕方の無い場合のみ
しかしカラム数が膨大になる場合でも分割するのは、EDI規約では分割しては "ダメ" とのこと、、、
まあ結局 Oracle あたりで調べてみるしかなさそうですね
どうでも良いけど、「リレーションをつかえば..」「そういう設計はない」「もう少し調べてろ」とか うちのアホ上司と
答えが同じで面白かったです。で、困ると「俺に(ここ)で聞くな」的なw 知らなければ知らないでいいですよ。無理しないでね。
何をもって「正規化する必要がない」なのか、俺には全然理解できん。
普通に正規化する必要ありそうに見えるけどな。
>>21 正規化について考えたのであれば
>>10のデータに関して
関数従属性(FD)を見当したはずですが、どのようなFDを
列挙したか書いてもらえますか?
ACCESSだけど、
>>13と同じ構造でテーブル設計されてるDBを見たことがある。
もうなんていうか、え…っ?何を見たんだろう…?って感じ。
でもさすがに300カラムはなかった。255カラムだったw
>>19 人の入れ代わりが繰り返されたら、そのテーブル構造だとどうなるかをまず考えてみよう。
そうして、正規化について基礎から勉強しなおそう。
スレ違いなのに、逆ギレを装いつつ煽ることで答えを引き出そうとするテクニックですね。
いい加減、スレ違いなお馬鹿さんにつきあうのはやめにしましょう。
>>24 いや、なので純粋に「関係データベースモデル的に」ですよ。ネタです。
とりあえず部分従属も推移的従属も多値従属もないですよ?
27 :
NAME IS NULL:2009/03/07(土) 23:37:48 ID:lFENR4eI
>>23 なんかスレ違いを続けてすみません。
プロジェクトA の 作業A の スタッフ1 は プロジェクトコードAにのみ従属するので断念しました。スキル不足かもしれません。
また、正規化の基礎が分かっている方なら、それが出来ないくらい分かりそうなものだと思いますが、、
データベース関連の本買ってきて勉強した方がいい。ですよw
カタカナ言葉で逃げないで、ちゃんと読めって言われた本やマニュアル読みなよ。
自己満足で変な物作るなよ。
>>27 失礼しました。関数従属性も見当しないで「正規化すると・・・」なんて
文句言う人も少なくないので一応ちゃんと見当したか確認したかった
のです。見当したという事で、了解しました。
もう一つ確認なのですが、各プロジェクトのスタッフの数は10人・20人・
30人で固定でしょうか。
欠員や人数割れは発生しませんか?あるいはこれらの人数は単に
上限を示すものでしょうか。
データーベースってさ、
「作る前に」
いっしょうけんめい、考えないといけないよね。
>>24 > ACCESSだけど、
>>13と同じ構造でテーブル設計されてるDBを見たことがある。
> でもさすがに300カラムはなかった。255カラムだったw
Excel の概念から脱却できなかったんだろうな。
まあ、Excel 2003 まででよかったよ、Excel 2007 使いだと、カラム数 1,000
とか平気で作りそうだし。(w
33 :
NAME IS NULL:2009/03/08(日) 00:16:05 ID:OlHguXyr
34 :
7:2009/03/08(日) 00:19:08 ID:vyix2FVv
>>29 こちらそ失礼をすみません。スタッフの数は極端な話 0人(全てお任せで社名のみ)〜100人近くになる可能性もあります。
直接プロジェクト管理する場合は、全てのスタッフ情報を登録する必要があり、外注先が子会社、別会社、個人とバラバラなので
マスタを作るとなるとショットで頼んだ個人まで登録しなくてはならないので、
>>13 みたいな形を考えました。
ただ想定している上限100名×5 = 500カラムはちょっと無理そうなので、テーブルのなかにテーブルがつくれるのがいいのかな?と考えました。
35 :
NAME IS NULL:2009/03/08(日) 00:29:25 ID:OlHguXyr
>>34 了解しました。実は以下の回答はあらかじめ書いてあったものです。
無駄にならなくて良かったw
まず私の意見としては「正規化すれ」云々のコメントは全く見当違いです。
例としてあげられた
>>13のスキーマは第五正規形まで見事に満たしています。
これ以上正規化しようがありません。更新時異常も起こりようがありません。
失敗はリレーションの正規化以前の、データ設計にあります。
例としてプロジェクトの「作業Aのスタッフ1の名前」を挙げます。
>>13のスキーマではこれは次の関数従属性で表現されています。
プロジェクトID -> 作業Aのスタッフ1の名前
これに対して、ベターな表現は次のようなものです。
プロジェクトID, 作業A, スタッフ1 -> 名前
何故これがベターかは左辺の作業名とスタッフ番号を具体値から属性名
に置きかえると判ります。
プロジェクトID, 作業名, スタッフ番号 -> 名前
幸いこれは多値ではない関数従属です。ですので綺麗に第一正規形の
リレーションで表現出来ます。試しに元の表現でもやってみます。
プロジェクトID -> 作業名, スタッフ番号, 名前
これは多値関数です。ですのでナイーブに実装しようとすると思わず入れ子
リレーションを発想してしまうかも知れません。
>>7のような質問が出てきた
理由を無理矢理理屈立てて推測すると、多分こんなところです。
いずれにしても
>>15のスキーマは
>>13のスキーマの正規化を崩している
のではなく、元より異なるデータ構造を実装したものなのです。
なので安心して
>>15のアプローチでデータベースを作ると良いと思います。
>>31 Oracleならありそうで怖いw
Accessは幸いなことに…いや全然幸いでも何でもないけど、1テーブル255カラムが最大。
>>26 >>13のテーブル構造で、それぞれのプロジェクトにかかるコストを算出することを考えてみて。
工程ごとの小計もそれに加えたりなんかすれば…、死ねるw
DB構築する意味ないじゃん。
なんだ〜、さっぱり理解できない…
最後の1文だけ同意するw
正規化できない暴威は結局,答えが欲しいんでしょ?
素直になれば良いのに。
「教えてください」って言えない子は,自分勝手に設計して
後で理解できれば本人のためにも良いと思う。
スレチってことも自覚してるようだし。
Access弄ってる気の利いた素人でもそんな設計しないよw
39 :
7:2009/03/08(日) 01:24:03 ID:vyix2FVv
>>35 >失敗はリレーションの正規化以前の、データ設計にあります。
>元より異なるデータ構造
このあたりを考えていなかったため、おはずかしい考えをさらしてしまいました、、、
別テーブルを、異なるデータ構造を扱うためのものとしてとらえてみます。
ベテランの方だと思うのですが、失礼すみませんでした。
>>37 要約すると、次のような感じ。
(1)
>>13のスキーマは正規形
(2)
>>15のスキーマは
>>13のとは異なるデータ構造を実装したもの
(3) なので
>>15のスキーマは正規化崩しではない。安心してOK。
(4) 正規化正規化言っている人は、ちゃんと理解して言っていますか?
(4)が屁理屈っぽく書いた理由です。
ただ正規化正規化言っているのも、ちょっと無責任だなと思ったので。
余興ついでにもちっと数学的に屁理屈をつけると
>>13のスキーマに
含まれる関数従属は
>>15のスキーマで表現されている関数従属
プロジェクトID, 作業名, スタッフ番号 -> 名前
の左辺にある作業名・スタッフ番号という属性に対してカリー化という
操作を適用し、出来た関数にこの2属性の具体値を適用する事で、
この一つの関数従属を複数の関数従属へと分割したものです。
数学的も何ら問題ない操作ですし、データモデリングの際には逆カリー
化と共に広く行われている操作です。
問題はこの操作によって出てくる関数従属の数や種類は適用された
2属性(作業名・スタッフ番号)の具体値(またはドメイン)に依存します。
例えばスタッフ番号の数が変わると、異なる数の関数従属が出ます。
他方でデータベーススキーマの一つの目的はデータ中の関数従属を
十分に表現する事ですから、関数従属の数や種類が変わるとそれに
応じてスキーマも変更しなければなりません。
スキーマ=時間不変な構造、が、スタッフ番号の数などでコロコロ
変化されては困ります。屁理屈を言えば
>>29の質問の意図はこの点
を確認するものでした。
ところが実際はスタッフの数はどうも曖昧っぽかったので、理屈的にも
ベターなのはこのカリー化を適用していない
>>15のスキーマです。
>>40 詳しい説明をどうもです。
でもカリー化とやらをググってたら脳ミソ逃避し始めた…w
>>41 ごめんなさい。ググるほどの概念でも、難しい操作でもありません。
手順を書くと次のような操作です。
(元の関数従属)
プロジェクトID, 作業名, スタッフ番号 -> 名前
(カリー化)
作業名, スタッフ番号 -> (プロジェクトID -> 名前)
これだけです。右辺も関数になっているのがミソです。
(左辺に具体値を適用)
作業A, スタッフ1 -> (プロジェクトID -> 名前)
作業A, スタッフ2 -> (プロジェクトID -> 名前)
...
作業B, スタッフ1 -> (プロジェクトID -> 名前)
作業B, スタッフ2 -> (プロジェクトID -> 名前)
...
あとはそれぞれの左辺の具体値を新たな属性名として利用して、
右辺の関数従属を
「プロジェクトID -> 作業Aスタッフ1の名前」
のようにスキーマ内で実装すれば
>>13のスキーマが出来ます。
ただこれらは「屁理屈」ですからね。理解としては楽しいですが
あまり世間的に役に立つとは思いません。
俺の意見としては
>>13 は「正規化できてない」だな。
単純に「作業名(?)」が重複してるから。
そんなん、「作業」が増えたときにすぐ死ねる。
「スタッフ」もとくに固定ではない、ってことだし。
マスタ化しづらいなら、マスタから値を引っ張るケース、その行に単一スタッフを
書き込むケース、なんて形に分けると思う。
俺もそう思う。
難しい言葉はともかく、第一正規形は
「テーブル内テーブル」を排除したものでしょ?
>>42 待った。
>>13を見ただけではそのような関数従属が存在するとは判断できないと
いう意味で、
>>13が非正規形であると言い切れないというのは良い。
ただ、
>>42のような関数従属の存在を前提とした場合、コッドの関係モデルが
一階述語論理に基づくものである以上、そのようなカリー化された関係を
スキーマに表現することはできない。
カリー化の操作そのものには問題はないのだが、「左辺の具体値を新たな
属性名として利用して」という部分で、元の関数従属を表現できなくなっている
ことに注意。
>>45 その通りです。一連の操作で展開された関係従属の集合と元の関数従属は
同じものとして扱う事は出来ません。
なので
>>13と
>>15のスキーマは「異なるデータ構造」、つまり異なる属性集合
と異なる関係従属性の集合を表現したものなります。
元々の質問が
>>15は
>>13の正規化崩しでは無いか、というものであったので、
そうではないです、なぜなら元より異なるデータ構造を表現しているのだから、
というのが一連の趣旨です。
>>43-44 データ設計(モデリング)とスキーマの正規化ははっきり区別すべきです。
データベースで表現したい対象から属性とその間の関係を抽出するデータ
設計とスキーマの正規化はどの本でも異なる章に書かれているはずです。
元のデータ中に存在する関係従属性を出来るだけ保ったままリレーションを
無損失に分解していくのが正規化の一連のステップですが、
>>13から
>>15 のように肝心の関係従属性の集合をざっくり別のものに入れ替えるようでは
流石に正規化の範囲を超えています。
これはデータ設計の問題として議論すべき事柄です。
実際
>>13のスキーマはちゃんと正規形なのです。なぜなら
>>27にあるように
「作業Aスタッフ1の名前はプロジェクトコードにのみ関数従属する」他の属性
についても以下同文、というようにデータを設計したらです。
そのようなデータを表現する限りに置いて、このスキーマは正規形です。
ですのでツッコミの入れどころは正規化ではなく、データ設計のそのものと
なります。
ありゃ、関数従属が全部関係従属になっている・・・Typoです orz
君らが賢いのわかったから、どっかよそでやってくれないかな。
やっぱりXMLデーターベースだよねー
あとから変更できるしー
いい加減、煽るのやめろよハゲ
注意されて逆切れするタイプなんだろ。
スルー推奨。
>>49 XQueryとXPathが全社共通になったらね。
>>53 そんなの待ってられないから、
とりあえず、現時点でシェアトップのものを
使いたいんだけど?
よし ならば DB2 v9.1 pureXMLだ
夏前にはv9.5が出るよん
>>53 それを言うなら問題はXQuery Update Facilityだと思うけど・・・
XQueryやXPathは世に言うXMLDBなら大概は使えると思う。
PHP+MySQLで、ある設定をひとつのユーザにつき10個までに制限したい
この場合の設定テーブルは
ID、ユーザーID、設定1、設定2、設定3・・・設定10
なのか
ID=ユーザーID*10+0、ユーザーID、設定
ID=ユーザーID*10+1、ユーザーID、設定
ID=ユーザーID*10+2、ユーザーID、設定
なのか・・・
どういう構造がいいんでしょうか?
典型的には後者だけど、次のような点が検討項目になるかな
・「設定」って何?
(a) 設定={設定値A, 設定値C, 設定値J, ...}みたいな形で
最大10個まで設定値の好きな組み合わせを選べるものなのか、
(b) 設定1: 設定値F, 設定2: 設定値A, ...設定10: 設定値Kみたいに
設定1から10までの項目があって、それぞれに設定値をセット
するようなものなのか
・(a)だとして、設定値を選択した順番に意味はあるのか。
・(b)だとして、設定値のダブりはありか(設定2: 設定値F, 設定5: 設定値F)
・「設定」をテーブルで表現したとして、どういう検索をしたいのか
設定値はユーザーが任意に入力できる正規表現の文字列なので、
多種多様な値が入ることになります。
検索はしないかもです。データベースでやる必要はないんでしょうか?
とりあえず後者のやり方でやってみます
ユーザーIDで検索するだけってことだよね。
ところでユーザーIDも保持してるならIDを10倍して足す意味が無いような。
>>59 後者だとして、「ID=ユーザーID*10+0」は多分使い勝手が
悪いので別の方法をとった方が良いよ。
単にユーザが正規表現を10個登録したいだけなら属性は
{ユーザID, 正規表現}だけで、この2属性の組にPK制約
かけておけば十分。
もし正規表現1は○○、正規表現2はXX、みたいにある
正規表現が何番目の正規表現であるかが重要なのであれば、
{ユーザID, 正規表現No, 正規表現}といった3属性にして
{ユーザID, 正規表現No}にPK制約をかける。正規表現Noは
1から10までの、ユーザごとの正規表現の通し番号です。
「ID=ユーザーID*10+0」という表現はユーザIDと正規表現No
の二つを表現しているので、すぐ隣に「ユーザID」属性もある
ことを考えると意味的にオーバーラップしています。
こういう属性は後日色々とトラブルの元であることが経験的に
知られています。
例えば今日から正規表現数を20個まで増量!などした時など。
なるほど。
{ユーザID, 正規表現}でPK制約しようと思いましたが、
フレームワークがCakePHPなんで
IDは制約として必要で複合キーもサポートされていないみたいです。
しょうがないのでやっぱり、ID=ユーザID*10+0にしてみようと思います
ありがとうございました。
なんでわざわざ SQL のスレで聞くのか・・・
タイトルに「質問」「質疑」って書いてあるスレ他にあまり無いし。
DB設計の方は「語る」スレらしいのでこっちに流れてくるのも
仕方がないのではないかと。
SQLServer2000を使用しています。
テーブルAに項目1がありそのMAX値に+1をした結果を
テーブルAにインサートするストアドプロシージャを作りました。
複数プロセスから同時実行する際に排他ロックをかけたいのですが、
デッドロックのような状態になってしまいました。(3プロセス同時)
ロックの考え方が間違っているのでしょうか?
@param1 output
AS
Begin Transaction
SELECT @param1 = MAX(項目1)+1
FROM テーブルA
WITH (TABLOCK,XLOCK)
INSERT INTO テーブルA(項目1)VALUES(@param1)
Commit Transaction
ロックについてはわからんけど。
auto_increment 列を使うのが一般的じゃない?
>>62 やめたほうがいいって回答されてるのにあえてやるってのは、回答者への
嫌がらせなんだろうかw
PKをIDにしても、べつにUNIQUE NOT NULLな制約は付けられるでしょ?
>>62 複合キーを使えないというのであれば、普通にサロゲートキーに
しておいた方が良いと思う。
「ユーザID*10+x」なんてキーにするなんて、仕様に自ら爆弾を
仕込むようなものですぜ。
SQLiteって、CHECK制約が使えないってひどくないですか。
データーの入る範囲を、1−100にしたい、とか思っても、
できないってことじゃないですか。
アプリ側で制約すればいいじゃん。
>>66 ありがとう
ただ、他のテーブルも同じように排他ロックをかけようとしていたので
先ほどの条件でうまく排他制御できないことが気になってました。
もう少し自分で試してみます。
>>74 読んでる教科書が2005年発行のやつだったので
古かったようです。
実際にやってみて困った話じゃないのかよ
だって教科書読んでたら、
対応してない、って書いてあるんだもん
でも他人様の成果物に対して「ひどい」なんて文句をここに
書き込む前にちょっとはクグろうや。
「sqlite check」で一瞬で見つかったよ。
トリガーっていうの、
よくわかりません
>>79 Insert とか Update とか Delete とかが発生したときに呼び出されるプロシージャ。
TableA のデータが削除されたタイミングで、TableB の関連データを削除する、
とかってときに使えるよ。
ようはストアード・プロシージャの一種なのね。
違いがわからんかった。
ユリウス暦ってのがよくわかりません
スキーマとプラグマの違いがよくわかりません
ランダムに1−5を生成して、
それをボタンが押されるごとに、
どんどん足していく、というプログラムなのですが、
SQL側でランダムに数字を生成して足す、という
構造に今、しているのですが、
「○を足しました」
とかってPHP側で表示したいのですが、今、
いくつの数字をランダムに生成して、いくつ足したのか、
って、PHP側で知る方法はあるのでしょうか?
それとも、前後の差分を取るしかない?
>>84 だってユリウス暦を取得する、って関数があるんです。
昨日発見しました。
>>85 SQL でどんな処理をしてるのか書こうな。
>>84 ユリウス歴が何かは Google とかで調べような。
SQL には直接関係ないから。
>>79 もちっと厳密に言うと、active databaseという考え方が元になっていて、
・○○が起きたときに (Event: イベント)
・△△だったら (Contition: 条件)
・XXしちゃう (Action: アクション)
のECAの三つ組みをデータベーススキーマとして登録する仕組み。
外部キー制約などで表現しきれないリレーションやその間の制約
を表現したり、データ更新のログをとったりするのに使えたりします。
>>82 どっちかというとこの質問はWikipediaの領分かな。
欧米における日本の旧暦みたいなものです。
今でも正教会とか、お祭りを今のグレゴリウス暦ではなく昔の
ユリウス暦で祝うところがまだあるんです。
しかしこれを実装するのであればDATE値から大安とか丑年とか
計算してくれる関数がないと不平等だよな。
>>85 > ランダムに1−5を生成して、
> それをボタンが押されるごとに、
> どんどん足していく、
なんか、最近似たようなモンを見たような気がするが、なんかの課題なのか?
SQLite3で、
あとからAUTOINCREMENT 指定するのは
不可能?
前スレでの話しだな。> ランダム
で、その前スレから疑問に思ってたけど、乱数生成をSQL側でしようとするのが疑問だった。
最終的にはUPATE Table SET val = val + random().... 的な使われ方だけで
済むのならSQLで済ませてもいいけど、いろいろ制約(乱数の範囲やvalの最大値)があるみたいだし、
素直にPHPで生成させておけば、そんなに悩むものでも無かろう。
>>92 それで生成させたランダム値を
PHP側で知りたいんですけど、無理ですか?
ようはコンビニでおでんを買って、
「たれは、ごまだれにしますか?からしにしますか?それとも何もつけないようにしますか?」
って聞かれて
「ランダムでいいです」
って答えて、
「でも、ランダムに決定して、その結果は教えてね」
みたいな。
>>93 できるだろ。テーブルに1件だけデータを入れておいて、Update のあと Select するとか。
テンポラリーテーブルか。
うまいね。
SQLite3の最新版で、
alterで、テーブルを作成したあとに、
autoincrementを付加することは可能なの?
見せる… 行ロックを無限に発生させてしまうSELECT文が…
>>4に関連して「最新のものの次点のレコード」を抽出したい場合は
どうすればいいでしょうか。
DBはOracle10gです。
<出力イメージ>
1 | 2007-11-10 | ccc
3 | 2007-11-11 | eee
>>100 1 | 2007-11-11 | aaa
の間違いじゃね。
Oracle使いじゃないけど、WITH句を使うとこんな感じかな。
WITH RemoveMax AS (SELECT * FROM Table WHERE (id,date_) NOT IN (SELECT id,max(date_) FROM Table GROUP BY id))
SELECT * FROM RemoveMax JOIN
(SELECT id,max(date_) AS date_ FROM RemoveMax GROUP BY id) AS T1
USING (id,date_);
WITH句なしで、
SELECT * FROM
(SELECT * FROM Table WHERE (id,date_) NOT IN (SELECT id,max(date_) FROM Table GROUP BY id))AS T1
JOIN
(SELECT id,max(date_)AS date_ FROM
(SELECT * FROM Table WHERE (id,date_) NOT IN (SELECT id,max(date_) FROM Table GROUP BY id))AS T2
GROUP BY id)AS T3
USING(id,date_);
フィールド名にdateは使えないのでdate_としています。
create table categorizings(
product_id integer not null references products(id),
category_id integer not null references categories(id),
sub_category_id integer references sub_categories(id),
created_at datetime not null default current_datetime,
updated_at datetime not null default current_datetime
)
というテーブルがあるのですが、重複しているレコードがあるので、それを抽出しようとしています。
はじめは
select product_id, category_id, sub_category_id
from categorizings
group by product_id, category_id, sub_category_id
having count(*) > 1
としていたのですが、重複しているデータのcreated_atとupdated_atも抽出するようにと言われて、困ってます。
今は
select c1.*
from categorizings c1
where concat(c1.product_id, '-', c1.category_id, '-', c1.sub_category_id) in
(select concat(c2.product_id, '-', c2.category_id, '-', c2.sub_category_id)
from product_categorizings c2
group by c2.product_id, c2.category_id, c2.sub_category_id
having count(*) > 1)
;
としているのですが、パフォーマンスが遅いし、これで正しいのかもよくわかりません。
なんかいい方法を紹介してください。よろしくお願いします。
MySQL 5.45
未チェック。概念だけ
select A.*
from
categorizings A,
(select
product_id, category_id, sub_category_id,
count(*) as RNUM
from categorizings
group by product_id, category_id, sub_category_id
) B
where
A.product_id = B.product_id and
A.category_id = B.category_id and
A.sub_category_id = B.sub_category_id and
B.RNUM > 1
>>102 パフォーマンスを気にするのなら、
product_id, category_id, sub_category_idのカラムを
複合primary keyに持つcategorizings_duplicatedなりの
別テーブルを作って前者のSQLをinsert intoして
それとjoinするのが最速かと。
105 :
NAME IS NULL:2009/03/17(火) 08:55:52 ID:HhqqMBkm
vistaに11gの30日番をインストールしました。
sqlplusがコマンドプロンプトと変わりません。
よく見慣れた十字架のお墓みたいなアイコンのsqlplusだけをインストール
できないでしょうか?
GUI版のSQL*Plusは11gから廃止されました。
107 :
NAME IS NULL:2009/03/17(火) 12:52:28 ID:HhqqMBkm
以下のようなデータがあるとします。
id no data
1 1 aaa
1 2 bbb
1 4 ccc
1 5 ddd
このデータをidとnoで昇順でソートした後
noの番号を降りなおしたい。
つまり、以下のように更新したい
1 1 aaa
1 2 bbb
1 3 ccc
1 4 ddd
このようなsqlはどのように記述すればよいでしょうか。?
>>108 idとnoの組合せで一意になる、かつDBMSがOracleと仮定して
update TableName a
set no = (select b.RN
from (select id,
no,
row_number() over (order by id, no) as RN
from TableName) b
where a.id = b.id
and a.no = b.no)
;
>>108 ついでにたぶん汎用解
update TableName a
set no = (select count(*) + 1
from TableName b
where a.id > b.id
or (a.id = b.id and a.no > b.no))
;
111 :
>>108:2009/03/18(水) 01:43:48 ID:???
112 :
>>111:2009/03/18(水) 16:24:28 ID:???
mysqlの場合は、以下のようにする。
update hoge as a inner join (select *,(select count(*) + 1 from hoge where no<x.no) as rownum from hoge as x) as b on a.id=b.id and a.no=b.no set a.no=b.rownum where a.id=1
mysqlだとそんな奇怪なSQLになるのか・・・
とはいえ、
>>110も標準SQLではないな。(UPDATE句に相関名は書けない)
相関名をやめて
update TableName
set no = (select count(*) + 1
from TableName b
where TableName.id > b.id
or (TableName.id = b.id and TableName.no > b.no))
;
にすれば標準だと思うけど。
Oracle10gにて
SQL中の文字列(WHEREの後ろとかLIKEの後ろ)にそのままでは使えない文字の全量、対応方法ってわかりますか?
予約語の一覧が欲しいのかな。
各RDBMSのマニュアル読んで、ユニークな列名を考えて下さい。
>>114 質問の意図が、予約語と解釈する人もいれば、エスケープが必要な文字と
解釈する人もいそうな曖昧な質問の仕方だなw
114です
すみません…
'%_(シングルコーテ、パーセント、アンダーバー)のようなエスケープが必要な文字を知りたかったのです。
>>108 このテーブルってidとnoがprimary keyだと思うんだけど、更新するカラムをprimary keyのするのはよくないと思うんだけど、どうなんだろう。
もし、俺がテーブル設計するなら、以下のようなカラムを用意して、idとnoをprimary keyにして、no2を更新カラムにする。
id no no2 data
こうしないと、以下のデータがあったとして、
id no data
1 1 aaa
1 2 bbb
1 3 ccc
二行目以下のnoを、まとめて+1するようなsqlをじた、キー重複エラーが発生する。
122 :
NAME IS NULL:2009/03/24(火) 15:04:34 ID:yR1qlEgs
ある条件でORDERBYした時の、あるレコードの前後のレコードを取得することって可能ですか?
全レコードを一旦取得して、ホスト言語で前後を抽出するか
ORDER BYが一個のカラムなら、対象レコードのそのカラムより大きいものをCOUNTして、
OFFSETでとってくることも可能かな
でも、ORDER BY対象がユニークなカラムじゃないとだめか・・
なんかどれも効率悪そうなんですけど、もっといい方法ありますか?
MySQLです。
あるレコードの前後つーのは、
あるレコードの前→あるレコードより小さい中での最大
あるレコードの後→あるレコードより大きい中での最小
ORDERBY対象がユニークなカラムじゃない
のに特定レコードの前後を取りたいとかアレなの?
氏ぬの?
>>122 具体例を挙げないと、何をしたいのかわからん人がほとんどだと思う(俺も含め)。
ソートした結果の10位前後のレコードを取り出したいというのなら
「じゃあ select * from table order by key limit 9, 3; でいいじゃん」
と誰もが答えるだろう。
126 :
NAME IS NULL:2009/03/24(火) 18:32:38 ID:yR1qlEgs
>>123 ああ、そうか、そう考えれば簡単ですね。ありがとうございます。
>>124 ありがとうございます。
例えば更新日時で時系列に次へ次へみたいにリンクを出したい時、
そういう場合どうすればいいのでしょう?
更新日時って同じタイムスタンプになる確率があるって聞いたんですけど
更新日時カラム自体をユニークにして万が一同じタイムスタンプになったら、再保存するようにするのでしょうか?
これが例えば変更されない登録日時なら主キーを使ってしまうって言う手もありますけど。
まあ、そもそも、更新されたら並び順が変わるし、このインターフェイス自体が問題あるきもしますけど。
127 :
122:2009/03/24(火) 18:42:55 ID:yR1qlEgs
>>125 具体的には126にちょっと書きましたが
記事の表示ページに更新日時順で次へ、前へというリンクを出したいんです。
で、そのページはダイレクトに主キーで記事を指定してくることもあるのでLIMIT 1 OFSSET〜っていうわけには行かない感じなんです
128 :
125:2009/03/24(火) 19:06:53 ID:???
>>127 ページング処理をしたかったのね。
俺も業務上そのテの開発はよくやるけど、やっぱり limit x, y だよ。
記事を指定して、その記事が含まれるページ(例えば81〜90件目を表示)とかに
飛ぶようなリクエストが発生するシステムであれば、
(順位, 更新日時, 記事ID) を持つソート済みテーブルをあらかじめ作成しておく。
レコード数が多いなら記事IDにindex付与。
更新日時が可変で順位が変わる可能性があるのなら、その頻度に応じてソート済みテーブルを再構築する。
じゃ123でいいじゃん
テーブルX(a,b)と
テーブルY(b,c)で
列bを結合キーにした場合、
テーブルXに無いレコードをテーブルYから削除するには
どのようなSQL文を書けば良いでしょうか
where not in select b from A
でいいんじゃないの?
ごめんAじゃなくてXだった
133 :
130:2009/03/26(木) 08:13:50 ID:???
>>131 ありがとうございます
結合は不慣れでして…
ちゃんと勉強しないといかんな
(´・ω・`)
>>133 結合は慣れです。
経験を積めば楽に結合出来るようにもなります。
慣れるまではプロの手ほどきを受けるのも良いかもしれませんね。
131で書いたのは結合じゃなくてサブクエリだけどね
136 :
NAME IS NULL:2009/03/27(金) 02:32:29 ID:p8FYVGy/
質問です。
以下のような、木構造のデータがあるとします。
東京→大田区→蒲田→羽田1丁目
東京→大田区→蒲田→羽田2丁目
東京→千代田区→秋葉原
大阪→住之江区→緑町
これを、テーブルに以下のような形式で入れるとします。
name prev_name
東京 東京
大田区 東京
蒲田 大田区
羽田1丁目 蒲田
羽田2丁目 蒲田
千代田区 東京
秋葉原 千代田区
大阪 大阪
住之江区 大阪
大阪市 大阪
緑町 住之江区
name=prev_nameなレコードが親トップとなります。(上記のデータですと、東京と大阪が親トップにあたります)
この状態から、name=大田区のレコードを削除されたと考えてください。
ここから、name=(蒲田、羽田一丁目、羽田二丁目)のデータを取得するにはどのようなSQLをかけばよいでしょうか?
※ 住所をこのような形式で管理するのはおかしい!と感じる方もいらっしゃると思いますが、
これは問題をわかりやすくするため、このようにしています。
実際に住所を上記のような管理をしようとしているわけではないので、あらかじめご了承ください。
>>136 恐らく、あなたが欲しいであろう回答をもらうための
前提条件が十分に説明されていない。
name in ('蒲田', '羽田一丁目', '羽田二丁目')
で満たされてしまうからだ。
138 :
NAME IS NULL:2009/03/27(金) 03:09:42 ID:p8FYVGy/
>>137 説明が足りず、すいません。
親がなくなってしまったname=蒲田のレコードと、その配下のレコード全部(つまり、羽田一丁目、羽田二丁目)を抽出したいという意味です。
>>138 その説明でも曖昧さはまだ残るのだが…。
「親が存在しない、つまり不完全な構造になってしまった全てのレコード
およびその子ノードたち(一世代まで下)を列挙したい」
と勝手に解釈するなら
select name from table_name
where prev_name not in (select name from table_name)
union all
select name from table_name
where prev_name in
(select name from table_name
where prev_name not in (select name from table_name))
140 :
>>139:2009/03/27(金) 03:57:31 ID:p8FYVGy/
>>139 解釈ありがとうございます。。。
>一世代まで下
ここは、一番最後の世代まで下、という解釈でお願いします。
ちなみに、MySQL使っております(後だしすいません。。)
>>140 これ、難しいけど問題としては面白いな。
解けそうで、解けないというか、一番最後の世代というところが難しいわ。
142 :
139:2009/03/27(金) 04:34:57 ID:???
>>140 そういうことなら、スマンが俺なら一つのSQLで済ますのはサジを投げる。
ストアドかホストアプリ側で列挙が完了するまでループ。
想定するシーンによっては、ホストアプリ側でn分木を再構築して
探索にはSQLに頼らない処理も考える。
いずれの方法も、循環参照の危険があるならそれも考慮しないと無限ループにハマるがな。
143 :
139:2009/03/27(金) 04:47:26 ID:???
>>140 ふと思ったが、もしかしてディレクトリツリーの再帰削除みたいなことをしたいのか?
それならトリガで子ノード(一世代だけでよい)のDELETE書くだけで済むけど。
>>143 MySQLってトリガのネストとか再帰とか可能なのか?
可能だとしても、階層に限界はあるだろうから、あまりにもネストが深いと失敗するかもな
MYSQLはOLAP使えないの?
どの程度の事をやりたいか判らないけどMYSQLのSELECT文には
WITH ROLLUP修飾子なるものが階層別の集計はやってくれる。
これ以上を求めるならMondrian辺りを突っ込んでMDXでクエリを
書いた方が幸せになれると思う。
whereでヒットしたレコードの指定件目を
SQL文だけで取得したいのですが、
どうすれば良いですか><
>>147 LIMIT 〜 OFFSET 〜が使えるDBMSならそれで
ROW_NUMBER()が使えるDBMSならそれで
countでいいじゃん
指定件目だぞ
なんでcountだよ
151 :
147:2009/03/28(土) 10:20:03 ID:???
>>148 ありがとうございます
sqliteですが、使えるか確認してみます><
>>147 orderを指定しないselectの、行が返される順番は保障されない
ということは覚えておいた方が良いかもしれない
>136
パッと見たかんじ、最大何階層になるかだけ解れば可能なように見える(実際SQL叩いてないけどw)。
最大階層数が不明なら階層数調べるためにループさせる必要があると思うのでストアドっぽい気がする。
>147
「ORDER BY」、「ROWNUM」
155 :
147:2009/03/29(日) 05:03:08 ID:???
LIMITとORDERで出来ましたヾ(^▽^)ノ
教えて下さった方々、どうもありがとうございました
礼にはおよばんよ。
またいつでも聞きにきなさい。
データベースダイアグラム(リレーションシップ)っていままで使用せずに来ましたが、
これって使うのが一般的ですか?
例えば、伝票ヘッダテーブル・伝票明細テーブルがあったとして、データベースダイアグラムしておくと、
ヘッダテーブルのレコードを削除すると、そのレコードに対応する明細テーブルからも自動的に削除される
って認識でいるのですが、なんか使いにくい気がしていつもコードからヘッダテーブル・明細テーブルを削除
しにいってます。
どうなんでしょうか。
データベースダイアグラムってMS SQL?
そうです。MS SQLです。
ACCESSでもリレーションシップは使っていませんでした。。
必要なきゃ使わなくていい。
ここは、SQL のスレであって、SQL Server のスレではないことに
気をつけような。
要は外部キーみたいなものだろうから、普通使うだろ。
みんな、サンクス。
すれ違みたいなので、そっちへ行くわ。。
開発中はリレーション張って開発するけど
本番はインサート性能落ちるからリレーション張らないな
Webだけの常識かもしれないけど
そうなんだ!?
情報サンクス〜^^
>>163 本番で外すような制約を開発時につけてるのか?
俺は開発時はリレーションに制約付けない。データの作成とか変更とかやりにくくなるから
逆に、本番は制約付ける。
制約のそもそもの目的は不正データの排除だから、本番についてないなら意味だろう
どうしても性能の問題で制約外すことはあるかもしれないが、
Webだけの常識ってのは違うとおもうぞ
Webシステムは伝統的にMySQLを使う事が多くて、
それにはMyISAMってのがあってだな、
設計時には勿論、外部キーを考慮してデータ設計するんだけども、
実際には云々以下略
>>166 > Webシステムは伝統的にMySQLを使う事が多くて、
プゲラw
お前さんのところの伝統を語られてもな・・・
まぁ実際問題Webサイトの大多数はMySQLだろうけどね
まぁ、スレ違いだな
クイズを出すPHPサンプルを弄っているのですが
問題を、AUTO_INCREMENTでIDを増やしつつ追加して
後で一部の問題を削除すると、空のIDでエラーになります。
つめて整理する方法&AUTO_INCREMENTを最後尾から
再スタートする方法はあるのでしょうか?
エスパーだが1〜最大IDまでのランダムなIDで出題してるの?
もしそうならORDER BY RAND()とか
そうです。
$id = rand(1, $count[0]);
としているのでハズレを引いていると思います。
ORDER BY RAND()調べてみます。
サンクス
>>170 >質問するときはDBMS名を必ず付記してください。
空き番号をつめるのはupdate書けばできるだろうけど、
自動採番が設定されてるカラムをupdateできるかどうかはDBによるんじゃね
自動採番号の設定値変える方法もDBによるんじゃね
DBMS?
でーたーべーすまねーじめんとしすてむ
ようは、つかってるDBの種類かけと
いろいろあるだろ、ORACLEとかMySQLとかACCESSとか桐とかファイルメーカーとか
だからそれDBじゃなくてDBMS
この場合のDBはDBMSの意味で使ってる
DBMSという用語が理解できるなら文脈でわかると思うが
DBMSとDBの区別がついてない人にとっては、DB=DBMSだからな
DBとDBMSという用語を明確に使い分ける必要はあんまりないんじゃない
あるんじゃないのかな。
アドバイス出来るほど理解出来ている人であればこの辺りは
誤解を招かないように意識して使い分けて書くべきだと思う。
文脈からも読めるかも知れないけど、ちゃんと言葉で明確に
区別するのに超した事はないよね。
スキーマとインスタンス、リレーションとテーブルとかと同様に
「似ているようで全然異なる、区別してもらわないと困る」類の
言葉だと思うよ>DBとDBMS
明確に使い分ける方がいいって意見はまあ納得できるんだが
会話は相手に伝わらないことには意味がないからな
>>173は確かにDBMSと書くべきだった
>>175は、
>>174がDBMSとは何かわからない人の発言かと思い、
あえてDBMSではなくDBと書いてある
DBという言葉は割と一般的に使われるが、DBMSという言葉は一般的ではないと思うんだ
そして一般にDBという場合、その多くがDBMSのことだったりすんだよな
俺は今のDBという言葉はDBMSを含んだ広い概念の言葉になってると思ってる
一般にDBという場合はドラゴンボールだろ
この板出来たときから居るけど、最初の1年くらいは
ドラゴンボールのスレが沢山あったんだぜ
実際の会話じゃないんだから
DBMSって言われて知らなかったら調べるだろ
相手をばかにしてるだけ
スルーで良いだろ
わざわざ相手にする必要なし
2003年に立ったドラゴンボールスレがまだ残ってるわけだが
>一般にDBという場合はドラゴンボールだろ
一般の友人のブログで「DBが〜…」とか書いてあって、「え!?なんでRDBMS知ってんだ!!」と驚いて本文を読んだらウボォー('A`)
>>179 お前がDBMSをDBと書くことによって相手に伝わってないじゃん
174で突っ込みもらってすら173のおかしさに気づけない時点で理解できてないことが見え見え
そうだな。DBMSがわかるやつが、あの文で通じないとはたしかに理解できてなかった
あと、おもったより、>今のDBという言葉はDBMSを含んだ広い概念の言葉になってると思ってる
が支持されてないようなので、今後は考えを改めることにするわ
いいかげんスレ違いなのでこの話題は俺はここまでにする
187 :
NAME IS NULL:2009/04/04(土) 23:48:34 ID:Zi6VTYVX
よろしくお願いします。
ある行の内容全て(主キーを除く)を、他の行へコピーしたいのですが、
どう書けばいいですか?
例)
ID | DATE | DATA
--+----------+-----
1 | 2009-04-05 | aaa
2 | 2000-01-01 | bbb
↑
ID=1のDATEとDATAの内容を、
ID=2のDATEとDATAへコピーしたい
理想の結果)
ID | DATE | DATA
--+----------+-----
1 | 2009-04-05 | aaa
2 | 2009-04-05 | aaa ←ID=1と同じ内容になる
(SQL文のイメージ)
UPDATE テーブル名 SET 【ID2の"ID"以外の全ての内容】 = 【ID1の"ID"以外の全ての内容】
サブクエリ
Oracleとかだと
update テーブル名
set (DATE, DATA) = (select DATE, DATA
from テーブル名
where ID = 1)
where ID = 2
って書けたりするけど標準SQLだと
update テーブル名
set DATE = (select DATE
from テーブル名
where ID = 1),
DATA = (select DATA
from テーブル名
where ID = 1)
where ID = 2
みたく書くしかないかな
190 :
187:2009/04/05(日) 00:34:23 ID:???
>>189 ありがとうございます。とても助かりました。
標準SQLですので、後者を使わせていただきます。
その解だとID毎に全部書かなきゃならんのだが・・
>>187 コピーする件数にもよるだろうけど、多くなければdeleteしてinsert
delete from テーブル名 where ID = 2
↓
insert into テーブル名 (ID, DATE, DATA)
select 2, DATE, DATA from テーブル名 where ID = 1
>187
MS SQLなら
update work
set [date] = w1.[date],
data = w1.data
from work,work w1
where work.id=2 and w1.id=1;
MYSQLは
UPDATE WORK, WORK W1
SET WORK.`DATE`=W1.`DATE`,WORK.DATA=W1.DATA
WHERE WORK.ID=2 AND W1.ID=1;
POSTGRESQLでは
update work
set "date" = w1."date",
data = w1.data
from work w1
where work.id=2 and w1.id=1;
おまいら家のPCにDB環境いくつある?
Oracle Express EditionとDB2 Express-C
何故そこにMS SQLの無料エディションが無い。
・会社で使ってないから
・Linuxに乗らないから
∧__∧
( ・ω・) Windows以外はいやDOS
ハ∨/^ヽ
ノ::[三ノ :.、
i)、_;|*く; ノ
|!: ::.".T~
ハ、___|
"""~""""""~"""~"""~"
>194
おれっくらいの達人になると脳内DBだぜ、
脳内DBは10行3列までしか格納できないのがちょっと不便。
九九も入らないなw
九九のDB作るには複合インデックスも必要だしね。
ににんがし〜
>>197 スレチだがDB2は日本では普及してるの?
SQLServerの元になったRDBだよね?
SQLServerの元はSybaseですがな。
DB2はIBM関係の仕事してたらまず間違いなく使うことがある
逆にIBMと関係ない仕事してたらまず間違いなく使わない
HiRDBと日立、Symfowareと富士通みたいなもんだ
そんなもんと一緒にすんなって怒られそうだな
>HiRDB
日立系の人から「使ってる?」と聞かれたことがあるけど、「知りません」って答えたら「そうでしょうね」と納得していたのが忘れられない。
うちは、日立の子会社だけど基幹は Oracle だし、
俺自身も使ったことないし。
富士通も日立も普通にオラクルだよw
有名で実績あるからオラクルのほうが入れやすいんだと思う
少々高くても金はあるところにはあるし。
しかしIBMはそういう場合でもDB2を入れてくる会社なんだぜ
210 :
なまえ:2009/04/06(月) 00:20:55 ID:???
SQLの基礎はIBMの研究所で確立されたと聞いたことがあるぞ
そうなると、DB2はもっとも由緒あるRDBMSといえるんじゃないかな
ま、由緒があるから機能や性能が優れてるとは限らんがw
>210
由緒はある、だが、パクって磨いて売りまくったのはオラクル。
よろしくお願いします。
初めてaccess触ってるもんでさっぱりです・・・
レコードを、起算日から終了日までの日数分出力したいのですが、どうすればよろしいでしょうか?
例)
ID data 起算日 終了日
--------------------------
001 A 20080101 20080110 ←10日分出力したい
001 B 20080201 20080220
(´・ω・`)…
>212
そのテーブルの日付範囲を条件にして他のテーブルから日付範囲分のレコードを取ってきたいってことか?
select 起算日−終了日 from テーブル where 起算日−終了日 = 起算日−終了日
でOK。
解説は↓↓↓↓↓がする
他のテーブル指定してねーじゃん
>>214 抽出元は、このテーブルです
1行目の起算日から終了日までだと、日数が10日あるので10行表示するようなイメージです
limitでいいじゃん
>>216 20080101
20080102
.
.
20080110
ってことか? 標準的なSQLでは無理。
まず、日本語で説明できるようになろうな。
>>218 やっぱ、ダメか・・・
ありがとうございました。他の方法を考えてみます
上司に説明してもらった方が解決しそう。
変数に代入して+1してけばいいんじゃないの?
BETWEENとかそういう話じゃなくてか
RDBMSによってはできるな。
accessはわからんが
テーブルをカラム A (ユニーク) でソートした時、A の値が 'HOGE' の行の
出現インデックスを取得するような SQL は書けますか?
先頭からループでブン回して出現位置を見つけるしかないんでしょうか?
Apache の Derby です。
>>225 'HOGE' が何行目にあるか? ってことかな?
ApacheのDerbyは使ったことないが、
SELECT count(*) FROM Table WHERE A <= 'HOGE';
でいけるんじゃね?
DBの統計情報を利用したいというように読める。
228 :
社内SE:2009/04/08(水) 23:05:12 ID:???
>225
SQL書くんのめんどいからヒント
ソート
行番号
'HOGE'指定
最小
を1個ずつクリアしていけOK。
俺っくらいのレベルになると脳内DBでサクッとできるんぜ。
脳内DBのテーブルは3列10行制限
DBでインデックスとゆう用語は勘違いされるからむ
ランクが知りたいんじゃないの?
・oracle11g
・あろテーブルで、複数のカラムで一つのIDを持っているんですが、
そのIDの重複の有無を調べるSQLを教えてください。
型は全てnumberです。
231 :
230:2009/04/09(木) 12:13:58 ID:???
勘違いしててすぐ解決しました。
文字化けが直らない。
疲れ果てて質問も出来ない。
いじょう
どのみちこのスレで文字化けの質問なんかしてもスレ違いだ
いじょう
DB2は迷ったらUTF8、他のDBもおすすめの日本語文字コードがあります。
235 :
NAME IS NULL:2009/04/13(月) 22:53:53 ID:z55NoKLw
達人の俺になんか問題を振ってくれ
age
逆に今時どのDBでもUTF8だろ
Accessとかならともかく
Accessは手軽にアプリケーションが作れるので気に入った。
JIS 第一なら概ねあいうえお順だから JIS 順ソートが仕様になってる所は
UTF-8 使えないんじゃないの。
今時の DB は UTF-8 でも JIS 順ソート指定とかできるんか知らんが。
UTF-8でSQLに渡してPHPから呼んで表に入れたら化けた。
SQLに渡したリストを表示するPHPは化けない。
化けてない方はブラウザもUTF-8で表示してる。
化けてる方はブラウザはEUC-JPで表示しててUTF-8に変更すると
SQL関係ない文字が化ける。
表作成のコードは一緒なのに。
もう嫌。
なんだよ SQL って・・・
IBMの研究所の偉い人が考えた言語
仮にMySQLならset names スクリプトの文字コード やっちゃえよ
243 :
239:2009/04/14(火) 14:12:12 ID:???
PHPファイル自体をUTF8で保存したら文字化け直った。
要するに文字コード変換一切せずに突っ込んでたって事じゃないか
∧∧
ヽ(・ω・)/ ズコー
\(\ ノ
、ハ,、  ̄
 ̄"
何にせよスレ違い。二度と来んなよー
where aaa<>'5'
と書くとaaa列がnullのレコードが取ってこれないのはどう理解しればいいですか?
納得いきません。
nullは'5'ではありませんので取ってくれよ、と思っています。
>>247 DBにおけるNULLの扱いを勉強しましょう。
>>247 null はどう評価しても null。つまり、true ではないから。
>249
あんがと。
もうひとつ質問
''(シングルクォート2連続)はnullと同じですか?
aaa is null
と
aaa =''
は同じですか?
>>250 同じ扱いのDBMSもあったような気がする・・・Oracleだったかな?
INSERT INTO ('')
INSERT INTO (NULL)
両者は同じになるのですが、どう理解しればいいでしょうか?
>>250 各RDBMSで挙動が異なる。
SQLの解説書によく出てくるよ。
>256
なるほど。
どおりで同じわけだ。
よくある質問1の日付が未来まである場合のテーブルで、
今日未満の最新レコードを抽出する事は可能ですか?
DATE型の大小関係で、「今日」という日付を使って
今日 <= MIN(DATE_column)
すべての日付の最小値をとり、今日を含む今日よりも新しい日付を抽出する。
between句について質問です。(初心者です)
code between '123456' and '123459' で範囲指定した検索を行うと
検索結果に code 1234 も含まれます。 なぜでしょうか?
また、数値型に変換して cast句を使用したのですが、code に全角数字が
含まれる為、SQLエラーとなりうまくいきません。
何かよい方法は無いでしょうか?
全角半角混在とは、、、
しょうがないから半角に統一するストアドファンクション作ろう
>>263様
ありがとうございます。
ストアドファンクションって何ですか?ってレベルなんですけど
調べてみます。
ちなみに、code には 「-」 も含まれます。。。。
>>262 >>1 まあ code 1234 が '123456'より大きく'123459'より小さいと判断されてるのだろう
文字列の比較ルールは処理系や文字コードによるのでこれ以上はなんともいえない
全角が入るって・・・エンドユーザの入力をそのままSQLに渡してるのか?
SQLインジェクションとか、別のとこで心配になってきたぞ。
ストアドで解決するよりも、ホストアプリ側でバリデーションすべきだと思う。
267 :
266:2009/04/15(水) 01:42:32 ID:???
・・・と書いてから気づいたが、既存のレコードが全角なのね、勘違いしてた。
まあ、既に入っちまったもんは仕方ないか。
>>262 の使ってるDBが何か知らんが、「照合順序」がキーワードになるんじゃないかな。
使っているDBはSQLSERBER2005です。照合順序をJapanese_binに設定しても同様にエラーがでます。。。
>>268 全角半角を区別したくないんなら、Japanese_CI じゃないのか?
質問です。
ISO規格のSQL(SQL-92)のみが使える機能を搭載したRDBMSはあるのでしょうか?
SASを使用しているのですがどうよらSQL-92が使える事は分かったのですが、各社の拡張機能をつい使ってしまう癖を直したくて質問しました。
よろしくお願いします。
本来のもの以外は全く使えないって正月番組の英語禁止ゴルフかよ
SQL Serverで
'1234' between '123456' and '123459' が真になるような
照合順序なんて無いと思うので、何かがおかしい
DBCC CHECKTABLEとかって2005でも実行できるのかな?
>>270 Oracleだとalter session set flagger=fullとかやるとチェックできる。
他のDBMSでも似たような機能はあるんじゃない?(知らんけど)
>>270 SQL92の良いリファレンスを買って手元に置く方が良いよ。
プロ野球養成ギプスじゃあるまいし、癖を直すにしても頭で
理解して直さないと意味がないでしょう。
でもちょっとチューニングしようと思ったら SQL92 じゃどうしようもならんよね。
277 :
270:2009/04/15(水) 23:33:11 ID:???
ご意見ありがとうございます。
参考にします。
質問です。
COLUMN Aの値がa1のところをa2に変えたいと思っています。
ただし制約があってCOLUMN AとCOLUMN Bでユニークなインデクスを作っているので
COLUMN Bの値がかぶらないようにチェックしないといけません。
COLUMN Bがかぶらない行だけを変える方法、あるいはCOLUMN Bがかぶる行を削除する方法を
教えてください。
testテーブル
aid|bid|value|ip|created
このようなテーブルから、
ipが同じ、かつ同じcreatedが同じ日付のものを重複として取り除き、
valueの平均を出したいのですが・・・
サブクエリを使えば、
SELECT bid, avg( value )
FROM (
SELECT *
FROM test
GROUP BY bid, ip, date( created )
) AS tmp
GROUP BY bid
のようにできるのですが、
サブクエリを使わずに実現する方法はありますでしょうか?
よろしくお願いします。
そのサブクエリ自体が間違っているような・・・
ipと日付が同じでvalueが異なる行があった場合は
どうするのだろうか。
>>279 select ip, date(created), avg(value) from test group by ip, date(created)
これで事足りるんじゃないの?
282 :
279:2009/04/16(木) 14:21:22 ID:???
>>280 説明が足りずすみません・・・
同じipで同じ日付ならば、時間が早いほうのvalueを使うほうにしたかったのですが・・・
SELECT bid, avg( value )
FROM (
SELECT *
FROM test
GROUP BY bid, ip, date( created )
ORDER BY created ASC
) AS tmp
GROUP BY bid
こんなかんじでしょうかね・・・
いろいろ間違ってるかもしれません;
283 :
279:2009/04/16(木) 14:24:53 ID:???
>>281 またまた説明が足りませんでした・・・
同じipで同じ日付を重複として取り除いたものから、
valueの平均をbidごとに集計したかったのです・・・
とりあえずそのサブクエリは文法エラーで評価出来ないと
言うことは意識しているかな。GROUP BYを使った場合は
無頓着に*は使えないよ。
あと「時間が早いほう」とは書いているけど、全く同時刻に
複数のvalueがある場合はどうなるのだろう。
最後に、やっぱりサブクエリ使わないと難しいと思う。
使えない理由がDBMSの仕様であるなら、DBMSの名前と
バージョンを書くべし。
サブクエリ使えないなら一時テーブル使えば?
達人の俺(まいど脳内DBの俺)が教えてやろう
>278
そーゆうとき、まずUPDATEするまえにDECODE関数を使って'a1'を'a2'に変えた表を作る
その表と元の無編集の表をキーで付き合わせればいいんだよ。
ポイントはdecode、not exists、from句に元の無編集の表と編集した表だ。
最終的にはDML一発でやりたい事ができるぞ。少なくとも俺の脳内では。
>279
達人の俺がパッと見た感じではごく普通の難易度に見えるが
俺の脳内DBは3列10行までしか格納できないのでパス。
aid|bid|value|ip|created
↓
bid|ip|created
なら教えてあげてもいい。
達人の脳内 DB はヒープどれくらい割り当ててるんですか?
俺っくらいの達人になると
ひーぷ()笑
だ。決してヒープという用語を知らないわけではないぞ。
良く解りませんがヒップへのアクセス権はguest可です
292 :
278:2009/04/17(金) 02:44:23 ID:???
達人様ありがとうございました。
decodeが使えなかったのでcaseを使って実現しました。
結局様々な事情で実装は別の方法を取ったのですが
勉強になりました。
公開したらヒップに SQL Injection 喰らいました。
アクセス権はつけてるけどINSERT権限はつけてないから無問題
295 :
DBの達人:2009/04/17(金) 05:56:38 ID:???
おはよう!
296 :
NAME IS NULL:2009/04/17(金) 08:26:10 ID:uJNeHSTZ
DBからデータを取り出すときに、
今週のものだけを取り出すにはどのようにすればよいのでしょうか?
7日以内ではなく、「今週」のものなのですが。
プログラムなどで、今週の始めと終わりの日付などを計算する必要があるのでしょうか?
SQLで可能ならば教えてください。
また、カラムに更新日時が記録されているとき、
たとえば3日以上j更新されていないものを取り出すにはどのようにすればよいのでしょうか?
初歩的なことかもしれませんが、どうかお願いします。
>>296 今週の日曜日から土曜日で、
WHERE date_column
BETWEEN CAST(NOW()-CAST(EXTRACT(DOW FROM NOW())||' day' AS INTERVAL) AS DATE)
AND CAST(NOW()-CAST(EXTRACT(DOW FROM NOW())-6 || ' day' AS INTERVAL) AS DATE)
298 :
297:2009/04/17(金) 10:07:54 ID:???
見逃してた。下の質問だけど、更新日時が今日より3日以内って意味かな?
WHERE date_column BETWEEN CAST(NOW()-INTERVAL'3 days' AS DATE) AND CAST(NOW() AS DATE);
299 :
297:2009/04/17(金) 10:28:50 ID:???
逆か
>>298 WHERE date_column NOT BETWEEN CAST(NOW()-INTERVAL'3 days' AS DATE) AND CAST(NOW() AS DATE);
300 :
296:2009/04/17(金) 15:48:09 ID:???
普通date_truncとか類似の関数で週単位の切り捨てもできるだろ
302 :
達人:2009/04/17(金) 23:06:00 ID:???
俺が出るまでもないな。
いまだに達人と聞くと、シューティングを思い出してしまう
304 :
NAME IS NULL:2009/04/18(土) 03:15:53 ID:AF1CyfHl
社員(名前 char(32),社員番号 int primary key)
個人情報(社員番号 int primary key,年齢 int,支店番号 int)
という2つのテーブルがあるとき、制約条件として
foreign key 社員番号 references 社員
というのを個人情報テーブルに追加した方がいいですか、それとも
foreign key 社員番号 references 個人情報
というのを社員テーブルに追加した方がいいですか?
社員番号がkeyなので社員テーブルを参照するのがいい。
つまり前者の制約でいいと思う。
でも、支店番号は社員テーブルにあったほうが良くないか?
一つのファクトは同じテーブルに収めろよ
>>304 そのテーブルの関係が1-0か0-1かによって決まる。
どっちかわかっていないなら付けられない。
1つのテーブルに纏めるべきだとは思うけど、
参照制限をかけたいがためにわざと別テーブルにしてる・・・とかか?
オッス達人だ。
>304
ある社員の
@名前はあるが、、年齢と支店番号がない。
A年齢と支店番号はあるが、名前がない。
どっちがイイのよ?
なんか変なのが居ついちゃったな
つか、それSQLの話じゃないし、設計の話はスレ違いだ
312 :
NAME IS NULL:2009/04/19(日) 05:12:30 ID:gQJBptjI
テーブルのカラム名でDATE(もちろん意味は日付です)というのを使いたいんですが、DATEというデータ型とかぶってしまいます。
プロの皆さん方は、日付という意味のカラム名はどうされてますか?
前になんか付ける。更新日ならUPD_DATEとか。
つかそれもこのスレじゃないな。
314 :
NAME IS NULL:2009/04/19(日) 05:53:22 ID:gQJBptjI
ついでに後1個だけ。
カラム名は、大文字も小文字も区別されないと思っておいたほうがいいですよね?
dbmsによる
>>314 大文字か小文字だけを使うように設計するべき。
Oracleなら全部大文字、MySQLやPostgreSQLは小文字って感じの規約が多いかな。
一応理由があって、Oracleは内部の情報としてカラム名やテーブル名を
大文字で管理してるから、大文字で最初から書いた方が効率が良くて、
逆にMySQLとかPostgreSQLは小文字で管理してるから逆になる。
ただどっちにしろSELECTとかINSERTみたいなコマンド部分は
大文字で書くのが一般的。
ただ、厳密な意味で大文字小文字を区別するってDBMSはあんまり無いと思う。
アだとジャガイモが在庫切れで非表示にしたい料理の他に
ジャガイモを元々使わない料理も出てこなくなる
技術系の質問スレって「そんなDB使う奴がバカ」「そんなテーブル設計する奴がバカ」
みたいな、何の解決にもならない根本否定するだけのスレをよく見掛けるけど、ここは
それがあまりない。おまいら「DB屋は今そこにあるDBを何とかしなきゃいけない」って
よく分かってるプロだなーといつも感心する。
ひんと: スルー力
322 :
318:2009/04/20(月) 10:47:49 ID:???
問題文3行目の「使用する食材全てについて在庫が〜」というのを見逃してました。
しっかり問題文を読まねば・・・・・・
解説ありがとうございました。
>>317 ""でくくると大文字小文字を区別するけど、くくらないとすべて小文字扱いになるよ、PostgreSQLは
他のは知らないけど、似たようなもんじゃないのかなあ。
>>321 何度見ても「するーか」と読んでしまう私のSELECT文
ユンカース
スツーカ
暴力二男
達人だ。
>312
「HIZUKE」または「HIDUKE」でOK。
ダサくても大規模プロジェクトでこんな名称使ってるとこたまにある
「〜_DATE」でOK。
よくあるのが
「INS_DT」「INP_DT」
「DEL_DT」
「UPD_DT」
運用日付なら「UNYO_HIZUKE」でオッケー牧場。
意味の無い返答はやめていただきたい。
330 :
NAME IS NULL:2009/04/21(火) 02:38:25 ID:6SQGommS
MySQLを使っているのですが、
ifnullとcaseの違いについてわからないことがあります。
以下のようなSQLファイルを作成しました。
-------------------------------------
~$ cat hoge.sql
use test;
drop table if exists hoge;
create table hoge (id int, no int, data text, primary key(id, no));
insert into hoge values(1, 1, 'aaa');
insert into hoge values(1, 2, 'aaa');
insert into hoge values(1, 3, 'aaa');
insert into hoge values(2, 1, 'bbb');
insert into hoge values(2, 2, 'bbb');
select ifnull(max(no)+1, 0) as no from hoge where id=3;
select (case when no is NUll then 0 else max(no)+1 end) as no from hoge where id=3;
-------------------------------------
これを実行してみたところ、以下のようになりました。
-------------------------------------
~$ cat hoge.sql | mysql -u root --table
+----+
| no |
+----+
| 0 |
+----+
+------+
| no |
+------+
| NULL |
+------+
-------------------------------------
なぜ、ifnullの場合は0なのに、caseの場合はNULLなのでしょうか?
よろしくご教示お願い致します。
いや単に前者がnull+1でnullになってるからだろ
333 :
>>330:2009/04/21(火) 03:39:55 ID:6SQGommS
>>331 >.332
本当にありがとうございました。
334 :
sql:2009/04/21(火) 05:28:21 ID:???
select distinct col1, col2, col3 from tablename;
とやると全行表示されるがこの件数だけを取得したい場合は一体どうかけばいいですか?
標準ではないが DB によっては limit 20 とか fetch first 20 rows only とか
追加で書けたりする。DB の SQL リファレンス参照。
select count(*) from tablename group by col1, col2, col3;
じゃないの?
337 :
336:2009/04/21(火) 06:20:06 ID:???
寝ぼけてるな俺・・・
select count(*) from (select distinct col1, col2, col3 from tablename);
あ欲しいのは件数か。「この件数」→「特定の件数」と勝手に脳内補完してしまった、失礼。
339 :
sql:2009/04/21(火) 06:43:13 ID:???
>>337 oracleでは動くのですが、MySQLでは動作しません。なんか違うんでしょうか?
ERROR 1248 (42000): Every derived table must have its own alias
>>339 エラーメッセージの通りじゃないの?(知らんけど。)
select count(*) from (select distinct col1, col2, col3 from tablename) a;
341 :
sql:2009/04/21(火) 07:32:37 ID:???
MySQLには「SELECTしたものを、n件まで表示する」というのがあって便利だった。
何でもう過去形なんだよw
それ SELECT TOP n とはどう違うの?
limit x となら完全に同じ。
さらに、limit x, y で開始行まで指定することもできて便利・・・だった
>>343 商用でMySQLという案件が無かったから。
自宅で試す程度で、あまり自信が無くてね。
>>343 そりゃ、ORACLEさんに買われて、お先真っ暗ですから
>>346 > 商用でMySQLという案件が無かったから。
OracleのSun買収でこのあたりどうなるかね?
共にSQLを拡張して互換性を取るような動きになると、ありがたいんだけども。
IBM「ちょwwwwwwwwおまwwwwwwwSQL作ったの俺たちのとこの博士だしw」
352 :
達人:2009/04/21(火) 21:47:59 ID:???
グルーピングは体で覚えるんだ
ロールアップまで使いこなせるようになるとGood
お偉いさん達は集計、小計、合計、率、比率、が気になってしょうがない生き物だから
>>352 特に前年比がね〜
めんどうなんだよ!
頭の体操になるけどね
orderみたいに、
そのままカラム名に指定するとエラーになってしまうカラム名を知りたいのですが、
どこかまとめてあるところご存じないでしょうか?
ここで質問していいんでしょうかね;
マニュアルどぞー
>>354 なんとなくわからないけ?
select *,order,where,select,group ,top,3 from from where where = order order by by
みたいな事できたらキモイでしょ
357 :
354:2009/04/22(水) 07:39:40 ID:???
>>355 すみません・・・
マニュアルのどこらへんに書いてあるんでしょうか?
>>356 orderとかselectはまだわかるのですが、
keyとかでもエラーになったので・・・
ちなみにMySQLです。
>>357 どこに書いてあるかも聞かないと分からないとは・・・・(驚愕)
自分が聞きたいことが何なのかが分からないことはよくある。
予約語、という言葉を知らないと探しにくいかもなあ
そんなことより僕と踊りませんか
予約語でも”で括ると使えちゃったりするかも
``じゃなくてか
(''ω'')ふひひ さーせん
いいから舐めろ
どのていど消費されるかわからない主キー(オートインクリメント)のデータ型を
とりあえず全部BIGINTにしておくというのは、
なにかデメリットはありますか?
ほかにもLONGTEXTなども、多めに取っておくと何か不都合があるのでしょうか?
>>367 MySQLだよね?
BIGINTのデメリットは消費データ量が4bytesから8bytesになること
LONGTEXTはMEDUIMTEXTにくらべてカラムヘッダが2bytesから4bytesになる
まあ2bytesとか4bytesをケチケチしなくていいと思う
こういうのってできる?
○ テーブル1
1 aaa
○ テーブル2
aaa bbb
aaa ccc
○ テーブル3
bbb xxx
bbb yyy
bbb zzz
ccc kkk
○ 結果
1 aaa bbb xxx
- --- --- yyy
- --- --- zzz
- --- ccc kkk
>>369 joinの左外部結合(右外部結合)
該当する行にはデータが、該当しない行にはNULLが入る。
「---」というデータが作りたいなら、置換してください。
371 :
369:2009/04/23(木) 12:50:14 ID:???
>370
--- はNULLの意味です。
LEFT OUTER JOINだと、
1 aaa bbb xxx
1 aaa bbb yyy
1 aaa bbb zzz
1 aaa ccc kkk
になりませんか?
重複している行をNULLなどにできないのでしょうか?
- --- --- yyyだけ見ると1 a bbb yyyなのか1 a ccc yyyなのか
わからないからねぇ。
>>369の結果テーブルは順序を持っている事になるから、結構
難しいと思う。
うーんお手上げです。
1回限りのデータなら、Excel使って手でデータ作った方が早いと思います。
>>369 問題を単純化するために、
1 aaa
1 bbb
2 ccc
2 ddd
2 eee
のテーブルを
1 aaa
- bbb
2 ccc
- ddd
- eee
と表示する方法から考えてみたら?
SQLでできないこともないだろうけど、俺ならホストアプリ側で制御かな。
ホストアプリのメモリで扱いきれないデータ量なら、表示用の別テーブルを作成する。
>369
達人の出番だなw
>>369 row_number()が使えるなら
1じゃなかったらnull、的な感じでいけると思う
row_numberでできるけどSQLでやることじゃないよなw
確かにw
やりたきゃ取得した側でやれって話だな
379 :
達人:2009/04/23(木) 21:46:19 ID:???
まいど、達人だ。
俺の出番か、まかせとけ
@.外部結合で表示(
>>371の表ね)、ソートし、各行に一意なID(オートナンバーとかROWNUMでいい)をふる。
結果は以下(列名を左から順に"ア","イ","ウ","エ","オ"とすし、このレコードセットを"ViewA"と名づけよう)
ア イ ウ エ オ
1 aaa bbb xxx 1
1 aaa bbb yyy 2
1 aaa bbb zzz 3
1 aaa ccc kkk 4
A.ひとつ前の行と比較して表示するか判定する。具体的には以下。
SELECT
DECODE(ZZZ.ア,(SELECT ViewA.ア FROM ViewA WHERE ViewA.オ-1=ZZZ.オ),NULL,ZZZ.ア) AS ア
,DECODE(ZZZ.イ,(SELECT ViewA.イ FROM ViewA WHERE ViewA.オ-1=ZZZ.オ),NULL,ZZZ.イ) AS イ
,DECODE(ZZZ.ウ,(SELECT ViewA.ウ FROM ViewA WHERE ViewA.オ-1=ZZZ.オ),NULL,ZZZ.ウ) AS ウ
,DECODE(ZZZ.エ,(SELECT ViewA.エ FROM ViewA WHERE ViewA.オ-1=ZZZ.オ),NULL,ZZZ.エ) AS エ
FROM ViewA ZZZ
ORDER BY 1,2,3,4
脳内ではできたが、実際にSQLは叩いてないからミス構文エラーかもしれん
少なくともヒントにはなっただろw
天才現る
select '1', 'aaa', 'bbb', 'xxx'
union all
select null,null,null,'yyy'
union all
select null,null,null,'zzz'
union all
select null,null,'ccc ','kkk '
;
381 :
達人:2009/04/23(木) 22:01:35 ID:???
へのつっぱりは、いらんですよ!!
>380
おしい FROM DUAL
Oracle厨房の心のよりどころDUALw
買収されたから、MySQLもDUALが強要されるように改悪されるかもしれんな。
SCOTT, TIGER が入る日も近いな。
まぁ、別にいいんじゃない?困る人は少ないと思うし
こうか。
(テーブル1を(a, b)、テーブル2を(b, c)、テーブル3を(c, d)とする)
select case when RN1 = 1 then a else null end,
case when RN2 = 1 then b else null end,
case when RN3 = 1 then c else null end,
case when RN4 = 1 then d else null end
from (select a,
b,
c,
d,
row_number() over (partition by a order by a,b) as RN1,
row_number() over (partition by a,b order by a,b,c) as RN2,
row_number() over (partition by a,b,c order by a,b,c,d) as RN3,
row_number() over (partition by a,b,c,d order by a,b,c,d) as RN4
from テーブル1
inner join
テーブル2
using (b)
inner join
テーブル3
using (c)
)
;
387 :
達人:2009/04/23(木) 23:08:45 ID:???
>386
Good。センスいい。
しかし、本当にSQLに向いてない仕様だなw
達人の
”ひとつ前の行のレコードと比較する”
ってテクはSQLでやれる事の可能性が広がったわ
ってかホントにできんの?
>>389 サブクエリに任意に連番を振ることが可能なら、可能だとは思う
思うが、今回の質問のようなものは俺ならやらない
グループインジケーションはクライアントアプリの仕事だ
ちゃんとしたレポートツールとかなら、そのぐらいの機能は大抵あるしな
しかし、SQLの規則では、order by はサブクエリには書けなかったと思った
なんで中間テーブルなりビューなりを用意しないとダメじゃないかな
まあ、このへんはDBMSによって変わってくるだろうな
partitionは使ったことない(というか使えるDBMS使ってないw)からよくわからん
>>389 やりたい事がそれであればlag関数でスッキリ実現可能。
ただ
>>369をSQLで実現しようとすべきでは無いってのは自分も同意
まぁ、SQLでやらなきゃならない事情があったんだろ
いろんな事情があるからな。
アプリ改造したいがソースを紛失したとかw
んで、SQLだけは外出ししてあったから直せるはずだろ、とか
テーブルの中にSQLを格納してあってSQLでSQL文を取り出すシステムとかもあるんだぜ
(データディクショナリとかそーゆーのじゃないくて)
mysqlを触ろうとしてるんですが、
DELETE FROM xxx WHERE aaa= bbb AND ccc = (SELECT MIN(ccc) FROM xxx WHERE aaa= bbb)
↑を実行したらエラーになりました。
ググったら「mysqlは副問い合わせが出来ない」って出てきたんですが
こういう場合、mysqlではどのようにやるのが常套手段なんでしょうか…
副問い合わせの結果をwhileやforeaceで回せばいいのでは
>>394 どもです…ほんとに簡易sqlって感じなんですねぇorz
>>395 version5.xでサブクエリ周りに機能追加なかったけ?
MySQL(InnoDB)をperl-DBIで使ってます。
複数テーブルにわたる更新の場合はオートコミットを切ってトランザクション下で処理するんですが、
これはテーブルロックがかかってる状態ですよね?
ほかのユーザーは該当テーブルについてリードはできるが更新はできない状態なんですよね?
しかし、トランザクション中でもテーブルに書き込みできてるんですが、これはテーブルロックじゃなくて、行ロックを勝手にしてくれてるって事で良いんでしょうか?
InnoDBは行ロックだよ
400 :
NAME IS NULL:2009/04/28(火) 02:18:37 ID:aHnBfSXl
株価データをDBに入れて保持してるんですが、今は1つの大きなテーブルに入れてます。
(trade_date DATE, stock_name int, market_type int, open double, close double)
これ1個のテーブルで3000万件くらいになってます。しかも最近データの増える速度がどんどん
速くなってきた。
なにをやるにも時間がかかるので、テーブルをわけてしまおうかと思っているのですが、
銘柄単位でテーブルを分けるとテーブルが5000個とかになるし、
日にちでテーブルを分けると10000個近くになります。
両方をやると、データの冗長性があまりにもひどい気がします。
銘柄ごとでも日にちごとでも検索しまくるのですが、こういう場合どういう
形のテーブルにしておくのがよいでしょうか?
>>400 カラムの意味と関連するテーブルのスキーマも見ないとわからん
あとテーブル設計に関してはスレチじゃないか?
402 :
401:2009/04/28(火) 03:05:34 ID:???
403 :
NAME IS NULL:2009/04/28(火) 03:12:20 ID:aHnBfSXl
すいません、そっちで聞いてみます。
404 :
NAME IS NULL:2009/05/09(土) 12:43:28 ID:JoxlLn6y
DELETE * FROM WHERE NAME LIKE "%ii%";
みたいなことをやりたいのですが、DELETEにはLIKEは使えないようなので、
ほかにやり方がないかと思っています。
どうかやり方がないか教えてください。
使えるだろ・・・。どこの DB だよ?
>DELETE * FROM WHERE NAME LIKE "%ii%";
そもそもSQL文が間違ってないか?
DELETE文は「DELETE FROM (テーブル名) WHERE (評価式)」だぞ
DELETE * って DELETE id,nameとかできたら便利だなw
*もいらなく無いっけ?
DELETEする前に、まずSELECT文としてきちんと評価されているかを確認するのが鉄則。
DELETEしたくない行を消したことが何度あったことか_| ̄|○
まあSELECTで表示させてから、SELECT * をDELETEに差し替えるわな
updateにwhere付け忘れた
あああああああああああああ
(*´Д`)⊃ROLLBACK
AUTO_COMMIT がえし!
AccessではDELETE文に*つける。
SQL SERVERの共通テーブル式でノードを辿る再帰クエリーを作成しているのですが、
ルートがループしているところがあります。
ループしている部分のデータの重複を避けたいのですが方法はありますでしょうか?
UNIONやEXCEPTを使用しようと思ったのですがダメでした。
Accessは削除クエリ作ると裏で勝手にDELETE *のSQL文が作られるけど
SQLを手打ちするなら*なしでも普通に通るよ。
漠然とした質問で申し訳ないんですが、効率のよいSQLの書き方について勉強するためのよい本や資料はどのようなものがありますか。
たとえば、
select users.* from users, groups where users.group_id = groups.id and group.name = 'Admin';
と
select users.* from users inner join groups on users.group_id = groups.id where group.name = 'Admin'
と
select users.* from users where users.group_id in (select id from groups where name = 'Admin')
のどれがいちばん効率がいいのかということを、自分で実験して調べるのもいいですけど、先人の知恵を使って勉強したいです。
なにかお勧めの本などを紹介してください。
あなたの言う効率とは?
単純に実在するテーブルで時間計測してみるとかでいいんじゃない?
RDBMSごとの得意・不得意よりも、稼働しているDBの構成に大きく依存する。
しかも正解が他で通用するとも限らない。
普遍的に通用するセオリーみたいなのってほとんどないからねぇ
どこでも通用するものだけに搾ったら本一冊も書けないんじゃない?
>>417 他の人も言ってように、DBMSやその構成に依存するから、コレってものは知らないなぁ。
昔はどこかのサイトに「こう書け」って事例があったよ。
でも、今となってはほとんど通用しないのじゃないかな。
例えば
>>417の3つめのクエリは遅いクエリの代表みたいなものだったけど、
今じゃどれも一緒。IN述語の処理そのものが速くなったというよりも、
1つ目もしくは2つ目に書き換えて実行している。と考えた方がいい。
一番参考になると思うのは、実行プランを出力させてみること。
実際の処理時間だけを比較してみるのではなくて、
クエリがどのような手順で実行されるのかをも確認する。
そのうちに、どう書けば効率のいいクエリになるのかわかるようになる。
結合(JOIN)するときはテーブルの行数が、少ない行数同士、片方が多い、両方多い等によっても
結合方法などの実行プランが変わるから、実データでいろいろやった方がいい。
DB2では人間が書いたSQL文が、RDBMSで自動的にどう解釈されているかが分かるログがあるよ。
単なるJOINであっても、内部的に挙動が異なる事があるとか、意外と考えさせられた。
今の自分は、自動化できる部分は全部自動化でいいと思ってる。
ってか統計とってチューニングしながら実装しろよ
よろしく、メガドック
425 :
417:2009/05/12(火) 00:24:43 ID:???
みなさん、いろいろありがとうございます。
結局、これといった資料はないというのが実情なんですね。
>>421 >例えば
>>417の3つめのクエリは遅いクエリの代表みたいなものだったけど、
>今じゃどれも一緒。IN述語の処理そのものが速くなったというよりも、
>1つ目もしくは2つ目に書き換えて実行している。と考えた方がいい。
ほしかったのはまさにこういうことが載っている本です。
explain でいろいろ調べたりするする前に、こういった先人の知識をあらかじめ知っておいた方がいいだろうと思ったのですが。
残念です。
そのへん知りたかったら
Oracleコンサル雇うしかないかもね
飯の種だからね
>>417 かなり昔の本なら、プログラマのためのSQL って本があったんだが
いかんせん古い
最近でその系統なら、アート・オブ・SQL とかどうだ
というか、スレ違いだな、そういうスレなかったか?w
>>417 最適化のノウハウの背後にある理屈を理解したいのであれば、英語
ず大丈夫ならRaghu Ramakrishnanの教科書がおすすめ。
オプティマイザも含めてデータベースに関わる理論を広く薄く網羅
した本なので、一冊持っておくとデータベースのある部分について
理屈を理解したくなった時にとっかかりとして大変便利なはずです。
429 :
NAME IS NULL:2009/05/13(水) 07:18:50 ID:R4pv+GIi
最近SQLの勉強を始めた者です。
VIEWって何のためにあるのかわかりません。結局いくつかのテーブルから自分の見たいカラムを
取ってきてJOINしているだけ(だからSELECTで同じことができるんじゃないか)という感じがするのですが、
VIEWの存在意義って何ですか?どういうケースで使うべきでしょうか?
俺的には、ワンクッションおけるってのが大きい。
Table A と B から View_C を作ってるとして、
アプリの方で、Select * From View_C としてるとする。
後で変更の必要があり、Table D と E から View_C を作ることに
なっても、アプリの変更はいらないから。
VIEWしか見れないユーザーであっても、テーブルの特定の行をいくらでも見れる。
(UPDATEやINSERTは不可)
これが大きな利点であると思います。
前スレより転載(VIEWの利点・欠点)
734 名前:NAME IS NULL [sage] 投稿日:2009/02/05(木) 21:55:47 ID:???
>>731 こんなもんかな?
利点:
・クエリが(一見)単純になる
・あらかじめパフォーマンスチューニングしたVIEWを定義することで
あとから書くクエリではパフォーマンスを考慮しなくて良くなる(場合がある)
・行や列ごとにセキュリティかけたい場合に使えたりする
欠点:
・あとからロジックを追うのが面倒(な場合がある)
・あとからパフォーマンスチューニングするのが面倒(な場合がある)
433 :
NAME IS NULL:2009/05/13(水) 21:22:02 ID:raTYNme4
質問させてください。
複合インデックスを作成する際のキーの順番って関係ありますか?
またその場合はカーディナリティの高い順にするべきでしょうか?
よろしくお願いします
>>432 利点の上2つは労力全然減ってないように思うけど
VIEWのSQL考えるかソースに書くとき考えるかの違いだけであって
>>433 カーディナリが高い順が一般的だが、
それがパフォーマンスに影響するかどうかはDBMSによるかな。
なかにはOrcaleのCompress索引のように第1キーのカーディナリが
極端に低い場合専用の索引があったりします。
436 :
433:2009/05/13(水) 22:50:51 ID:raTYNme4
>>435 ありがとうございます。
もう1つよろしいですか?
order byで使用する項目も基本的にはカーディナリティ順で良いのでしょうか?
datetime型を想定しています。
すいません。書き忘れてました。
DBMS:MySQL5
です。
437 :
NAME IS NULL:2009/05/13(水) 23:28:06 ID:R4pv+GIi
SELECT * FROM A,B WHERE 条件;
と
SELECT * FROM A INNER JOIN B ON 条件;
って同じですか?
違います。
439 :
NAME IS NULL:2009/05/13(水) 23:39:24 ID:R4pv+GIi
ありがとうございます。
どっちのクエリも、AとBの積を求めて、そこから条件を満たすレコードだけを
残すから同じ結果になりませんか?
>>438 where条件で外部結合した場合、評価や結合順序で結果が変わるってのは聞いたことがあるんだが
内部結合でも同様のことが起こりえる?
結果の問題じゃなくて内部の動作の問題だっていうなら、
オプティマイザ次第な所があると思うんだ
>>437の最初のSQLの「条件」と後のSQLの「条件」が同じなら
そもそも前者は結合してない
「条件」は同じって前提でしょ?(A.ID=B.IDとかで。)
前者は結合してないってどういう意味???
443 :
441:2009/05/14(木) 21:45:27 ID:???
ああ間違えた。忘れてくれ。
結論:
>>437は、「条件」が内部結合条件であるとき、
・結果は同じ
・実行速度は違うかもしれんし同じかもしれん(オプティマイザ次第)
445 :
440:2009/05/14(木) 22:22:07 ID:???
>>441,443
条件式の内容が書かれてないから、必ずしも結合に関する条件を
書いてあるというわけじゃないかもしれないがな
>441は直積は結合じゃないって言いたかったんじゃないかと思ったが
前者は直積とったテーブルをフィルタしてる
後者は条件に従った結合をする段階でフィルタする
そういう意味で結合してない、じゃないのかな
ただ、実際はオプティマイズ入るから直積とったようなワークなんぞつくらんだろうし、
内部結合においては同じ条件式なら同じ結果になる気がするんだが...ならない例があるかな?
初心者が読んだらいいようなサイトと本を教えてください。
>>438の反応は、
結果は同じでも、そもそもそこに書いてあるSQL文は「違います」
というネタ的回答だと流してたわ。
SQL文が違うんだからDBMSによっては
実行プランが異なる可能性もあるし、
実行プランが同一でもその作成過程が異なる、とかの
厳密な意味での「違います」だととったな、俺は。
あと、質問の内容からすると初心者っぽいから、
「結果が同じだからって、短絡的に同じだと思うなよ」と諌めたかったんでは。
450 :
NAME IS NULL:2009/05/15(金) 09:56:31 ID:8Je7scRL
sqlStr = "select * from t_member where member_id = ○○";
↓OR
telephone1 = ○○";
これが出来るSQLを教えて欲しいです。
451 :
NAME IS NULL:2009/05/15(金) 11:00:39 ID:8Je7scRL
単純に
select * from t_member where member_id=○○ or telephone=○○;
でいいのかな??
アプリ側の実装の問題では?
アプリが何かで答えは変わるな
454 :
NAME IS NULL:2009/05/15(金) 14:05:47 ID:8Je7scRL
javaでアプリを作っています。
DBはMYSQL5.0でnetbeansを使用してます。
((レンタルテーブル))
レンタルID PRIMARY KEY,
インベントリID FOREIGN KEY
((インベントリテーブル))
インベントリID PRIMARY KEY,
映画ID FOREIGN KEY
((映画テーブル))
映画ID PRIMARY KEY
上記のようにレンタルテーブルはインベントリテーブルを、インベントリテーブルは映画テーブルをリファレンスしている場合に、
最も人気のある(レンタル数の多い)映画名を抜き出したいです。どのようなサブクエリを書けばいいでしょうか?
457 :
456:2009/05/18(月) 18:31:02 ID:???
すみません
上記の問題については出来ました。取り消します
TSUTAYAの中の人だったら嫌だなw
実際ML見てるとこれ業務そのものじゃないかなぁって質問あるし
あながち無いとは言えん
460 :
NAME IS NULL:2009/05/21(木) 01:19:22 ID:216X3HC3
左外結合 右外結合 ってそれぞれ何と読むんですか?
左外部結合、右外部結合のことみたいですが、買った教科書には上記のように記述されていました
もう1つ、左、右外結合はどのようなところで使うのでしょうか?
概要はわかったのですが、あまり使われないような気がします・・・
よろしくお願いします
sage忘れました すみません
ダメだゆるさん
使いどころがわかりやすいよう、業務に即した例を挙げると、
勇者テーブル
・勇者ID
・勇者名
勇者が覚えた魔法テーブル
・勇者ID
・魔法名
というテーブルがあったとする。
「勇者名」と「それぞれの勇者が覚えている魔法の数」を知りたい場合、
内部結合だと勇者が魔法使いならいいが、勇者が戦士だった場合魔法を1つも覚えていない。
すると一覧には、戦士は名前自体出てこないことになる。
外部結合であれば、戦士であっても名前だけは出てくる。
ありがちな業務だな。
どんなシステムでもその2テーブルは外せないよな
>>460 ひだりがいぶけつごう、みぎがいぶけつごう
>>460 そんなしょうもない教科書は捨てて他のを買った方がいい
ちょっと今1週間習ってて不安があるので質問です
oracleでSQLを勉強してるんですが
いまいち覚えられてない・・・
どれをやるにも見なきゃ出来ない。
今のレベルはこういう場合は確かこれとこれを使うんだよな・・・くらい。
シルバーの本を借りたんだがやったことではあるんだが応用?見たいな感じで
さっぱりすぎてへこんだ
いろいろ遊んでればそのうちに覚える
仕事でやってれば自然と覚えるよ。
471 :
NAME IS NULL:2009/05/22(金) 02:03:38 ID:MrqDSeOc
PostgreSQL でプライマリキーで検索かけてるのに、インデックススキャンになりません。
現在 100万行チョイ入ってるテーブルで、こんなインデックスになってます。
Indexes:
"txxx_pkey" primary key, btree (xxx_id)
explain してみると以下の通りインデックスが使用されないようです。
# explain select * from txxx where xxx_id=100000;
QUERY PLAN
--------------------------------------------------------------
Seq Scan on teditlog (cost=0.00..49310.86 rows=1 width=193)
Filter: (xxx_id = 100000)
(2 rows)
実際に select すると秒単位で時間がかかります。
インデックスを使用させるにはどうしたらよいでしょうか?
472 :
471:2009/05/22(金) 02:11:25 ID:???
>>471 の explain 結果のテーブル名が生のまま出ていましたね。
teditlog は見なかったことにして、txxx と読み替えてください。
追加情報ですが、xxx_id は BIGINT で、おおむね連番のシーケンス番号が付いています(たまに歯抜けになります)。
で xxx_id は、他テーブルから外部参照されています。
といった感じですが、インデックスが使用されない原因になっていそうでしょうか。
473 :
471:2009/05/22(金) 02:52:55 ID:???
すみません、自己解決です。
該当カラムが BIGINT なので、検索したい値も BIGINT にしなくてはいけないようです。
つまり、
# explain select * from teditlog where elid=cast(100000 as bigint);
QUERY PLAN
--------------------------------------------------------------------------------
Index Scan using txxx_pkey on txxx (cost=0.00..3.04 rows=2 width=192)
Index Cond: (xxx_id = 100000::bigint)
(2 rows)
ということらしいです。
単に 100000 と書いただけじゃ BIGINT とは扱ってもらえないんですね・・・
バージョンを確認したら PostgreSQL 7.4.7 なんですけど、新しいのだと改良されてたりするんでしょうか。
ところでこれにちなんだ追加質問ですが、列挙した値をまとめてキャストする方法ってあるでしょうか。
たとえば
select * from txxx where xxx_id in (10000, 20000, 30000)
なんてやる場合、(10000, 20000, 30000) の全部の値を BIGINT にキャストしたいです。
(CAST(10000 AS BIGINT), CAST(20000 AS BIGINT), CAST(30000 AS BIGINT)) みたいにしないといけないでしょうか。
>>471 8系だと型が完全一致しなくてもインデックス使うみたいだよ
475 :
NAME IS NULL:2009/05/22(金) 13:48:07 ID:BGl6oKa6
>>468 シルバーでSQLだと9i?
状況が許せば10gの方がいいと思うけど。
自分的には「現場で使うSQL」(だっけ?)がお勧め
最初うちは、考える+本を見るの繰り返しになるのは
しょうがないんじゃないかな
基礎体力つけないと、なかなか応用力はつかん気がする
・MySQL 5.1.33です
userID | groupID
1 | 1
2 | 1
3 | 1
4 | 2
5 | 3
5 | 3
列の一部が userID | groupID となっています
groupIDに所属しているuserIDが1つのレコードを抜き出したいです。
上の表だと 4|2 のデータだけ抜き出せるでしょうか?
GROUP BYをうまく使うのかな?と思って試したのですが、思い通りの結果が出ませんでした。
group by groupID
having count(userID) = 1
ばっちりです!
userIDとgroupIDの両方をGROUP BYしていたので
COUNTでうまく数えられなかったようです。助かりました−
MySQL 5.1.34を使ってます
key data1 data2 data3
-----------------------
1 a b c
2 a a c
3 c c a
4 b c b
こういうテーブルから
data1、data2、data3のいずれかにaが入っているものを取り出したいです。
where data1 = 'a' or data2 = 'a' or data3 = 'a'
>>479 SELECT * FROM TableName WHERE 'a' IN (data1,data2,data3);
例を出すなら、希望の検索結果(この場合keyの一覧)も書かないと伝わりにくいかもよ
質問です
classA
|__Name
|__AAA
|__BBB
classB
|__BBB
|__Name
|__CCC
select * from classA naturaljoin classb;
を実行すると
Name BBB AAA CCC
で中身が出力されると思うのですが、解釈としては両方にある列名が先に出てきて、
そのとき先に出てくるのはnatural join の前に指定した表通りの順
一致してない列名はnatural join の前に指定した表、次に後に指定した表 で出力される
ということでよろしいのでしょうか?
お願いします
順番気にするなら*使わないからわからん
実装依存入ってくるんじゃないのかなぁ。
ともあれコマンドラインから手打ちする場合はともかく、
プログラムにクエリ埋め込むときは絶対に*使わないから
>>484と以下同文。
>>483 SQLでは、テーブル定義の列の順番は基本的に意味を持たないってのが原則
必要な場合は列リストを書いて指定する
俺の持ってる本ではその順番で出力されるようなことは書いてあるが、
それが定義された動作なのか実装に依存するのかは不明
>>484が言うように、順番を指定したいなら*ではなく列リストを書くべき
>>483に対する答えとしては同意だけど、
>>485 > プログラムにクエリ埋め込むときは絶対に*使わないから
なんで「絶対」? たいていの言語にはカラム名を配列などの添字で
扱えるから、場合によっちゃ * は十分ありだと思うけど。
そうですかー わかりました
まぁたぶんということで思ったとおりの解釈にします
ところで、自分はMySQL5.0.67を使ってるのですが、
・完全外部結合(A full outer join B)
・和集合(A union join B)
・共通集合(A intersect B)
・差集合(A except B)
で構文エラーが出ます
サポートしてないということでいいのですかねー?
もし、MySQLの仕様がわかるようなページがあればURLお願いします
バージョンアップを考えたいと思います
>>489 勉強用に使ってます
ポスグレですか 使ったことがないのでイマイチとっかかりにくいです^^;
わざわざURLありがとうございます 見てみます
>>487 俺も場合によってはありだと思うが
とあるプロジェクトでselect * 禁止ってルールがあったことがあるな
スキーマの変更がSQLに影響を及ぼすのを避ける
項目数の増減によるパフォーマンス変化を避ける
が主な理由だった気がする
まあ、プログラマ的立場からいえば、プログラム作らす前にDB設計終えとけとw
492 :
NAME IS NULL:2009/05/24(日) 09:26:16 ID:p08hoVjs
>>490 本とセットなら、SQL鯖かOracle+現場で使うSQLがいいと思う
PostgresベースのSQL勉強用の本、あまりいいのがない気がする
#MySQLも同じ・・・・
#単なるお勉強しました じゃなくてその後の業務でも使えそうな本ね
最初にSQL鯖やOracleなんて覚えたら環境依存激しすぎて
ああOracleだったらできるのにこれだからフリーのRDBMSはと愚痴る人間になっちゃうぞ
そんなん何で始めても一緒。本人の資質次第だよ。
Postgresとかで始めても、やっぱり「Oracleは環境依存が激しすぎて」なんて
愚痴るようになる人だっているわけだし。
う〜ん、もめていますが、
>>489で書いたのは
>あと目的がシステム開発じゃなくてSQLの勉強なのであれば
と限定した上で、
>MySQLよりPostgreSQLの方が良いよ。
>こっちの方がSQL標準により対応しているので。
と書いたのですが。最大公約数としての標準SQLを学ぶので
あればMySQLよりPostgresがベターと言うだけの話であって、
システム開発にまつわる個別の実装の方言の問題はとりあえず
保留、で良いのではないでしょうか。
(参考書の書き方の問題もありますが。実践なんちゃら系の本は
標準と方言をちゃんと区別してないことが多いですし)
現場で使うSQLがそもそも標準SQLじゃなくてOracle/SQLServer依存なんだから駄目だろ
いや、だから現場で使うとは誰も言っていないじゃないですか。
どうでもいいスレ違いはやめにして、次の質問どうぞー
499 :
NAME IS NULL:2009/05/24(日) 18:29:24 ID:p08hoVjs
8.4からCTEも使えるし、そう違うとは思えないんだが>管理系は別
細かい部分の差異の読み替えは、慣れだしね
どんな時にどうすればいいのか、の考え方の方が重要でしょ?
こういう場面で一度も話題に上らないDB2( ´・ω・)カワイソス
Sybaseより見ないからなぁDB2
次期バージョンでは、PL/SQL が使えるらしいぞ
うん。IBM社内的にもv9.xからv10.xになればいいじゃん、という声があったほど大きく変わった。
なのに「v9.7」
PL/SQL使うならOracleでいいじゃんみたいな
506 :
NAME IS NULL:2009/05/25(月) 07:43:45 ID:+IuRrIp9
Oracleからの移行狙いなんだろうね
商用のpostgresにも、そういうのなかったっけ?
>>504 DLして試してみたいかも>後一ヶ月くらいか
Express9.5 CentOS に入れて放置だわw
ミドルウエアやERPがDB2に対応してくれないとそんなに移行しないだろ
PL/SQLさえ動けばいいわけじゃないんだし
また皆さん痛いところをつく(ノД`)
509 :
NAME IS NULL:2009/05/25(月) 13:09:28 ID:+IuRrIp9
その通りなのだが、試してみたくね?
SQL鯖メインだから、かんけーねーといえばそれまでなんだが
現行ではまず使うことないんだけど>DB2
distinctで、かぶり無しで抽出したレコードを空白やカンマ区切りで結合するのは、
どのようにコードをかけばいいでしょうか?
SELECT disctinct(種類) FROM 商品リスト
レコードは
1 バナナ 果物
2 キャベツ 野菜
3 リンゴ 果物
4 イチゴ 果物
5 ニンジン 野菜
上では
果物
野菜
と2レコードで出るのですが、
果物 野菜
と1レコードで出したいです。
SQLでは列の数が可変な問合せはできない
ストアド使えばできなくもないけど
アプリでやったほうがいいかと
512 :
510:2009/05/25(月) 20:06:02 ID:???
>>511 すいません、
もしややこしいこと書いていればすいません。
上では
果物
野菜
と2レコード 1フィールドで出るのですが、
「果物 野菜」
と1レコード 1フィールドで出したいのです。
1レコード2フィールドではないのですが、
前者ならできますでしょうか?
ごちゃごちゃ言っても回答は同じ
514 :
510:2009/05/25(月) 21:21:43 ID:???
煽りじゃなくて、少し入門書を読んだ方が良いね。
今のままじゃ、違和感ばかりたまって、いくらやっても向上しないよ。
>>510 MySQLならGROUP_CONCAT
あとは知らん。
昔Oracleでなんかの上位10個を検索して横に並べるってSQL見たことあるなぁ
どんなんしてたっけなぁ
やっぱプロシージャだったかな
数固定ならSQLだけで何とかならんこともない
LIMIT 1 OFFSET 0
LIMIT 1 OFFSET 1
…
いやなんでもない
520 :
NAME IS NULL:2009/06/01(月) 00:06:43 ID:3TUTRBRK
初心者です。どうか教えてください。
visual studio 2005をADOを通してデータベースmdbを接続し
FPspreadへ表示できるようにしたいのですが全くわかりません。個人としては
dim cnn as adodb.connection
dim rs as adodb.recordset
'データベース接続したとする
ここからアクセスデータを取得したいのですが
SQL = "SELECT FROM * ;"
rs.open(SQL, cnn)
?????
ここからの文を作れずつまずいています。
SQL文からデータベースをスプレッドシートに表示するにはどういった構文に
すべきでしょうか?
スレ違い
VB スレでも行け
522 :
NAME IS NULL:2009/06/01(月) 00:15:27 ID:3TUTRBRK
わかりました。すみませんでした。
SELECT FROM * ふいたwww
ろ
辞めちゃった人間の作ったJETデータベースエンジンのMDBを引き継がされて
テーブル名が*とかフィールド名がFROMとかSQLがSELECT [FROM] FROM [*]とかいう
ウンコDBを書き換える仕事はもうイヤだお・・・
FROM SELECT *
博士が泣いておられます
select [where],[group by],count(where) from [from] where [order] is null
group by [group by] order by [null]
こういうのは?
なんのナゾナゾだよw
質問します。
【DBMS名】Oracle 10g
【バージョン】申し訳ありません。不明です。
【テーブルデータ】
ID | DATE | DATA
--+----------+-----
1 | 2009-05-11 | aaa
2 | 2009-06-01 | bbb
3 | 2009-06-10 | ccc
4 | 2009-06-12 | ddd
5 | 2009-07-19 | eee
【説明と欲しい結果】
このようなテーブルから、下記のように
2 | 2009-06-01 | bbb
3 | 2009-06-10 | ccc
4 | 2009-06-12 | ddd
[DATE]が今月分のレコードのみを抽出するSQLの書き方を教えて下さい。
(システム日付は今日、2009/06/03とします)
よろしくお願いします。
日付を yyyymm で取ってきて、200906 と同じかどうか。
あるいは、年が 2009、月が 6 のレコード。
日付操作関数を調べてね。
普通に DATE > '2009-06-00'
又は DATA >= '2009-06-01'
でいいんじゃ?
ヒント:trunc関数で月単位の切り捨てもできる
534 :
530:2009/06/03(水) 23:56:43 ID:???
>>531 >>532 >>533 ご回答ありがとうございます。
Oracleが手元にないので、実際に試せないのですが、
システム日付を「yyyymm」で取得して、
その後、[DATE]が先ほど取得したyyyymmで始まるかどうか、
を抽出条件に入れることで対応したいと思います。
これで永眠できます。
最近はじめたものなのですが
質問です。
SELECT*INTO 1○○ FROM 2○○
1を2に挿入するってことなのですか?
それとも2を1に挿入なのでしょうか?
いまいちわからないので教えてください。初歩的で申し訳ないです
SELECT じゃなくて INSERT じゃねえの?
それともDBMS固有SQL?
>>536 んー固有かどうかはわかないです。
他人の作ったACCESSのVBAコードだったんで・・・
やってみればいいじゃん。
SQL ServerとJetな。
INTO句で指定したテーブル名のテーブルがCREATEされるよ。
FROMがレコード抽出元テーブルの指定。
え マジでこんな書き方許されるの?
マイクロソフトだもん。
SELECT INTO は PostgreSQLにもあるよ。
用途は全く違うがSELECT INTO はoracleにもある
Oracleのはいくらなんでも別物だろう。
PostgreSQLはSELECT INTOよりもCREATE TABLE ASが推奨されてなかったっけ?
Oracleで意味的に同じものは
CREATE TABLE AS SELECT
どなたか教えてください。
テーブルに
ステータス、登録日、ID、…
といった情報をもつレコードがあるとき
IDでグルーピングして、複数のレコードが合ったときに
@ステータス 90>30>20 の優先順位で高いほうのレコードを抽出。
A同じステータスの場合は、登録日が昔のものを抽出
ということを一つのSQL文でやりたいのですが、やり方が全くわかりません
助けてください…
order by field(ステータス, 90, 30, 20), 登録日
とかでいいんでなくて?
おお、ステータスはこうやるのですか
ただ、これって、1レコードになるのでしょうか
ちょいと試してみます。出来なかったらまた伺います。。。
イッテキマス
552 :
NAME IS NULL:2009/06/05(金) 17:25:22 ID:5dMjVb/r
SELECT name from X where name LIKE '%キーワード%'
→ 文字列「キーワード」を含むname「キーワード1」「重要キーワード」など
が選べます。
逆に、文字列「キーワード」に含まれるnameを選ぶようなSQL文はありますか?
「素敵なSQL文」
→文字列「キーワード」に含まれるname「キー」「ワード」「ワー」などを選ぶ。
となるような「素敵なSQL文」です。よろしくお願いします。
>>552 逆にすればいいんじゃね。
SELECT name FROM X WHERE 'キーワード' LIKE '%'||name||'%';
554 :
552:2009/06/05(金) 18:13:38 ID:5dMjVb/r
ああああああああああああああああああ。
>>553 こんなことできたんですね。ありがとうございます。
(MySQLでは「||」はムリなのでしょうか。
'%'||name||'%'のかわりにconcat('%', name, '%')でイケました。)
テーブル名をワイルドカード指定することは可能でしょうか?
例えば、A0,A1というテーブル名のテーブルがあった場合、
SELECT * FROM A*;
のように、テーブル名をワイルドカード指定して、A0,A1の内容を参照したいのですが。
出来たとしてどんな結果を期待してるんだろうな。
UNIONか?
558 :
sage:2009/06/05(金) 21:28:43 ID:PrWmL95S
PRO*COBOL での プリコンパイラにて
「WHEN」の中に「式の記号」は書けない という旨のエラーがでます
CASE WHEN col_1 = 1
THEN '○'
WHEN col_1 = 2
THEN '×'
ELSE NULL
END
WHEN の中に 「=」 が プリコンパイラでエラーとなります
col_1 IN('1') としても、条件を逆にして
col_1 <> '1' としても
「IN」、「<>」 が プリコンパイラでエラーとなります
実現したい条件は、 CASEが ネストで3階層あります
CASE when col_1 = ' '
THEN
CASE when col_2 = ' '
THEN CASE when col_3 <> ' '
THEN col_3 を比較条件のカラムにする
END
ELSE col_2 を比較条件のカラムにする
END
ELSE col_1 を比較条件のカラムにする
END col_x =:INP_ID
CASE WHEN を使わないで、上記の条件をどのように記述したらよいのでしょうか
DB設計がとてつもなく汚い悪寒w
スレ違いだな。COBOL スレでも行け。
>>558 Pro*COBOLってことはOracleなんだろうから書けそうなもんだけど、
どうしても書けないなら
where col_1 = なにか
or (col_1 = ' ' and col_2 = なにか)
or (col_1 = ' ' and col_2 = ' ' and col_3 = なにか)
とかするしかないんじゃね?
PRO*COBOLは知らんけど
CASE col_1
WHEN 1 THEN
みたいに書けんの?
>>558 まずはそのSQLがSQL*Plusとかで通るかどうか試すべき
564 :
sage:2009/06/06(土) 14:08:20 ID:4vB1BD0o
>>559 DBリンクを使って、他業者のDBのテーブルを判断なので
確かにDB設計が汚いです @@;
>>561 ありがとうございます。その記述にして、やってみます
>>563 SQL*PLUSでは、実行でき、ちゃんと望みどおりの検索結果が返ってきます
565 :
NAME IS NULL:2009/06/07(日) 03:52:32 ID:BvTw+nDU
HEXの形式で入っている文字列を普通の文字に変換したいのですが
例) '31323334' →’1234’
どう書けばいいのでしょうか?DBはオラクル10gです
566 :
NAME IS NULL:2009/06/07(日) 09:48:22 ID:H5yYzBMm
おしえてください。
ある整数の列があるとして、
昇順あるいは降順にソートしたものが
以下のようなデータだったとしてます。
1, 2, 3 , 10, 15, 60, 125, 524, 680
この結果の中において隣接する値と一番乖離している行番号を取得したいです。
どうすればいいでしょうか?
>>567 「昇順時で次の値までが一番離れている」と受け取った。
LIMITクエリで手抜きだが。
SELECT num,(SELECT min(num) FROM Table AS T2 WHERE T1.num<T2.num)
FROM Table AS T1 ORDER BY 2 DESC NULLS LAST LIMIT 1;
NULLS LASTが使えないなら、2カラム目のサブクエリをCOALESCEで囲うか。
>>567 select *
from (select T1.ColumnName,
min(T2.ColumnName),
min(T2.ColumnName) - T1.ColumnName,
row_number() over (order by min(T2.ColumnName) - T1.ColumnName desc) as RN
from TableName T1
inner join
TableName T2
on T1.ColumnName < T2.ColumnName
group by T1.ColumnName)
where RN = 1
;
差が同じところが2箇所以上あっても1つしか選択されないので注意
date_sub()でのintervalの指定に
変数や別テーブルからselectした結果を使いたいのですが、
mysql> select @x:='interval ''6'' month';
+----------------------------+
| @x:='interval ''6'' month' |
+----------------------------+
| interval '6' month |
+----------------------------+
1 row in set (0.00 sec)
mysql> select date_sub('2009-4-30', @x);
ERROR 1064 (42000): You have an error in your SQL syntax
以上ではエラーになります。
クオート?かなにか必要なのでしょうか。
サーバはMySQL5.0を使っています。
お願いします。
571 :
NAME IS NULL:2009/06/07(日) 14:07:44 ID:s0waBkcv
揚げ
572 :
NAME IS NULL:2009/06/07(日) 14:27:47 ID:FbuXSqjn
567です。
>>568 >>569 お返事ありがとうございます。
MySQL5を使っているのですが、
例示していただいたコードではsyntax errorが出て
あれこれと考えていました。
autoincrement列を追加し、その値を取得することで対処しようと
思います。
SELECT id,(SELECT min(num) FROM test_table AS T2 WHERE T1.num<T2.num)-num as diff FROM test_table AS T1 order by diff desc;
ありがとうございました。
>>565 昔やったときは文字単位でばらしてCHR()でがんばったなぁ。
なんでこんな基本的な機能がないんだろうって文句言いながら。
今ならあるのかな?
MySQL4.1.2(各文字コードはUTF-8)を使用し、形態素解析済みのカラムに対するFullText検索を試しているのですが、
SQLの書き方が悪いのか、結果が思うようにいきません。
検索ワードがひとつだとまずまずなのですが、ANDやOR・NOTといった複数語となると特に・・・
例として「赤ちゃん」「権力者」をAND検索する場合ですが、どう書けばいいのでしょうか。
試しているSQL文は以下のような感じです。※「権力者」は分かち書きされて「権力 者」となっています。
(例1※おそらく間違い)
SELECT * FROM some_table MATCH(some_column) AGAINST('+"赤ちゃん" +"権力 者" in boolean mode');
=>LIKE検索では結果は2件だが、131件ヒットする。
+や-記号が効いていないようで、上記「権力 者」の前の+を-に変えても結果は変わらない。
以下も同じで、LIKE検索に比べ数10件の誤差が出る(ワードにスペースが含まれない場合の例のつもり)
SELECT * FROM some_table MATCH(some_column) AGAINST('+赤ちゃん +権力 in boolean mode');
(例2※LIKE検索っぽい書き方をしてみた)
SELECT * FROM some_table MATCH(some_column) AGAINST('赤ちゃん') AND AGAINST('権力 者');
=>5件ヒットする。=>「赤ちゃん」しか含まない結果が3件ある&ググッてもこういう書き方をしてる例が見つからない
すみませんがお願いします。
MATCHってWHERE句なくても動くんだ?
577 :
575:2009/06/07(日) 18:53:06 ID:dWbdg2sE
>>576 申し訳ない、WHERE抜かしてました。正しくは
(例1)
SELECT * FROM some_table WHERE MATCH(some_column) AGAINST('+"赤ちゃん" +"権力 者" in boolean mode');
(例2)
SELECT * FROM some_table WHERE MATCH(some_column) AGAINST('赤ちゃん') AND AGAINST('権力 者');
'の位置を確認してみれ
580 :
575:2009/06/07(日) 19:25:16 ID:dWbdg2sE
>>578-579 おしえていただいたページは両方とも参考にしていました。
しかし・・・'の位置orz
以下の文で正しい結果(LIKE検索と同じ2件取得)となりました。
SELECT * FROM some_table WHERE MATCH(some_column) AGAINST('+"赤ちゃん" +"権力 者"' in boolean mode');
ありがとうございました!
581 :
580:2009/06/07(日) 19:27:03 ID:dWbdg2sE
くひっ。また間違えた・・・正しくは
SELECT * FROM some_table WHERE MATCH(some_column) AGAINST('+"赤ちゃん" +"権力 者"' in boolean mode);
です。
まず落ち着こうよ。
読みやすい文章を書くのも大事なことです。
583 :
NAME IS NULL:2009/06/10(水) 22:45:16 ID:zpAa6Yna
sqlserver 2000 を使っています。
varchar型の文字列に含まれる改行コードの数を出したいのですが、
何かいい方法はありませんか?
教えてください。
動く環境無いんで想像だけど
replace(文字列,'\r\n','')
と
文字列
のlengthの差で出るかな。
改行コード、数えて何したいかによるんじゃないのかな?
例えば、行数に応じて出力先の高さを可変にしたいとか
この場合、無理してSQLでやらずに、ホストのプログラムでやった方が楽だと思うよ
改行コードで分割して配列に詰め込むような関数を使う(自作する)とかね
586 :
NAME IS NULL:2009/06/10(水) 23:31:44 ID:zpAa6Yna
>>584 select replace(len(文字列,char(10),'')) - len(文字列) from テーブル で
取得できました!
今日1日中考えていたのでちょっと感動です。
ぐっすり眠れます。
ありがとうございます。
>>585 まさにそうなんです。行数で高さを調節したかったんです。
明日改行数を取得する関数を作ってみようと思います。
SQLでなんとか出せないかと視野が狭くなっていました。
もっと柔軟に考えなきゃいけませんね。
ありがとうございました。
587 :
585:2009/06/10(水) 23:35:59 ID:zpAa6Yna
くひっ。僕も間違えた・・・正しくは
select len(文字列) - replace(len(文字列,char(10),'')) from テーブル
です。
589 :
NAME IS NULL:2009/06/11(木) 22:39:02 ID:/TZVY2cm
SQL Serverを使用しています。
例えばselect * from INFORMATION_SCHEMA.COLUMNS
のような内容をを特定の行だけ縦に表示するにはどう書いたらいいでしょうか?
colmun data
--------------------
table_name test
colmun_name 番号
みたいな感じです
同じ行を何個もUNIONして…
AP側でどうにかしろ
だいたいSQLに「表示」なんて概念は・・・・
>>589 select * from INFORMATION_SCHEMAしてアプリ側で調整
おはずかしいのですが REPLACE 文に付いて教えください。
ID DATA
--------
1 258.9
2 350.6
3 426.9
--------
ID 2 の行を置き換えようと
INSERT OR REPLACE INTO MYDB VALUES(2,330.8);
これだと2の行が置換でなく追加されてしまうので悩んでいます。
今は DELETE 文発行して、INSERT しています。
where ID = 2 が要るだろ普通
>>594 早速ありがとうございます。
VALUES() の後では文法エラーになってしまって(悩中)
WHERE 文の記述ヶ所教えていただけませんか?
INSERT OR REPLACE も UPSERT(だったかな)もよくは知らないのだけど、
IDがプライマリーキーじゃないと拙いような気がする。
SQLは
>>593のままでも通りそうだけど。
INSERT OR REPLACEなんていう気持ち悪い構文はSQLiteか?
UPDATE文を使え
>>596 あああ、PRIMARY KEY ・・
ありがとうございます。ID INTEGER PRIMARY KEY で置換しました。
599 :
589:2009/06/16(火) 16:30:36 ID:???
遅くなったけどありがとう。
自前で処理することにします。
600 :
NAME IS NULL:2009/06/17(水) 02:06:29 ID:tRvf1FDN
すみません、SQL初心者です。
下記のようにSQLを組んだのですが、「--エラー箇所」の場所で
「1つ以上の表が外部結合されています?」のようなエラーが発生してしまいます。
どのように修正したら良いか教えて下さい。
【やりたいこと】
CASE WHENで取得した、「A.コード1」または「A.コード2」に対応する「T.製品コード」が
ない場合でも、レコードを弾かず、T.製品名を空としてレコードを取得したい。
(+)を外すとエラーは発生しないのですが、対応するコードがないデータが
弾かれてしまいます。
【環境】
オラクル8i + ASP
---------------------------------------------------------------------------
SELECT
A.KEY1,
A.KEY2,
T.製品名
FROM
Aテーブル AS A,
Bテーブル AS B,
Cテーブル AS C,
Dテーブル AS D,
取引テーブル AS T
WHERE
A.KEY1=B.KEY1
AND A.KEY1=C.KEY1
AND A.KEY1=D.KEY1
AND A.KEY2=B.KEY2
AND A.KEY2=C.KEY2
AND A.KEY2=D.KEY2
AND A.KEY3=T.KEY3
--エラー箇所
AND T.製品コード(+)= CASE WHEN (C.条件コード判定='1' OR C.条件コード判定='2') AND D.フラグ='1'
THEN A.コード1
ELSE A.コード2
END
ORDER BY A.KEY1, A.KEY2, A.製品名
AND A.KEY3=(+)T.KEY3
がいるんじゃなかろか
AND CASE WHEN T.製品コード(+)= CASE WHEN (C.条件コード判定='1' OR C.条件コード判定='2') AND D.フラグ='1'
THEN A.コード1
ELSE A.コード2
END
THEN 1 ELSE 0 END = 1
603 :
600:2009/06/17(水) 20:43:10 ID:???
>>601、602
返信が遅くなって申し訳ない。
今環境がなく試せないのですが
後日試してみます。ありがとうございます。助かります。
クエリについて質問があります。
レス内容が長くなってしまいすみませんが、説明に分かり辛い部分がありましたら補足しますのでどうかよろしくお願いします。
【質問テンプレ】
・DBMS名とバージョン: SQLite 3
・テーブルデータ:長いため下記に記載
・欲しい結果:Mozilla Firefox 3.0.11のブックマークファイル(*.sqlite/SQLite 3)から特定の履歴(閲覧)を削除したいです。
・説明:長いため下記に記載
●テーブルデータ
==================================================================================================================
■moz_historyvisits
| id | from visit | place id | visit date | visit type | session |
------------------------------------------------------------------------------------------------------------------
■moz_places
| id | url | title | rev host | visit count | hidden | typed | favicon id | frecency |
==================================================================================================================
●欲しい結果と説明
[moz_places]テーブルの[id]フィールドが、[moz_historyvisits]テーブルの[place id]フィールドと一致する場合に、
[moz_places]テーブルのレコードを削除したいです。
また、その際の追加条件として、[moz_places]テーブルの[url]フィールドに[
http://www.test/]という文字列を含む場合は、
必ず削除、[
http://www.example.com/*]または、[
http://*.sqlite.localhost/*]という文字列を"含まない"場合も必ず削除、
それ以外の場合は削除しないという条件を付け加えたいです。
さらに、それと同時に上の条件で、[moz_places]テーブルからレコードを削除したら、[moz_historyvisits]テーブルの該当
レコード(idとplace idを比較して一致した[moz_historyvisits]テーブルのレコード)も削除したいです。
(
>>80さんが言っているような事をしたいです。)
●自分で調べて書けた一部
DELETE FROM moz_places WHERE id IN (SELECT place_id FROM moz_historyvisits)
AND (url LIKE '
http://www.test/%'
OR (url NOT LIKE '
http://www.example.com/%' AND url NOT LIKE '
http://%.sqlite.localhost/%'))
※[moz_historyvisits]テーブルのレコードを同時に削除するという方法が分からないです。
・上のクエリは、長いので改行して投稿しました。
・一応実行できたのですが、添削していただければ幸いです。
●補足
1.データベースファイル名は、[places.sqlite]です。
2.[moz_historyvisits]テーブルの[place id]には、重複データが有ります。
3.Windows XP Professional SP3 (32bit版)で、PupSQLite・TkSQLiteというソフトで操作しています。
4.SQL(SQLite)については昨日あたりから調べ始めました。
(プログラミング言語については、JavaScriptとVBSだけは、なんとか調べて基本的な事だけは若干理解できる程度です。)
以上、どうかよろしくお願いします。
605 :
604:2009/06/20(土) 05:03:44 ID:???
>>604 標準SQLでは複数テーブルからのDELETEはできない。
どうしてもやりたければ参照整合性制約やトリガーを使うけど
まあDELETE文2回でいいんじゃね?
607 :
604:2009/06/21(日) 01:52:54 ID:???
>>606 レスありがとうございます。
できれば、そのトリガー(もしくは参照整合性制約)というものを使って同時に削除したいです。
よろしければ、
>>604のクエリにトリガーという方法を加えたクエリを書いていただけますでしょうか?
下記のページを参考に調べているのですが、基本的な事しか理解できず複雑な式は分からず・・・。
net-newbie.com/sqlite/lang.html#createtrigger
お時間のある時で構いませんので、お手数ですが再度レスをいただけると助かります。
どうかよろしくお願いします。
sqliteを使ったことがないけどこれでいけるかな
CREATE TRIGGER delete_history AFTER
DELETE ON moz_places
BEGEN
DELETE moz_historyvisits WHERE id = OLD.id
END
被るところだったw
>>608のDELETE文はFROMがいるんじゃね
DELETE FROM moz_...
610 :
604:2009/06/21(日) 03:10:18 ID:???
>>608,
>>609 レスありがとうございます。
ちょっとそこまでくると、サッパリで分からないのですが、
>>604に書いた下記のクエリの下に追加すればいいのでしょうか?
>●自分で調べて書けた一部
>DELETE FROM moz_places WHERE id IN (SELECT place_id FROM moz_historyvisits)
> AND (url LIKE '
http://www.test/%'
> OR (url NOT LIKE '
http://www.example.com/%' AND url NOT LIKE '
http://%.sqlite.localhost/%'))
CREATE TRIGGER delete_history AFTER
DELETE ON moz_places
BEGEN
DELETE moz_historyvisits WHERE id = OLD.id
END
バックアップ取ってから試してみたいと思いますが、よろしければ再度レスをいただければ幸いです。
何度もすみませんが、よろしくお願いします。
611 :
604:2009/06/21(日) 04:15:16 ID:Bz0yhBlW
604です。
色々弄っていたところ、下記のクエリ文で動作しました。 多分。(汗
●クエリ
CREATE TRIGGER delete_history AFTER
DELETE ON moz_places
BEGIN
DELETE FROM moz_historyvisits WHERE id = OLD.id;
END;
DELETE FROM moz_places WHERE id IN (SELECT place_id FROM moz_historyvisits)
AND (url LIKE '
http://www.test/%'
OR (url NOT LIKE '
http://www.example.com/%' AND url NOT LIKE '
http://%.sqlite.localhost/%'))
間違い等ありましたら、指摘していただけますでしょうか。
何度もレスをしてスレを伸ばしてしまってすみませんが、よろしくお願いします。
DELETE FROM moz_places WHERE id IN (SELECT place_id FROM moz_historyvisits)
AND (url LIKE '
http://www.test/%'
OR (url NOT LIKE '
http://www.example.com/%' AND url NOT LIKE '
http://%.sqlite.localhost/%'))
が実行されると、自動的に
CREATE TRIGGER delete_history AFTER
DELETE ON moz_places
BEGIN
DELETE FROM moz_historyvisits WHERE id = OLD.id;
END;
が走る。
これがトリガね。
614 :
604:2009/06/23(火) 00:49:07 ID:???
返事が遅れてすみません。
>>612 レスありがとうございます。
なんとなく分かったような気がします。(・ω・;)
ただ、間抜けな事をしていて消すテーブルが逆でした。(爆
ただ今、修正中なのです。
回答・アドバイス等いただいた方々に大変感謝しています。
この度は色々とどうもありがとうございました。
テーブルが作成されているかを確認する標準的な方法はあるでしょうか。
mysqlならCREATE DATABASE IF NOT EXISTSでいけるのですが。
616 :
NAME IS NULL:2009/06/23(火) 22:02:19 ID:Lck5HQZ4
テーブル一覧のプロパティのファイルグループ名を
クエリで取得することって出来ますか?
スレ違い。
618 :
NAME IS NULL:2009/06/24(水) 11:02:20 ID:cpDMBc2F
以下のように、AとBのカラムがあるHOGEと言うテーブルがあったとして、
AとBのカラムを見てユニークなものだけをカウントするにはどういうSQL書けばいいでしょうか?
DBMSはMySQL5.0.67です。
A|B (TABLE HOGE)
-+-
1|2
3|5
7|3 この場合、1,2,3,5,7,9
9|5 よって、その合計の「6」が答え
指定のMySQLで出来るかどうかは知らん
select count(distinct *) from (select A from HOGE union all select B from HOGE) as X
SQLって統一規格じゃないんですか?
独自SQLのようなものがあるんですか?
ある程度の機能と用件を満たせば準拠。
プログラミング言語と比べるとSQLは独自色が強い。
統一規格はあるけど、方言に頼るところも多い。
文字列変換や時刻関数等はほとんど方言だな。
oracleの外部結合の方言はひどいw
オラクルの外部結合って、SQL92が出てくる前からあったんじゃなかったけ。
各ベンダーの独自拡張があって、その後の標準化だから、
互換性のために方言として残るのは仕方ないだろう。
DB2 に truncate 相当の機能が無いのには驚いた。
良い悪いって話じゃないけど。
下のようなテーブルでIDが1のDATEの新しい順に10個取得したいのですが、もっと早くできる書き方はないでしょうか
IDにはインデックスが無く、DATEはインデックスがあります。
mysql 5.0.51aです
ID | DATE
--+----------
1 | 2009-01-11
2 | 2006-01-01
1 | 2006-11-10
3 | 2008-07-12
SELECT * FROM table WHERE id = 1 ORDER BY DATE DESC limit 10
>>625 id = 1で検索してるから、idにインデックス付けてみたら?
で、実行計画取ってみて、インデックスの有無で変化があるか確認してみて
IDの意味解って付けてんのかよ
628 :
NAME IS NULL:2009/06/28(日) 13:31:46 ID:tWKLIY9h
もちろん、IDはプライマリキーです。
とかね。
あるあるw
630 :
625:2009/06/28(日) 18:03:08 ID:???
問題をわかりやすくするため単純にしたつもりだったのですが
横着してテンプレのものを流用したため、逆に誤解を招く書き方になったようですいません。
ほかで聞くことにします。失礼しました
Y!知枝袋にでも逝っておいで
つか、そこまで単純にしてしまって、
速度に差が出るほどバリエーションのある書き方できると思ってたのか?
相変わらず厳しいやつらだ
SQL Serverでストアドつくろうとしてるけど、
アプリからストアドに渡す引数がいっぱいあるんだけど普通?
これってアプリでやるべきじゃねぇのか。
アプリにするかストアドにするかの基準を教えてくれ。
ここはSQL文を語るスレ
引数がいくつでもスピード重視ならストアドにするんじゃない?
まあ、スレチ。
Postgresql v8.3で
商品(商品番号(int),商品名(char))
分類(分類番号(int),分類名(char))
取り扱い(商品番号(int),分類番号(int),取り扱い時期(int))
という3つの表を
商品情報(商品番号,分類番号,商品名,分類名,取り扱い時期)という
一つの表集合として結合(4個目の表として存在させる)したいのですが、方法が良く分かりません。
新しく表を定義するのであればcreate tableかなと思ったのですが、表を結合表示させるときは
selectを使っていましたし、create tableとselectをどうやってつなぎ合わせるのか見当もつきません。
ヒントだけでも構いませんのでご教示願います。
create table 商品番号 (〜〜〜)
insert into 商品番号 select 商品番号, 分類番号, 〜〜〜 from 〜〜 natural join 〜〜 natural join 〜〜
的な感じでいいんんじゃないの?postgres知らんけど
MySQLです、↓のようなSQL文がありまして
SELECT DISTINCT aaa.*, bbb.name FROM {table_a} aaa LEFT JOIN {table_b} bbb ON aaa.uid = bbb.uid INNER JOIN {table_c} ccc ON aaa.snid = ccc.snid
これにaaa.mailが第四のテーブル({table_d} ddd)のddd.mailと一致しないものを抽出という条件を追加したいのですが
どういう風にすればいいでしょうか?
度々すみません・・・。
>>637について、
create table 商品情報(
商品番号 int,
分類番号 int,
商品名 char(20),
分類名 char(50),
取り扱い時期 int
) insert into 商品情報 select 商品番号,分類番号,商品名,分類名,取り扱い時期
from 商品 natural join 分類 natural join 取り扱い natural join;
とやってみたのですが、どうもエラーになってしまいます。
insert付近でのエラーとなっているのですが、
insertとcreateを分けてしまうと、createまでは通っても、
insertで既に存在する表の作成云々というエラーになってしまいますし、
表の趣旨も全く意味をなさないものになってしまいます。
どこをどのように修正すればよいのでしょうか?
宜しくお願い致します。
VIEW作るんじゃいかんの?
>>640 最後の natural join が余計。
つか、キーワードが分かったら自分でマニュアル読んでみれ。
>>640 恒常的に見るのであれば、
craete view 商品情報(・・・・)
select 〜
実体作りたいって言ってんだろカス
結合したいっていう話しか出てないだろ
人の話はちゃんと読め
>一つの表集合として結合(4個目の表として存在させる)したいのですが
>一つの表集合として結合(4個目の表として存在させる)したいのですが
>一つの表集合として結合(4個目の表として存在させる)したいのですが
>一つの表集合として結合(4個目の表として存在させる)したいのですが
>一つの表集合として結合(4個目の表として存在させる)したいのですが
>一つの表集合として結合(4個目の表として存在させる)したいのですが
元質問者はVIEWの存在を知っているのかどうかが知りたいところではある
ある時点のスナップショットをとりたい=>ワークテーブル
複数テーブルの結合結果を表として扱いたい=>VIEW
どちらをやりたいのかによるな
>>650 横からすみませんが、「ちゃんと読め」とか「よくない」とか文句だけ言うよりは、
自分で回答を示せば良くないですか?
>>639 動作未確認だけど、WHERE句で条件付けるのはダメ?
WHERE NOT EXISTS(
SELECT *
FROM {table_d} ddd
WHERE ddd.mail = aaa.mail
)
653 :
639:2009/07/01(水) 14:03:32 ID:???
>>652 行けました、NOT EXISTSという使い方があったんですね
前任者の書いたSQLに処理を追加する作業だったんですが安請け合いして後悔し始めたところです
dくすでした
細かい話だけどNOT EXISTS ならSELECT 1 とかすべき
細かい話だけど最近のRDBMSならSELECT *で十分最適化されるよ
むしろ*のほうがいい
で、どっちが正解?
>>657 昔は定数の方が速かった。今は * の方が速い時もある。
なるほど
教えてくだせー
>>4で、例えば最新の3件を抽出するにはどうしたらいいですか?
top n とかrow_number()とかrownumとか。
DBMSの種類によって書き方が違う。
662 :
660:2009/07/03(金) 22:18:56 ID:???
MSDEのData更新に困っております
AccessプロジェクトよりCSVファイルをインポートして
DataBase作成しているのですが、インポート先のCSVファイルは
常に更新されています
AccessプロジェクトのData更新の為、インポートを行うと
重複したDataになります・・・・
重複しないクエリもしくはVBEはないでしょうか?
まず「インポート」の意味から勉強してこようぜ
話はそれからだ。
importの前にdeleteすればOKだね
はい 次
668 :
663:2009/07/07(火) 20:04:57 ID:???
申し訳御座いませんマルチしておりました
反省しております
>>665さん
AccessプロジェクトのDataをdeleteしましたができませんでした
別のやり方があるのでしょうか・・・
MDBの様にリンクできればよいのですが
>>668 あっちのスレでもいっぱい返事もらってるのに
並行で進めるのはやめれ
>>669 質問の内容はどうでもいいことばかり。
だれかれに構って欲しいのさ。
あちこちに書くのは、2chに張り付いてるからだろ。
とにかくかまって欲しいんだよ。
671 :
NAME IS NULL:2009/07/09(木) 14:22:20 ID:I1RDXwu9
postgresSQLを使っているのですが、以下の問題がわかりません。
以下の順序で列を表示するビュー定義を考え実行する
支払金額、明細
>>671 宿題は自分で解く。
順序の指定は ORDER BY
SQL Server 2005 互換性レベル8.0(2000)です。
別テーブルに問い合わせて、条件に該当するレコードが存在するかどうかを、列に表示したいのです。Boolで。
SELECT CM.CustomerID, CM.CustomerName,
FlagUriage = ( CONVERT( bit, ( SELECT COUNT(*) FROM UriageData UD WHERE UD.Nendo = 2008 and UD.CustomerID = CM.CustomerID ) ) )
FROM Customer CM ORDER BY CustomerID
現在は、このように件数をCountしたのをbitにConvertしてますが、これでいいんですかね。
EXISTS を使えば、booleanを返すのだから、
FlagUriage = ( EXISTS ( SELECT * FROM UriageData UD WHERE UD.Nendo = 2008 and UD.CustomerID = CM.CustomerID ) )
のようにすればよさそうだけどエラーになる。
キーワード 'EXISTS' 付近に不適切な構文があります。
一番りこうな書き方は何ですか。
674 :
NAME IS NULL:2009/07/09(木) 15:58:07 ID:H2IBJWq1
>>673 どういう文脈で使いたいのかいまいち分からないけど
TSQL内で使うならIF
SQL分だけで使うならcoalesceでよくない?
利口ってか、早いのは実行計画とってみないとわからん
外部結合してNULLかどうか判定するとかが一般的じゃないかな
あとはUNION使って
SELECT ..., 1 as FlagUriage WHERE ...
UNION
SELECT ..., 0 as FlagUriage WHERE not ...
とか
>>673 SQL鯖はよく知らないが
> FlagUriage = ( CONVERT( bit, ( SELECT COUNT(*) FROM UriageData UD WHERE UD.Nendo = 2008 and UD.CustomerID = CM.CustomerID ) ) )
> FlagUriage = ( EXISTS ( SELECT * FROM UriageData UD WHERE UD.Nendo = 2008 and UD.CustomerID = CM.CustomerID ) )
なにこれ? よっとして (CONVERT .....) AS FlagUriage と同じことなのかな?
COUNT(*)するよりEXISTSの方が良さそうなので、
CASE WHEN EXISTS ( SELECT * FROM UriageData UD WHERE UD.Nendo = 2008 and UD.CustomerID = CM.CustomerID ) THEN 'あり' ELSE 'なし' END
で動かないかな?
MySQL 5.0.45で質問です。
webのアクセスログをDBに格納しており
以下の様なTABLEになります。
FILE | DATETIME
-----+---------------------
aa.txt | 2007-11-01 00:05:10
aa.txt | 2007-11-01 06:02:00
bb.txt | 2007-11-01 02:30:30
aa.txt | 2007-11-02 10:15:15
aa.txt | 2007-11-02 15:30:00
cc.txt | 2007-11-03 10:05:50
これを以下の様に、ファイルの日毎のアクセス数(COUNT)を
取得したいと思っていますが、どのようにSQLを書けば良いでしょうか?
FILE | DATE | COUNT
-----+-------+-------
aa.txt | 11-01 | 2
aa.txt | 11-02 | 2
aa.txt | 11-03 | 0
bb.txt | 11-01 | 1
bb.txt | 11-02 | 0
bb.txt | 11-03 | 0
cc.txt | 11-01 | 0
cc.txt | 11-02 | 0
cc.txt | 11-03 | 1
理想は以下のようになれば良いですが、上記のようになってくれれば
あとはプログラムで対応したいと思ってます。
FILE | 11-01 | 11-02 | 11-03
-----+------+-----+------
aa.txt | 2 | 2 | 0
bb.txt | 1 | 0 | 0
cc.txt | 0 | 0 | 1
mysql> select date_format(hiredate, '%m-%d'), count(*) from emp group by date_format(hiredate, '%m-%d');
+--------------------------------+----------+
| date_format(hiredate, '%m-%d') | count(*) |
+--------------------------------+----------+
| 01-23 | 1 |
| 02-20 | 1 |
| 02-22 | 1 |
| 04-02 | 1 |
| 04-19 | 1 |
| 05-01 | 1 |
| 05-23 | 1 |
| 06-09 | 1 |
| 09-08 | 1 |
| 09-28 | 1 |
| 11-17 | 1 |
| 12-03 | 2 |
| 12-17 | 1 |
+--------------------------------+----------+
13 rows in set (0.00 sec)
このSQLはあまり性能がよくないので気をつけてね
レスありがとうございます
ただファイル毎の統計が欲しかったので以下のようにしてみました
あとはプログラム側で加工していこうと思います。
select
A.FILE,acdate,COUNT
from
(select
FILE, acdate
from
(select DISTINCT FILE from LOGTABLE) as A1
CROSS JOIN
(select DISTINCT date_format(actime,'%m%d') as acdate from LOGTABLE) as A2
) as A
LEFT JOIN
(select
FILE, date_format(actime,'%m%d') as acdate2, count(*) as COUNT
from
LOGTABLE
group by
concat(month(actime), '-', day(actime), FILE)
) as B
ON
A.FILE = B.FILE and A.acdate = B.acdate2
order by
FILE, acdate
Oracle xeで、以下の機能を実現したいんですが...
どうにも長くなってしまいそうで...短く実現する方法はないでしょうか?
あるテーブル『TT』に
KEY
-----
3
5
6
10
11
って感じで入ってる値を1回のSQLで横に並べたいんです。
key1 | key2 | key3 | key4 | key5
----+------+-----+-----+-----
3 | 5 | 6 | 10 | 11
で、散々悩んだ挙句...
SELECT
T1.KEY KEY1, T2.KEY KEY2, T3.KEY KEY3, T4.KEY KEY4, T5.KEY KEY5
FROM
(SELECT KEY FROM (SELECT KEY, ROWNUM RN FROM TT) WHERE RN = 1) T1,
(SELECT KEY FROM (SELECT KEY, ROWNUM RN FROM TT) WHERE RN = 2) T2,
(SELECT KEY FROM (SELECT KEY, ROWNUM RN FROM TT) WHERE RN = 3) T3,
(SELECT KEY FROM (SELECT KEY, ROWNUM RN FROM TT) WHERE RN = 4) T4,
(SELECT KEY FROM (SELECT KEY, ROWNUM RN FROM TT) WHERE RN = 5) T5
こんなSQLを書いたんですが...
正直もっと簡単にならないものでしょうか?
このスレはまとめサイトがあったほうがいいかもわからんね
>681
レスthx
そおですか...
一応maxが20の可変長なんで、自分の書いたSQLを20まで書けば実現できるんですが...
ストアドかアプリサイドで、ですね。
アプリサイドは通信料増えるのを嫌って最後の手段で考えてました。
ちょっと検討してみます。(´・ω・`)
>682だった。(´Д`;)
縦横変換の基本形に従うと次のようになる。
SELECT
MAX(CASE WHEN RN = 1 THEN KEY END) AS KEY1,
MAX(CASE WHEN RN = 2 THEN KEY END) AS KEY2,
MAX(CASE WHEN RN = 3 THEN KEY END) AS KEY3,
MAX(CASE WHEN RN = 4 THEN KEY END) AS KEY4,
MAX(CASE WHEN RN = 5 THEN KEY END) AS KEY5
FROM (
SELECT KEY, ROWNUM AS RN FROM TT
)
簡単になるかどうかはともかく全表検索は1回で済む。
質問したいんだけど、XEを業務で使っているの?
687 :
681:2009/07/17(金) 17:07:04 ID:???
>686
thx。自分で考えた方法よかよっぽど良いですね。
結局、あれから検討した結果。。。他にも要因があってアプリサイドでやることになりました。
xeは業務で使ってますよ。
本ちゃん環境は10gらしいですが...
>687
なるほど開発で使っているのか。
ちょうど俺も試しに使ってみようとしていたところなんだ。
ありがと。
689 :
NAME IS NULL:2009/07/19(日) 16:28:56 ID:Ee/IhaoQ
下記のようなデータがあり、最新の3日分のデータを取得しようとしています。
このような場合、MySQLでのSQL文はどうなるでしょうか?
◎データベース
id | date | memo
---+------------+------
1 | 2009-12-22 | test1
2 | 2009-12-23 | test2
3 | 2009-12-24 | test3
4 | 2009-12-24 | test4
5 | 2009-12-25 | test5
◎取得しようとしてるデータ(最新の3日分のデータ)
array(
'2009-12-25' => array(
array('id'=>5,'date'=>'2009-12-25','memo'=>'test5'),
),
'2009-12-24' => array(
array('id'=>3,'date'=>'2009-12-24','memo'=>'test3'),
array('id'=>4,'date'=>'2009-12-24','memo'=>'test4'),
),
'2009-12-23' => array(
array('id'=>2,'date'=>'2009-12-23','memo'=>'test2'),
),
);
select * from test t1,
(select distinct date_format(date, '%Y-%m-%d') df
from test order by df desc limit 3) t2
where date_format(t1.date, '%Y-%m-%d') = t2.df
order by t1.date desc;
>>689 SELECT * FROM table
WHERE `date` >= DATE_SUB(CURDATE() , INTERVAL 3 DAY)
で、どうでしょう?
データの無い日をどう数えるかによるね
693 :
689:2009/07/19(日) 22:37:34 ID:???
>>690-692 すみません、MySQLではなくSQLite(Ver.2)でした。
SQL文を実行してみましたがno such functionやsyntax errorでした。
SELECT * FROM Table AS T1 WHERE 3 > (SELECT count(DISTINCT date) FROM Table WHERE date > T1.date);
SQLiteで動くかどうかしらね。
Oracle 10g で質問です。
WITH句で書いたクエリをインライン展開するかどうかを
ヒントなどで制御する方法はないでしょうか?
「実行に時間はかからないが、SQLが長い/複雑になる」という場合に、
SQLはWITH句に1回だけ書きたいのですが、
実行結果をTEMP TABLE TRANSFORMATIONするとかえって遅くなるので、
参照箇所のそれぞれで(インラインで書いた場合と同じように)
実行して欲しいのです。
簡単に言うと、WITH句で、
@同じクエリを複数回書かなくて良い
A同じクエリを複数回実行しない
と出来るうちの、@だけ使いたいということです。
方法をご存知の方がいらっしゃいましたら、教えて下さい。
よろしくお願いします。
Oracleをなめまくる
>>695 どうも最終的にどんな結果が欲しいのか良くわからん。
簡単でいいからやりたいことをSQLで例示してくれないか。
こういうことかな? たとえが適正かどうかは別にして
WITH WithT AS (SELECT * FROM Table WHERE col1 = true)
SELECT * FROM WithT WHERE col2 = 1
UNION ALL
SELECT * FROM WithT WHERE col2 = 2;
この場合、WITH句のクエリが1度実行されて、一時的に置いておいて
その中から col2 を2回検索される。
のだけれども、col2にはインデックスが張られているので、
SELECT * FROM Table WHERE col1=true AND col2 = x;
が2度実行される方が速い。
だから、そのように動かす方法は無いかや?
で、俺はその答えを知らない。Oracle使いでもないしな。
何かスイッチで制御できるものなのか、それとも各ベンダーの
プランナやオプチマイザでの性能UPを期待するしかないのか?
本来はそこもオプテイマイザが適切に判断するはずなんだが、それが
実際には意図した実行計画になっていなかったから明示的にHINTで
指定したいのだと読んだが?
答は俺も知らん。
ますますわからん
701 :
695:2009/07/23(木) 02:11:26 ID:???
695です。言葉足らずですみません。
言いたかったことはほぼ
>>698さん、
>>699さんに書いてもらった内容でした。
ただインデックスがある場合に限らずで、
「一時的に置いておいて」の処理自体でそこそこ時間がかかってしまうようで、
2回実行した方が速いことが結構あります。
ですが実際はそうは動いてくれず、
ヒントなどで制御できないのかな?と思った次第でした。
それらしいヒントは調べても見当たらなかったので、
ヒント以外でも何か方法があればと思ったのですが、、、
702 :
698:2009/07/25(土) 14:43:40 ID:???
>>701 >>699も言ってるが、プランナかオプティマイザが適切に判断するべきところなんだけど、
Oracleの仕様上WITH句のサブクエリだけ先に実行されてしまうようになっているのなら
どうしようもないが、判断上でサブクエリが実行されているのなら、コスト計算の問題かな?
一時テーブルへの待避コストを多く見積もるようにどこかにパラメータはない?
てか、Oracleスレで聞いた方がいいかも。
SQLiteで以下のようなテーブルがあります。
hashが主キーです。
hash|name|size
LIKEでの検索時にdistinctでnameとsizeが重複するものを除外したいのですが、
hashも取得しなければなりません。
よってSELECT hash, name, sizeとしたいのですが、
distinctでhashは除外したいのです(そうしないと重複はあり得ないため)。
なにか良い方法はありますか?
>>703 日本語でおk
ハッシュ値がユニークなのに、ほか二つの値が同じレコードをまとめたいなんて、一体どっちのハッシュ値をもってくればいいんだ?
705 :
703:2009/07/26(日) 01:13:40 ID:???
>>704 あ、そういえばそうですね。
重複したname,sizeをリストから除去したいです。
ハッシュは最初に現れる値でも最後に現れる値でもどちらでも良いですが、重複をのぞく方法は他にあるのでしょうか?
>>705 今端末さわれる場所にいないからなんとも言えんが、
select hash, name, size from table_name where name != (select name from table_name group by name, size having count(*) >1) and size != (select size from table_name group by name, size having count(*) >1);
で、いいのか?
汚いな...
>>705 select distinct on (name, size) hash, name, size from table_name;
おやすみ。
>>707 それポスグレだろ。
select hash,name,size from table_name group by name,size
でいける。他だと動かないみたいだけど。
それ動くのかよw
むちゃくちゃだな
SQLserver2005の処理で一つ教えてください。
2つの同じ項目のビューがあり、それを一つのビューにマージしようと思っています。
ただある項目が重複した場合は重複データを破棄したいのですが
UNIONだとキー以外の項目が違っていたら別データ扱いですし、
UNION ALLでは問答無用で入ってしまいます。
重複キーを指定してマージすることはできるのでしょうか?
>>710 なんかデジャヴだな
キーが同じでキー以外の項目が違う場合はどのデータを残すん?
select id, value from union_parts_1
union all
select id, value from union_parts_2 where not exists (select * from union_parts_1 where union_parts_2.id = id)
とか?
>>711 破棄だから、重複したデータは結果から削除じゃないのか?
>>710 select id,value from table1 where id not in (select id from table2)
union all
select id,value from table2 where id not in (select id from table1)
で行けると思う。ためしてないけど
重複コードを破棄しちゃいかんだろ。
1つ残すととらえるのが自然だと思う。
そう読むのが自然な気はするけどどっちを残せばいいのかわからん。
キー以外のカラムも同じならどっちでもいいんだろうけどそうでは無いんだよね?
>>714,715
どちらかのテーブルのデータ残すなら
>>712で行けるんじゃないか
両方消すなら
>>713 それ以外なら
>>710の説明不足
やりたいことをちゃんと説明できないのは
自分自身も何をどうしたいのかはっきり分かってないって事だろうな
こういうの、どうすればうまくいきますか?
テーブル
日付 | 数量
---------------
2009-6-10|1000
2009-6-11|2000
2009-6-13|3000
2009-7-10|1100
2009-7-13|1200
2009-7-15|1300
取得したい表(同日を比較したい)
当月 数量 前月 数量
-------------------------------
2009-7-10|1100|2009-6-10|1000
2009-7-11|1100|2009-6-11|2000 2009-7-11は無いため2009-7-10のデータをセット。
2009-7-13|1200|2009-6-13|3000
2009-7-15|1300|2009-6-15|3000 2009-6-15は無いため2009-6-13のデータをセット。
>>720 先月との比較を曜日で合わせてる?
日付対応のルールが明確でないと色々厳しいと思うけど。
>>720 PostgreSQL用、つっても汎用的に書いたつもりだが、
INTERVAL型指定とかEXTRACT(=date_part)なんかはお使いのDBに合わせてな。
SELECT
CASE WHEN T1.日付 IS NULL THEN T2.日付-INTERVAL'1 MONTH' ELSE T1.日付 END AS 当月,
CASE WHEN T1.数量 IS NULL THEN (SELECT 数量 FROM Table WHERE 日付 = (SELECT max(日付) FROM Table WHERE 日付 < T2.日付+INTERVAL'1 MONTH')) ELSE T1.数量 END AS 数量,
CASE WHEN T2.日付 IS NULL THEN T1.日付+INTERVAL'1 MONTH' ELSE T2.日付 END AS 前月,
CASE WHEN T2.数量 IS NULL THEN (SELECT 数量 FROM Table WHERE 日付 = (SELECT max(日付) FROM Table WHERE 日付 < T1.日付-INTERVAL'1 MONTH')) ELSE T2.数量 END AS 数量
FROM (SELECT * FROM Table WHERE EXTRACT(MONTH FROM 日付) = EXTRACT(MONTH FROM NOW())) AS T1
FULL JOIN
(SELECT * FROM Table WHERE EXTRACT(MONTH FROM 日付) = EXTRACT(MONTH FROM NOW()-INTERVAL'1 MONTH')) AS T2
ON EXTRACT(DAY FROM T1.日付) = EXTRACT(DAY FROM T2.日付);
実用的な速度が得られるかどうかしらんよ。
07/01とか06/01のデータが無い場合が厄介だな
724 :
722:2009/07/29(水) 16:48:22 ID:???
訂正
SELECT
CASE WHEN T1.日付 IS NULL THEN T2.日付+INTERVAL'1 MONTH' ELSE T1.日付 END AS 当月,
CASE WHEN T1.数量 IS NULL THEN (SELECT 数量 FROM Table WHERE 日付 = (SELECT max(日付) FROM Table WHERE 日付 < T2.日付+INTERVAL'1 MONTH')) ELSE T1.数量 END AS 数量,
CASE WHEN T2.日付 IS NULL THEN T1.日付-INTERVAL'1 MONTH' ELSE T2.日付 END AS 前月,
CASE WHEN T2.数量 IS NULL THEN (SELECT 数量 FROM Table WHERE 日付 = (SELECT max(日付) FROM Table WHERE 日付 < T1.日付-INTERVAL'1 MONTH')) ELSE T2.数量 END AS 数量
FROM (SELECT * FROM Table WHERE EXTRACT(MONTH FROM 日付) = EXTRACT(MONTH FROM NOW())) AS T1
FULL JOIN
(SELECT * FROM Table WHERE EXTRACT(MONTH FROM 日付) = EXTRACT(MONTH FROM NOW()-INTERVAL'1 MONTH')) AS T2
ON EXTRACT(DAY FROM T1.日付) = EXTRACT(DAY FROM T2.日付);
当月、前月の日付を表示する部分で、対応する日付がない場合の表示を±逆にしていた。
>>723 それはこのSQLだと前月最終データからとってくるだけなんだけど、
7月31日の前月データは6月30日('2009-07-31' - '1 month' の値次第)になる。
725 :
NAME IS NULL:2009/07/29(水) 19:27:46 ID:JrJvF1CD
一つのSQL文内に、同じSELECT文が何度も出てくる場合、
あらかじめSELECTした結果に別名をつけておいて、
それを使い回すことってできますか?
>>725 WITH句をサポートするDBMSならそれで
なければVIEWで
一時テーブルかなー
728 :
725:2009/07/29(水) 22:29:26 ID:???
ありがとうございます。
一文中では無理な感じでしょうか。
SELECTしか使えない環境なので、一文でなんとかしたかったのです。
PostgreSQLなのですが、DBMSはよく分かりません。
SELECTしか使えない環境・・・? Accessか何かか?
そこでSQLインジェクションですよ
内容によってはなんかできるかもしれないけど、それだけだとちょっと難しいよね
>>728 PostgreSQLは最新の8.4からWITH句をサポート
初めて質問するので書き方が間違っていたらごめんなさい。
・MySQL 4.1
maintable
mid | field1 | field2
---------------
5 | 2 | 4
6 | 1 | 5
・
・
・
subtable
sid | tema
----------
1 | その1
2 | その2
3 | その3
4 | その4
field1=sid,field2=sidとして結合なり置換して
mid | tema1 | tema2
-------------------
5 | その2 | その4
6 | その1 | その5
・
・
・
としてselectすることはできるのでしょうか。どうかよろしくお願いします。
>>733 SELECT T1.mid,T2.tema,T3.tema
FROM maintable AS T1
LEFT JOIN subtable AS T2 ON T1.field1=T2.sid
LEFT JOIN subtable AS T3 ON T1.field2=T3.sid;
735 :
nanasi:2009/07/30(木) 06:17:30 ID:suQVAKTQ
736 :
NAME IS NULL:2009/07/30(木) 11:05:29 ID:72K2TDMo
ほんと基本的な質問ですみませんが、テーブル定義書において、タイプ記述方法を調べたいのです。
CHAR,NUMERIC,DECIMALなどを書く方法もありますが、それ以外の方法(特に今回知りたいのは0,S,A,Oと書く方法)について、
教えていただけないでしょうか。
サイトの紹介でも結構です、よろしくお願いいたします。
回答またはアドバイスをお願いいたします。
長文ですみません。
MySQLを使用しています。
[テーブルの項目]
・ID(主キー):数値(AUTO_INCREMENT)
・KEYWORD:文字列
・USER_ID:数値
・ENABLE_FLG:有効/無効設定フラグ (TRUE/FALSE)
[前提]
・ユーザはキーワードをデータベースにいくつでも登録できる。
・ユーザはそれぞれのキーワードに対して、有効/無効を設定できる。
・同じキーワードを別のユーザが登録することができる。
・1人のユーザが同じキーワードを2つ以上登録することはできない。
[取得したい情報]
・指定した複数のキーワードを全て登録しているユーザ(USER_ID)を知りたい。(AND検索)
(キーワードが有効になっていることが条件)
・条件を満たしている全てのUSER_IDを取得する。
検索するキーワードが'AA'と'BB'の場合は
↓のようになりますよね?
SELECT USER_ID FROM KEYWORD_TBL
WHERE KEYWORD == 'AA' AND ENABLE_FLG == 'TRUE'
AND USER_ID IN
(SELECT USER_ID FROM KEYWORD_TBL
WHERE KEYWORD == 'BB' AND ENABLE== 'TRUE');
キーワードが3つ以上だった場合(AA,BB,CC)は、
WHERE句と副問い合わせを伸ばすしかないでしょうか?
'AA','BB','CC'を登録してあるUSERを選ぶ、
という処理のスマートな書き方を教えてください。
select user_id from keyword_tbl where keyword in ('AA', 'BB', 'CC')
group by user_id having count(*) = 3
とか?
実際に確認してないけれども。
>>738 なるほど!その手がありましたか。
参考になりました。ありがとうございます。
MySQLで、ある数値がカンマ区切りで数値の入っているフィールド
nums(text型)に含まれるかを判断するWHERE文を書きたいのですが、
どう書いたら良いでしょうか。
ANDで絞り込み条件として使いたいのですが、思いつきません。
イメージとしてはこんな感じです(128がnumsに含まれるレコード抽出)。
SELECT * FROM test WHERE 128 IN(nums);
どうか知恵をお貸しください。
>>740 SELECT * FROM test WHERE nums REGEXP concat('(^|,','128','(,|$)');
かな? 自信なし。
書き込んでから気づいた。直書きならわざわざconcatで連結する必要ないな。
nums REGEXP '(^|,)128(,|$)';
743 :
NAME IS NULL:2009/07/30(木) 20:57:26 ID:EY3peTrf
postgreSQLで、
日付の差分を値の補正に使いたいのですが、
日付の差分を値に掛けると XXXX day みたいな日数表示になってしまいます。
この日数型を整数にするにはどうすればいいでしょうか。
>>743 EXTRACT(DAY FROM INTERVAL型)
745 :
743:2009/07/30(木) 21:22:24 ID:???
調べたらextractというのがありました。
(extract(year FROM age(日付1,日付2)) * 365) +
(extract(month FROM age(日付1,日付2)) * 31) +
(extract(year FROM age(日付1,日付2)))
これに月の日数と閏年の判定をいれれば、ゴリ押しでとれなくもないですが。。。
746 :
743:2009/07/30(木) 21:31:47 ID:???
>>744 extract(day FROM (日付1-日付2)) で日数とれました。
ありがとう。
747 :
740:2009/07/30(木) 21:36:55 ID:???
>>741-742 早速のレス有難うございます。
レスが遅くなり申し訳ありません。
ただいま確認したところ、期待通りに動きました。
大変助かりました。有難うございました。
748 :
NAME IS NULL:2009/08/01(土) 01:13:32 ID:QhJyGjWf
私は、ある素材生地を扱っている者です。
加工賃の計算でSQLを使用したいと思っておりますが、
エクセル見たく上手いことができず、
お教えいただきたく質問させていただきました。
横(50〜200)は生地の幅、縦(100〜500)は生地の長さで
枠(3〜30)は生地をカットする加工賃を表しています。
MM | 50| 75|100|150|200
---+---+---+---+---+---
100| 3| 5| 8| 10| 15
150| 5| 7| 10| 13| 18
200| 8| 11| 15| 20| 21
300| 10| 15| 18| 21| 24
400| 12| 16| 20| 23| 26
500| 15| 18| 24| 27| 30
(例1)幅が100、長さが200のときの加工賃は15となる。
(例2)幅が80、長さが250のときの加工賃は18となる。
(例3)幅が175、長さが428のときの加工賃は30となる。
抽出するクエリを教えて下さい。お願い致します。
それだと、長さで抽出するしかないね。
長さ n として、n <= MM で、かつ、一番小さい奴を取ってくる。
どうせなら、
長さ | 幅 | 加工賃
ってテーブル構造にしとけばいいのに。
>>748 抽出するクエリより、まずテーブル構造考えないとダメじゃないか
まず考えたテーブル示してくれ
あとSQL使うデータベースは何を使うんだ?
これを見てくれ こいつをどう思う?
長さランクテーブル 幅ランクテーブル
ランク|長さ1|長さ2 ランク|幅1|幅2
1 | 0|100 1|0|50
2 |100|150 2|50|75
3 |150|200 3|75|100
4 |200|300 4|100|150
5 |300|400 5|150|200
6 |400|500
加工賃テーブル
幅ランク|長さランク|加工賃
1|1|3
1|2|5
中略
5|5|26
5|6|30
SELECT 加工賃 FROM 加工賃テーブル
WHERE 長さランク=(select ランク from 長さランクテーブル where 長さ1<ながさ and ながさ<=長さ2)
AND 幅ランク=俺の尻の穴に貴方の野太いアー
>>751じゃランクを細分化したくなったとき困るだろ
素直に
>>749で
select min(加工賃)
from TableName
where 長さ >= 注文された長さ
and 幅 >= 注文された幅
で初めてか?力抜けよ
>>752 の方法でいけるね。
ちなみに同表をクエリで得るにはPIVOTを使う。
USE [MyDB]
GO
CREATE TABLE [dbo].[PriceTable](
[width] [int] NOT NULL,
[length] [int] NOT NULL,
[payment] [int] NOT NULL
) ON [PRIMARY]
GO
SELECT length as 'MM',[50],[75],[100],[150],[200]
FROM
(SELECT length,width,payment FROM PriceTable) AS SourceTable
PIVOT
(
MIN(payment) FOR width IN ([50],[75],[100],[150],[200]))AS PIVOTTABLE
754 :
725:2009/08/01(土) 12:13:14 ID:iuklVi8s
レコードの値と、最大値、データ数などの集約情報とを、
演算したいのですが、例えば、
<得点テーブル>
id|得点
--------
1|100
2| 50
3| 70
SELECT id, (得点/MAX) AS 最大値との比率
FROM 得点テーブル, (SELECT MAX(得点) FROM 得点テーブル) AS 最大値
このSQLでは最終結果を出すときと、最大値を出すときで、
得点テーブルを2回フルスキャンしてる気がするのですが、
このSQLを効率化することってできないでしょうか?
得点にインデックスが張ってあれば
SELECT MAX(得点) FROM 得点テーブル
の部分はフルテーブルスキャンにはならないだろ
756 :
725:2009/08/01(土) 12:47:46 ID:iuklVi8s
まあそうなんですが、上のは簡単化した例えです。
実際は得点テーブルってテーブルは無くて、
得点テーブルの部分にはさらに副問い合わせが入ります。
こういう場合に、2回SELECTをしないで済む方法があれば教えて下さい。
じゃあ
select A.ID,
A.得点 / max(B.得点)
where 得点テーブル A
cross join
得点テーブル B
group by A.ID,
A.得点
とか?
こっちのほうが遅そうだけど
758 :
725:2009/08/01(土) 13:14:36 ID:???
SELECT2回しなけりゃいいって問題じゃねえw
効率化したいんです。
そりゃ情報小出しにしてりゃそうなるわな
無い。
トリガを使って出入りを監視すれば。
761 :
725:2009/08/01(土) 13:24:39 ID:???
『得点テーブル』は副問い合わせ結果なんだけど、
その副問い合わせが、中でさらに8回くらい副問い合わせしていて重い。
だから、2回同じことをやらずに済む方法があれば知りたいのです。
ちなみに、WITHは使えません。
762 :
725:2009/08/01(土) 13:29:40 ID:???
>>760 どうもありがとう。
他のところでチューニングしてみます。
SQLを見直すか、インデックスを見直すか、テーブルを再設計するか。
悩ましいね。
764 :
NAME IS NULL:2009/08/01(土) 21:36:16 ID:qL1wMwr+
先輩方、質問させてください。
例えばこんなテーブルがあったとします。
A B C
┌──┬──┬──┐
│ │身長│体重│
│佐藤│180 │ 80 │
│鈴木│170 │ 70 │
質問1
ABCの列はフィールドとカラムどっちが正しい呼び方?
質問2
Aのようなプライマリーな列は何と言うのですか?
どっちが正しいっていうか
カラムとロウ
列と行
フィールドとレコード
属性とタプル
みたいに組み合わせを間違わなければ何でもいいかと。
リレーションの中でタプルを一意に識別できる属性または
属性の組み合わせは候補キーという。
候補キーの中でひとつを選んでプライマリキーとする。
ちなみに氏名じゃ一意性に欠けるから普通は候補キーにならない。
766 :
764:2009/08/01(土) 22:00:55 ID:qL1wMwr+
>>765 なるほど。ありがとうございます。
カラム(列)
ロウ(行)
フィールド(属性)
レコード(タプル)ってことですよね?
質問2の答えは候補キーですか。英語でなんて言うんだろ?Candidate keyでいいのかな。
氏名を候補キーにするのは通常しないって。
同姓の人なんていくらでもいるでしょ。
プライマリキーになれるのは、Nullじゃなく一意なカラムだけですよ。
候補キーになるかどうか判断するんであって、「候補キーにする」もんじゃないね。
769 :
764:2009/08/02(日) 03:54:10 ID:???
>>767 すみません。
都道府県や数値を書くべきでした。
ただの例なので一切つっこまれないと高を括っていましたが、甘かったです。
2chを舐めすぎていました。反省します。
ちょっと舐めるくらいにしておけ
例がおかしかったらつっこまれるのは2chに限った話じゃない
ただまぁ、質問の前提情報が不足してるってのも、そこを勝手に判断して
思い込みで回答したり突っ込み入れたりするのも同じ穴の狢なんだよな。
>>764がもし全国の苗字毎の平均身長、体重の集計データとかだったら
何もおかしなことはない。
そんな特殊例なんて無視するのが当然だろ。
何言ってんの?w
そんなデータ誰が欲しがるんだよ。
頭おかしいとしか思えないw
そりゃ、
>>772は単なる例だから。
ただ、分析や設計をする立場の人間なら、
>そんなデータ誰が欲しがるんだよ。
というように、書いてもいないことを思い込みで勝手に判断するのは
戒めるべきだってこと。
違うだろ。
わけのわからない要求があがってきたら、それを客と話し合って相談する。
>>772みたいに勝手に想像をふくらませて「ありえないことないな」と判断するほうが危険だろ。
新入社員か?
勝手に判断するなって書いてんのに、なんで「ありえないことないな」と判断したことになるんだよw
>>773 ワインバーグは「奇跡はどこにでも存在する」と書いているが、同じような意味で
現実の案件はみんな特殊例と言ってもいいかもね。
まあまあ。
きっとジンバブエのフリー家計簿ソフトが今も正しく動くのかについて考えないか
いろいろ書いてる途中でKITTがのこってしまいました。
780 :
710:2009/08/04(火) 17:14:06 ID:???
>>711-719 せっかくレスいただいたのにレス返していなくてすいません。
言いたかった事はAとBというビューをマージし、Cというビューを作ろうと思ったのですが
AとBで重複しているレコードがあり、それは片方だけCに持って行きたかったんです。
ただAとBで若干内容が違っている項目があるので、それは無視して
主キーのみで重複チェックをかけたかったのですが、その方法がわかりませんでした。
とりあえず教えていただいた式をよく見て試してみたいと思います。
本当に遅くなってしまいましたがありがとうございました。
>>780 うん、それはみんな分かってる。
その上で、重複したときにどっち捨てるのかが分からなかったんだよ。
自分ならビューをマージせず元テーブルをマージするが
783 :
710:2009/08/04(火) 18:48:56 ID:???
早速サンプルを参考に試したら無事できました!
アドバイスありがとうございました。
>>781 すいませんホント言葉足らずで・・・。
どっちが残ってもいいかと思っていたので書いてませんでした。
>>782 確かに本当は余計なものは作りたくなかったのですが
特別な処理のINPUT用にビューが欲しくて別途作ろうとしていました。
ただ単なる重複キーだけを知りたかったら
select
distinct 主キー
from tableA
union
select
distinct 主キー
from tableB
でいいじゃん・・・。
本当に他のデータがどうでもいいならね。
それは何もかも違う
ID HOGE
01 A
01 B
01 C
02 A
03 B
HOGEをAもBもCも持っている、ID:01だけ取り出すにはどうすればよかですか
DISTINCTしたのをCOUNTして3件のヤツとか
groupするんじゃなくて?
いやもちろんGROUPしてCOUNTだけど
先にDISTINCTしとかないとAABとかでも3件だしな。
そういうケースがあるかは知らんけど。
>>786 hogeがA,B,Cの3種類のみでってことなら、
SELECT id FROM Table GROUP BY id HAVING count(DISTINCT hoge) = 3;
hogeが3種類以上あり、そのうちのA,B,Cを有するものなら、結合するしかないかな。
SELECT distinct id FROM
(SELECT * FROM Table WHERE hoge = 'A') AS T1
JOIN
(SELECT * FROM b_test WHERE hoge = 'B') AS T2
USING(id)
JOIN
(SELECT * FROM b_test WHERE hoge = 'C')AS T3
USING(id);
やっぱ商演算テンプレに入れようぜ
これでどう?(標準SQLなのにOracleで動かないというオマケつきだけど)
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
)
)
;
792 :
790:2009/08/04(火) 21:07:30 ID:???
下段のSQL修正
SELECT distinct id FROM
(SELECT * FROM Table WHERE hoge = 'A') AS T1
JOIN
(SELECT * FROM Table WHERE hoge = 'B') AS T2
USING(id)
JOIN
(SELECT * FROM Table WHERE hoge = 'C')AS T3
USING(id);
existsもjoinも汚いんだよな。
もう少しなんとかなりそうなんだが。
794 :
790:2009/08/04(火) 21:21:56 ID:???
>>793 そういわれて、思いついたSQL
SELECT id FROM b_test WHERE hoge in ('A','B','C') GROUP BY id HAVING count(DISTINCT hoge) = 3;
795 :
790:2009/08/04(火) 21:24:47 ID:???
あ、id=1でDも持っている可能性があるから、ABC"しか"じゃなくてABCを持っているなら
HAVING countDISTINCT hoge) >= 3;
ですね。
WHERE hoge in ('A','B','C') と書いてるのに?
797 :
790:2009/08/04(火) 21:27:45 ID:???
>>796 そうだった...orz
ついでに、
>>791のSQLはPostgreSQLだと
SELECT DISTINCT id
FROM Table T1
WHERE NOT EXISTS (SELECT *
FROM (VALUES('A'), ('B'), ('C')) T2 (hoge)
WHERE NOT EXISTS (SELECT *
FROM Table T3
WHERE T1.id = T3.id
AND T2.hoge = T3.hoge
)
)
;
で動く。
SQLパズルにヒント乗ってそうだが参照するのが死ぬほどめんどくさい。
799 :
738:2009/08/04(火) 22:15:16 ID:???
ABCのどれかが欠けてるやつ以外という逆説手法でいけるのか。
質問主じゃないけど参考になった。
逆説は考えてみたけどNOT A OR NOT B OR NOT Cじゃできなくて諦めたが、NOT EXISTSが正解だったんだな。
>>797にthx。
801 :
NAME IS NULL:2009/08/04(火) 22:47:53 ID:JCPNsOCy
何が知りたいかと言えば、シルバーでダイタイ平均いくらかかりますか?
あとゴールドは?
Oracleだと
>>791の
from (values 'A', 'B', 'C') T2 (HOGE)
の部分は
from (select 'A' as HOGE from dual
union all
select 'B' from dual
union all
select 'C' from dual
) T2
かな?
803 :
786:2009/08/04(火) 23:03:33 ID:???
おお、予想以上の反響でびっくり
みなさんありがとう
hogeの指定は動的なんですわ
やっぱりwhere一発とかじゃ簡単にできないか
明日になっちゃうけど教わったやつ試してみる
>>791はSQLServer2008でも動かないんだが。
>>803 動的ってことは別テーブルに条件保存したら、その方が簡単な気が
select ID from (
select テーブル.ID,テーブル.HOGE from 条件 join テーブル on 条件.HOGE=テーブル.HOGE) as T
group by ID
having COUNT(*) = (select COUNT(*) from 条件)
テーブルの(ID,HOGE)がユニークならこれで行けるっぽ
806 :
NAME IS NULL:2009/08/05(水) 04:33:07 ID:RB7uuMhx
PostgreSQL8.1 です。
シーケンスを含むDB を pg_restore したのですが、そのシーケンスに対する curval の取得が失敗します。
一度 nextval 等で値を取得すれば curval も取得できるようになるのですが、こういうものでしょうか?
CREATE SEQUENCE したばかりのシーケンスの curval が取得できないのと同じような感じです。
怪盗1412号を怪盗KIDと読むくらい無理があるな
>>807 作り直すの意味するところが掴みかねるが
条件に対応するレコードをセットするわけで、テーブルそのものを作り直す必要はないが
たとえば条件がA,B,Cなら、条件テーブルにA,B,Cの3レコードセットしとく
SELECT文を発行するたびにそれをやるのはなぁ。
じゃあ条件に合わせて毎回SQL作り直すか?
普通にSQL動的に作った方が楽じゃね?
条件の個数が固定なら動的SQLでもいいかもしれん
条件の個数が変わるなら動的SQLのが大変じゃないかな
まあ、状況次第だな
個数がどうであるかは大した問題ではないけれど
delete→insert(またはその逆)は大変面倒な気がする。
そんなことをするくらいなら一時テーブルを作る方が
よほどいいんじゃないかと思うのは俺だけ?
Oracle 10g で質問です。
UPDATE文でテーブルの指定の列 (カラム)全てを
順番にAでアップデート、Bでアップデート、Cでアップデート
みたいに3パターンのアップデートを繰り返し
3000件あったとしたらAで1000件、Bで1000件、Cで1000件
見たいな感じにしたいのですが
どうすればよいでしょうか?
ご指導をお願い致します
1000件ずつにきちんと分けれたらいけるだろ。
テーブルの構成を書かないならこれ以上はアドバイスできない。
ROWNUM
819 :
NAME IS NULL:2009/08/08(土) 15:53:09 ID:ZMe9F3VY
SQLITEでテーブルに入ってる列の名前を表示させるSQL文を教えてください
.help にヒントがあるようにおもう >> 819
>>817-818 説明不足スミマセン
ROWNUMで解決しました
ありがとうございました
MySQL 5
テーブル
data1 data2 data3
a あ 100
b あ 150
c あ 130
d あ 190
b い 120
c い 180
a い 160
d い 110
c う 140
b う 115
d う 125
a う 155
欲しい結果
あ い う
a 100 160 155
b 150 120 115
c 130 180 140
d 190 110 125
こういうのってSQLで出来るのでしょうか?
3列固定なら簡単にできる。
動的なら難しい。
>>823 > 3列固定なら簡単にできる。
> 動的なら難しい。
>
レスどうもです
列は固定です
>>822 data1、data2の組み合わせでユニークになるのなら
select
data1,
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'あ') as "あ",
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'い') as "い",
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'う') as "う"
from テーブル t
group by data1
3列固定で、かつ
あ い う
a 100 160 155
b 150 120 115
c 130 180 140
d 190 110 125
みたいな取得をしたいんだったらテーブルの作りを変えるのも考慮してみては
>>826 ありがとうございます
テーブルの構造を作り変えることも検討したいと思います
828 :
827:2009/08/10(月) 22:29:14 ID:???
select
data1,
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'あ') as "あ",
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'い') as "い",
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'う') as "う"
from テーブル t1
group by data1
Subquery returns more than 1 row
となるのですがどうしてでしょうか・・・
select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'あ'
は、このSELECT文で欲しい値が返ってくることは確認しました
select data3 from テーブル t1 where t.data1 = 't1.data1' and t1,data2 = 'あ'
と t1.data1 にシングルクォートを付けると処理は正常終了しますが
当然ですが、結果は data3 は NULL が返されてしまいます
教えていただいた SQL に間違いはないと思うのですが
何が悪いのか教えていただけないでしょうか
>>828 3つのサブクエリの最後、
and t1(カンマ)data2 = 'あ'
になってる。
どっちも t1?
読んだ通りのエラーだよ。
select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'あ'
select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'い'
select data3 from テーブル t1 where t.data1 = t1.data1 and t1,data2 = 'う'
この3つのSQLのいずれかが複数件の結果を返してしまっているということ。
構文エラーにならないんだねえ。
where句のカンマ演算子ってどういう扱い?
833 :
827:2009/08/10(月) 22:55:04 ID:???
>>829 select
data1,
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1.data2 = 'あ') as "あ",
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1.data2 = 'い') as "い",
(select data3 from テーブル t1 where t.data1 = t1.data1 and t1.data2 = 'う') as "う"
from テーブル t1
group by data1
結果変化ありませんです
>>830 >>822 に書いたとおり全てのデータがひとつのテーブル内に記述されてるんです
mysql5でできるかはわからんが
MSSQLの解
SELECT data1 as 'data1',[あ],[い],[う]
FROM
(SELECT data3,data1,data2 FROM Table1) AS SourceTable
PIVOT
(
MIN(data3) FOR data2 IN ([あ],[い],[う]))AS PivotTable
>>825が間違ってるね。まぁすぐ気づきそうだけど、俺も828で気づかなかったしw
正しくはこうか。
select
data1,
(select data3 from テーブル t2 where t2.data1 = t1.data1 and t2.data2 = 'あ') as "あ",
(select data3 from テーブル t3 where t3.data1 = t1.data1 and t3.data2 = 'い') as "い",
(select data3 from テーブル t4 where t4.data1 = t1.data1 and t4.data2 = 'う') as "う"
from テーブル t1
group by data1;
別解。
SELECT T0.data1 AS T0 ,T1.data3 AS あ ,T2.data3 AS い ,T1.data3 AS う FROM
(SELECT data1 FROM テーブル GROUP BY data1) AS T0
LEFT JOIN
(SELECT * FROM テーブル WHERE data2 = 'あ') AS T1 ON T0.data1 = T1.data1
FULL JOIN
(SELECT * FROM テーブル WHERE data2 = 'い') AS T2 ON T0.data1 = T2.data1
FULL JOIN
(SELECT * FROM テーブル WHERE data2 = 'う') AS T3 ON T0.data1 = T3.data1;
836 :
835:2009/08/10(月) 23:00:44 ID:???
俺も間違ってる。
別解の1行目。
×SELECT T0.data1 AS T0 ,T1.data3 AS あ ,T2.data3 AS い ,T1.data3 AS う FROM
○SELECT T0.data1 AS T0 ,T1.data3 AS あ ,T2.data3 AS い ,T3.data3 AS う FROM
ちゃんと実行してから書け
838 :
827:2009/08/10(月) 23:08:43 ID:???
みなさん ありがとうございました!
できました
感謝します
勉強しないといけないです・・・ orz
839 :
NAME IS NULL:2009/08/11(火) 15:37:39 ID:pDd9m9X6
今月の誕生日の人の検索はどうすれば良いでしょうか?
誕生日はYYYY-MM-DDの形式で保存されております
%08%や____08__などやってみてもだめでした。
どのDBMSでも月を取得できる関数が何かしら用意されてるはず
もし無ければ文字列に変換して比較
842 :
839:2009/08/11(火) 16:00:33 ID:???
ありがとうございます。
MySQL 5.1.37 Windows
MySQLで勉強している最中なんですけど、教えてください
select now();で
2009-08-11
select extract(year_month from now());で
200908
が返ってくるのはいいんですけど、そこに01を連結して
20090801が返ってきて欲しくて
select concat(extract(year_month from now()),01)とすると
2009081になってしまいます。
20090801にしたいのですが、どうすればいいのでしょうか
>>843 クォーテーションで括ればよくね。
select concat(extract(year_month from now()),'01');
他、
SELECT DATE_FORMAT(CURRENT_DATE,'%Y-%m-01');
845 :
843:2009/08/11(火) 20:40:19 ID:???
846 :
703:2009/08/12(水) 12:36:16 ID:???
>>708 今更ですが、無事動きました。
この記述はSQLiteオンリーなのでしょうか?
Select句にhashがあんのにGroupBy句にないから普通ならエラーだな。
「ありがとうございました」と言え
あー、あざーす
DBMS名: PostgreSQL 8.3系
データ
id | date | memo
---+------------+------
1 | 2009-12-22 | test1
2 | 2009-12-23 | test2
3 | 2009-12-24 | test3
4 | 2009-12-24 | test4
5 | 2009-12-25 | test5
test1があったらこれ
id | date | memo
---+------------+------
1 | 2009-12-22 | test1
test2があったらこれ
id | date | memo
---+------------+------
2 | 2009-12-23 | test2
test3があったらこれ
id | date | memo
---+------------+------
3 | 2009-12-24 | test3
上記のテーブルより
一度に"test1"、"test2"、"test3"の条件を指定してデータを抽出する際、
どれか1パターンのみのデータを抽出したいのですが
可能でしょうか?
優先順位とか関係ないなら、in ('test1', 'test2', 'test3') で、TOP 1。
PostgreSQL で使えるか知らんけど。
rder by memo = 'test3', memo='test2', memo='test1' limit 1
とか、、苦しいか
本当に test1, 2, 3 の優先順位ならば ORDER BY memo LIMIT 1 だけでいけそう。
もっと複雑ならば ORDER BY CASE memo CASE 'test1' THEN 1 CASE 'test2' THEN 2 ... END LIMIT 1 とか。
一応、こんな感じでまとめた。
select
*
from
table1
where
memo = 'test1'
union all
select
*
from
table1
where
memo = 'test2'
and (select count(*) from table1 where memo = 'test1') <= 0
union all
select
*
from
table1
where
memo = 'test3'
and (select count(*) from table1 where memo = 'test1') <= 0
and (select count(*) from table1 where memo = 'test2') <= 0
相当おかしい感じがするのは気のせいと思っている
気のせいじゃないよ。
Oracle10gで
○○都○○市〜〜
○○○県○○市〜〜
のように住所が入っているaddress列から
都道府県名だけを抽出したい場合
どんな文を書けばいいんでしょうか
それはSQLの仕事じゃ無いような・・・
REGEXP_SUBSTRでもつかえば?
簡単なのは正規表現を使って、
REGEXP_REPLACE(address,'^(...*?(都|道|府|県)).*$','\1')
かなあ・・・パフォーマンス悪いだろうなあ
頻繁に発生するなら都道府県マスタ作って前方一致で結合して…とかがいいかも
>>859 それだと京都府が...
PostgreSQL用だけど、要は正規表現で関数は書き直して。
SELECT substring(address , '^(.*?(東京都|道|府|県))') FROM Table;
>>860 前方一致で1行ごとに47都道府県と比較するのと正規表現とどちらが速いだろうな。
'京都府'はいけるように作ったぞ
全部の都道府県をテストしたわけじゃないが
>>862 スマソ ...*? 頭の..を見逃していた。
抽出はREGEXP_SUBSTRを使えばいいのか・・・
勉強になるわあw
というか都道府県なんて50も無いんだから手で抽出(というか記述?)した方が早くね?
>都道府県なんて50も無い
それは856の抽出結果が50しかないということを意味する訳ではないし
何度もやるかもしれない
都道府県とは書いてあるが、市区町村まで分けようとしてるんじゃないの?
868 :
NAME IS NULL:2009/08/14(金) 23:59:57 ID:TqQmlfGr
カラム
a char (4) not null
b decimal(4) not null
がある場合、
条件句で
'2000' < a
と
2000 < b
はどちらが速いでしょうか?
(データとインデックスは同じ)
後者の方が速いでしょ。
aにインデックスがある
bにインデックスがある
の2つを比べるなら一緒でしょ
871 :
NAME IS NULL:2009/08/15(土) 15:55:43 ID:c8dfsvTH
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
前回の衆院選の投票率は
小選挙区が67.51%
比例代表が67.46%
次の衆院選は
めざせ投票率72%!
 ̄ ̄∨ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
∧_∧ ∧_∧ age
(・∀・∩)(∩・∀・) age
(つ 丿 ( ⊂) age
( ヽノ ヽ/ ) age
し(_) (_)J
◆◆◆投票率ageageブラザーズ◆◆◆
72.1%じゃあかんの
DBMS名: PostgreSQL 8.3系
データ
key1|key2 | date
---+------+------------
0001|001 | 2009-12-22
0001|002 | 2009-12-24
0001|003 | 2009-12-24
0002|001 | 2009-12-24
0002|002 | 2009-12-25
上記より
key1|key2 | date
---+------+------------
0001|001 | 2009-12-22
0002|001 | 2009-12-24
key1とkey2でユニークなキーになりますが
key1のキー単位に1件ずつ抽出したいのですが?
key1 は group by で求めるとして、key2 はどういう基準なの?
key2、dateはkey1に紐づくデータで特に指定はないです
すみません。すっかり忘れてました。
ありがとうございます。
>>873 PostgreSQLならDISTINCT ONで
SELECT DISTINCT ON (key1) * FROM Table;
普通ORDER BYと組み合わせるがな。
879 :
NAME IS NULL:2009/08/21(金) 01:37:47 ID:xrxomkXj
テーブルabc( id , create_date , flag )に1万件のデータが存在します。
create_dateでソートした先頭の千件以外にflag=1をセットするにはどうすれば良いでしょうか。
副問い合わせ使って1度にやりたいのですが上手くできません。
データベースはPostgreSQL(8.3)です。
update abc set flag=1 where id = (select id from abc order by create_date desc limit 1000);
〜以外というのができれば良いのですが・・・
ポスグレさわったことないけどNOT EXISTS
881 :
NAME IS NULL:2009/08/21(金) 01:45:55 ID:xrxomkXj
>>880 おぉ、こんな便利なものが。やってみます!
882 :
NAME IS NULL:2009/08/21(金) 03:18:54 ID:xrxomkXj
Postgresqlの場合はNOT EXISTSではなくてNOT INでした。
update abc set flag=1 where id not in (select id from abc order by create_date desc limit 1000);
上で行けました!
883 :
NAME IS NULL:2009/08/21(金) 03:28:06 ID:xrxomkXj
PostgreSQLにはNOT INもNOT EXISTSもあるよ
NOT INでパフォーマンスが問題になったらNOT EXISTSに置き換えるのが手っ取り早い
DB初心者です。すごく初歩的な質問かもしれませんがよろしくお願いします。
■以下環境
・DBMS:SQL Server2005 Express & Management Studio
・テーブルのある列には、数字+文字(例.1日目、2日目、5日目)などの
値が格納されています。
・欲しい結果:数字+文字の[数字部分]のみをビューの列に格納したいと
考えています。
■質問
ビューの指定列に関数などを使用して数字のみ取り出すことは可能でしょうか?
無理な場合、どのようなSQL構文を書けば実現可能でしょうか?
replaceで'日目'を''に、とか。
>886
replace(指定列,'日目','')で、できました!
とりだした部分を使って数値計算がしたく、
文字部分が邪魔でどうすればいいか悩んでいたのですが、
すっきりしました!
ありがとうございます!
どういう使い方してるかわからんからアレだけど
一般的にはテーブルに「日目」を付けない状態で格納する。
金額に「円」つけて格納してたりして
格納は別の人がやってるor既存データ
とかなんでないの?
よくあること。
891 :
885:2009/08/21(金) 23:23:50 ID:???
>890
おっしゃるとおりです。
別のアプリケーションでデータをテーブルへ格納するので、
そこからビューを作って特定の列どうしを計算したりするつもりでした。
テーブルの中身をさっさと修正した方が今後の為に良いように思うけどなぁ
| A | B | C |
――――――――
| 1 | 1 | a |
| 1 | 2 | b |
| 1 | 3 | c |
| 2 | 1 | c |
| 2 | 2 | b |
| 2 | 3 | a |
| 2 | 4 | c |
| 3 | 1 | b |
| 3 | 2 | a |
| 3 | 3 | c |
こういう時に
Cの値を複数指定してそれがBで指定した順に連番になっているときだけAを抽出する
というSQL文って書けますでしょうか?
複数しているCの値を cb とした場合
抽出されるのは2だけとなります
select T1.A
from TableName T1
inner join
TableName T2
on T1.A = T2.A
where T1.C = 'c'
and T2.C = 'b'
and T1.B = T2.B - 1
;
とか?
895 :
893:2009/08/23(日) 16:03:22 ID:???
>>894 うまく行きました
本当にありがとうございます
重ねて質問で申し訳ないのですが
現在A,B,C各々にインデックスは張っています
さらに高速化が望めるインデックスの張り方ってありますでしょうか?
>>893 cbで指定したときはA=2ではなくてA=1じゃないのか?
俺なら
A | C
-----
1 | abc
2 | cba
3 | bac
ってテーブルにする。
もうカラムCを横に繋げて持っちゃえよ
ああスマンかぶった
>>895 create index IndexName on TableName (C, B, A);
かな?
やってみんとわからんが
>>894の例だとCの値の数だけSQL作らないといけないな。
動的SQLでもいいが。
>>896-901 いろいろ議論ありがとうございます.
最近まで横に繋げて持ってたんですが,
あまりにも文量が多かったのでSELECTしても
HDDIOが遅いせいでかなり時間がかかっていました
それでなんとか早くする方法がないかと試行錯誤しているところです
>>900 インデックスはってみます
時間がかかるとか、不都合な部分を自分以外に原因を持って行くのは楽だよなあ
>903
気を悪くさせたなら申し訳ありません
select Table.A from Table where match(C) against('cb');
というクエリを実行してUPU使用率はほとんど上がらないまま
一定時間後に値が返ってきたので
HDDIOによるタイムロスと思ってたのですが
他に原因がありそうでしょうか?
いまさらですがMySQLで
メモリは2GBのPCでmysqldに1Gほど割り当てられています
A B C1 C2
1 1 a b
1 2 b c
2 1 c b
2 2 b a
2 3 a c
3 1 b a
3 2 a c
「ac」を探すときは、where c1='a' and c2='c'
「abc」を探すときは、
select T1.A
from Table T1 LEFT JOIN Table t2 ON t1.A=t2.A and t1.A=t2.B-1
where T1.c1='a' and T1.c2='b' and T2.c2='c'
「cbac」を探すときは、
select T1.A
from Table T1 LEFT JOIN Table t2 ON t1.A=t2.A and t1.A=t2.B-2
where T1.c1='c' and T1.c2='b' and T2.c1='a' and T2.c2='c'
そんなテーブルどうやってメンテするんだよ
まあもともとのテーブルも似たようなもんだが
列名はA、B、Cとかじゃないんだろうけど、
もうちょっと相関性のあるデータの入れ方を力説した方が良かったんじゃないかな〜
908 :
NAME IS NULL:2009/08/24(月) 07:10:01 ID:TouBA/nc
SQLiteを使っています。(質問としてはSQL一般です)
趣味のDB設計中に、テーブルとかカラムの構成の仕様がどんどん変わっていくような場合
データの追加・修正・削除を簡単に行う方法はないでしょうか。
GUIのDB操作ツール(PupSQLite等)を使うのが一見よさそうですが、
内部インデックス(ユーザからは見えない)の整合性を取りながら追加・修正・削除を行うのはなかなか面倒です。
トリガーを使って整合性を取り、GUIツールでデータ編集する方法もありますが、
もっと直感的な方法はないでしょうか。
(複数のテーブルの同種のインデックスを関連付けるなどして、簡単にデータ編集できるツールなどないでしょうか)
DB初心者のため、的外れな質問かもしれません。
より適切なスレッドがあれば誘導してください。
よろしくお願いいたします。
インデックスと言っているのは外部キーの事だよね?
Accessで連鎖更新・削除が出来た気がする。
つかここはSQL文のスレだからツールとかはスレ違い。
910 :
908:2009/08/24(月) 08:08:48 ID:???
>インデックスと言っているのは外部キーの事だよね?
はい。SQL用語のインデックスのことではないです。
(SQL用語に"インデックス"があるのを今調べて知りました)
紛らわしくてすみません。
"外部キー"も理解が曖昧で、全く設定していなかったのですが
便利そうなので使ってみます。
>Accessで連鎖更新・削除が出来た気がする。
考えていたことに近いです。
>つかここはSQL文のスレだからツールとかはスレ違い。
やはりツールに依存する機能なんですね。すみません。
初歩的な質問、すいません MySQLです。
日付の入っている列 input_date があります
input_date
--------
2008-12-11
2008-12-15
2009-04-05
2009-04-08
2009-05-10
2009-05-15
2009-07-01
2009-07-05
〜
ここから例えば 2009年4月のデータのみを extract関数で取り出す事って出来ますか?
月初と月末を指定すれば between や <、>を使って出来るのは判るのですが。
質問です。
下記のようなデータがあり、
顧客テーブル
顧客番号 連番 フラグ
00000001 001 0
00000001 002 0 ←
00000002 001 0 ←
00000003 001 0
00000003 002 0 ←
00000004 001 0 ←
各顧客の最大の連番レコード(←)のみフラグを'1'に更新したいのですが、
そのSQLに悩んでいます。
SELECT 顧客番号, MAX(連番) FROM 顧客テーブル GROUP BY 顧客番号
この結果を上手くUPDATE文に絡めたいのですが……
Oracle8iです。よろしくお願いします。
適当に書いたから、動かないかもしれん
update 顧客テーブル set
フラグ = 1
where
顧客テーブル.連番 = (
select MAX(T.連番) from 顧客テーブル T
顧客テーブル.顧客番号 = T.顧客番号
)
row_numberが1のものを更新する
>>914 in句を使って絡めてみた。
update 顧客テーブル set フラグ='1'
where (顧客番号, 連番) in (SELECT 顧客番号, MAX(連番) FROM 顧客テーブル GROUP BY 顧客番号)
どうすか?
918 :
914:2009/08/24(月) 21:57:31 ID:???
>>915 >>917 早速試してみましたところ、いずれの方法でも求める結果が得られました!
みなさんありがとうございました。
919 :
916:2009/08/24(月) 21:58:57 ID:???
シカトかよ
ぷっ
row_numberって、where句に直接使えるんだっけか?
select句にしか使えないんだったら、maxの方が簡単だべ。
個人的には相関サブクエリを薦めるけども。
922 :
NAME IS NULL:2009/08/26(水) 01:12:53 ID:K0v/cQev
select id,(Case when status in ('SWAP','SWAPT') then SUBID else (SUBID*(PRICE/100)) end)::NUMERIC(38,8)
ここで、(Case when ....)::NUMERIC(38,8)というのは何をやっているのでしょうか?
()の中のCASE文の内容をNUMERICに変換しているのでしょうか?
よろしくお願いします。
>>922 CASE文の結果(出力)をNUMERIC(38,8)にキャストですね。
キャスト演算子"::"はPostgreSQLの方言だと思っていたけど、
他にも使えるのかな?
924 :
NAME IS NULL:2009/08/26(水) 01:29:38 ID:K0v/cQev
ありがとうございます。PostgreSQL派生のDBからの質問でした。
オラクルではできない書き方なのですね。
925 :
NAME IS NULL:2009/08/26(水) 03:52:24 ID:K0v/cQev
すいません、もうひとつだけ。
SELECT 'my name'::"NAME";
とやると、
my name
と表示されるのですが、これはいったいなにをやっているのでしょうか?
DB2なんだけど、
品名、日付、数量
A、2009-01、1000
A、2009-02、2000
A、2009-03、3000
B、2009-02、1000
こんなテーブルがあって、下記のような結果を得たい場合は
どんなSQLが考えられますか?
品名、2009-01数量、2009-02数量、2009-03数量
A、 1000、 2000、 3000
B、 NULL、 1000、 NULL
最初のテーブルとほとんど変わってないように見えるけど。
NULLも出したいということ?
勉強中のど素人ですが、強引にやってみたw
こういうのスマートになかなか出来ないなあ
SELECT 品名, t1.数量 "2009-01数量", t2.数量 "2009-02数量", t3.数量 "2009-03数量"
FROM (SELECT * FROM tablename WHERE 日付 = '2009-01-01') t1
FULL OUJTER JOIN (SELECT * FROM tablename WHERE 日付 = '2009-02-01') t2 USING(品名,)
FULL OUJTER JOIN (SELECT * FROM tablename WHERE 日付 = '2009-03-01') t3 USING(品名,)
select 品名,
sum(case when 日付 = '2009-01' then 数量 end) as "2009-01数量",
sum(case when 日付 = '2009-02' then 数量 end) as "2009-02数量",
sum(case when 日付 = '2009-03' then 数量 end) as "2009-03数量"
from TableName
group by 品名
;
931 :
930:2009/08/26(水) 19:05:45 ID:???
ほんとだw
つか文法間違えてない?w
日付もTO_DATEがいりそうな
/)
///)
/,.=゙''"/
/ i f ,.r='"-‐'つ____ こまけぇこたぁいいんだよ!!
/ / _,.-‐'~/⌒ ⌒\
/ ,i ,二ニ⊃( ●). (●)\
/ ノ il゙フ::::::⌒(__人__)⌒::::: \
,イ「ト、 ,!,!| |r┬-| |
/ iトヾヽ_/ィ"\ `ー'´ /
935 :
NAME IS NULL:2009/08/26(水) 23:18:39 ID:cAgACWNL
(Mysql5.0での実行を予定しております。)
enginテーブル(検索エンジンのドメインと、検索ワードの項目名が格納されている)
----------------
エンジン | id |
----------------
google.com | q |
yahoo.co.jp| p |
URLテーブル
-----------------------------
url | search |
-----------------------------
google.com?q=aaaa | |
yahoo.co.jp?p=bb | |
google.com?q=c&u=1 | |
・
・
・
SQL1発で「URLテーブルのsearch列に対応したidの文字を入れ、下記のような状態にしたいです。」
副問い合わせやGROUPBY句などを組み合わせたりして色々考えましたが、解決策が見当たりません。
お分かりになられる方が居られましたらご教授よろしくお願いいたします。
------------------------------
url | search |
------------------------------
google.com?q=aaaa | aaaa |
yahoo.co.jp?p=bb | bb |
google.com?q=c&u=1 | c |
・
・
・
>>935 最後のパターン以外はとれた
確認はSQLiteだけど、MySQLでも多分いけるんじゃない
select d1.url, substr(d1.url, length(v.engine)+1) as search
from URLテーブル d1
cross join (
select d2.engine || '?' || d2.id || '=%' as engine from エンジンテーブル d2
) v
where
d1.url like v.engine;
またまた度素人が(ry
最後の状態を見る限りだと、
最初の'='の後の文字列をsearch列に入れる、
'='のすぐ後の2文字が'c&'ならsearch列に'c'を入れる、
てことでいいのかな?
URLテーブルにナンバリングしたUNIQUEキーをつくって、
相関副問い合わせで、とか^^;
update URLテーブル "URLt1" set serach =
(select case substr(url, instr(url,'=')+1,2)
when 'c&' then 'c'
else substr(url,instr(url,'=')+1)
end
from URLテーブル "URLt2" where URLt1.no = URLt2.no);
お門違いの回答ならすいませぬ。
pやqが?直後に来るとは限らないし、=以後は&か文末が現れるまででしょ。
正規表現で書くなら engineテーブルのidをIDと書くけど。
[\?&]ID=([^&$]*?)
かな。MySQLの文字列連結だとconcat('[\?&]' , id , '([^&$]*?)') な具合だろうけど、
MySQLがどこまで正規表現に対応しているのかしらね。
実際はホスト言語側でURLテーブルに挿入する時点で処理(search分離)しておくべきでしょうね。
940 :
NAME IS NULL:2009/08/27(木) 06:17:03 ID:0vbJ9O4e
>>937-939 >pやqが?直後に来るとは限らないし、目的の項目(例えばq=aaa)以後は&か文末が現れるまででしょ。
おっしゃる通りです。説明不足ですみませんでした。
昨夜まで「あれ?これ無理なんじゃない?」と思ってたんですが
皆様のご提示内容を参考にすると出来そうな感じになってきました。
ありがとうございます!
今日一日空き時間使って悩んでみます!
941 :
939:2009/08/27(木) 06:34:02 ID:???
正規表現間違えていたので、一応訂正しておく。
× [\?&]ID=([^&$]*?)
○ [\?&]ID=([^&$]*)
○ [\?&]ID=(.*?)(&|$)
こんな感じかな。テストしていないけど。
942 :
927:2009/08/27(木) 15:22:35 ID:???
>929,930
ありがと、解決しました。
943 :
935:2009/08/30(日) 13:27:40 ID:IiFjmKoL
>>935です。
すみません、色々試してはみたのですが、なかなかうまくいかず、まだ完成していません。
というのも、肝心のsearch列に値を設定する部分がわからないのです。
例えば、(下記テーブルの例で言うと)
url列の値がgoogle.comの情報ならsearch列にbbbやaaa(q=の後の値)を格納するということがしたいのですが、
「下記SQLの????の部分にbbbとかaaaとかを持ってくる方法」
がわかりません。
UPDATE URLテーブル SET search = ???? where url LIKE '%google.com%'
低レベルな質問ですみませんが、お分かりになられる方がおられましたら
ご教授よろしくお願いいたします。
(pやqが?直後に来るとは限らないし、目的の項目(例えばq=aaa)以後に&が続く場合もある)
URLテーブル
-----------------------------------------
url | search |
-----------------------------------------
google.com?q=bbb | |
google.com?q=aaa&u=1 | |
google.com?u=1&q=ccc&u=1 | |
yahoo.co.jp?p=bbb | |
yahoo.co.jp?p=ccc&d=fff | |
yahoo.co.jp?g=x&p=ttt&t=g | |
↓
※こんな風に更新したい。
-----------------------------------------
url | search |
-----------------------------------------
google.com?q=bbb | bbb |
google.com?q=aaa&u=1 | aaa |
google.com?u=1&q=ccc&u=1 | ccc |
yahoo.co.jp?p=bbb | |
yahoo.co.jp?p=ccc&d=fff | |
yahoo.co.jp?g=x&p=ttt&t=g | |
944 :
935:2009/08/30(日) 15:28:52 ID:IiFjmKoL
うーん、よくよく考えてみれば、これ絶対無理ですよね。
基本的な考え方が抜けてました。
ストアドプロシジャとかカーソルとかを使わない限り、
1回のUPDATE文で1つの列に複数種類の値を設定できないですもんね。
例えば、
aaa
bbb
ccc
という3種類の値を、下記のような1回のUPDATE文でsearchに設定できないですもんね。
(????の所に複数の値を返すサブクエリを書いたらエラーになるし)
UPDATE URLテーブル SET search = ????;
>>943 ググってみたんだけど、MySQLの正規表現で部分抽出や置換が出来そうにないのよね。
出来るのなら、その関数なり演算子のURLを教えてくれたら、わかるかもしれない。
それが出来ないのなら、ホスト言語側で一行ずつ処理するしかないと思う。
>>944 > 1回のUPDATE文で1つの列に複数種類の値を設定できないですもんね。
いや、そのあたりは何とかなりそうな気がする。
947 :
935:2009/08/30(日) 16:05:31 ID:IiFjmKoL
>>945 おっしゃるとおりmysqlの正規表現では不可能なようです。
http://okwave.jp/qa4636418.html >>946 多分無理だと思う。
UPDATE urltable SET search = (複数レコードを返すサブクエリ);
も
UPDATE urltable SET search IN ('f','d','a');
も無理だし。
やはりUPDATEを連続実行する必要がありそうorz
私の知らないテクがあればご教授よろしくお願いいたします。
>>947 945=946なんだが、
> UPDATE urltable SET search = (複数レコードを返すサブクエリ);
こいつはどのDBMSでも無理だが、元質の例えで出てきた範囲ななら
正規表現で抽出することが出来るDB、PostgreSQL等だと
UPDATE url SET search = substring(url from E'[\?&]'||id||'=([^&$]*)') FROM engin WHERE url.url ~('^'||engin.engin);
みたいな感じで可能。
ま、WHERE url.url ~('^'||engin.engin); で一行しか返らないという条件付きな。
949 :
935:2009/08/30(日) 19:30:22 ID:IiFjmKoL
>>948 レスありがとう。
でも、すんませんorz 私のレベルが低すぎて解読できないorz
>substring(url from E'[\?&]'||id||'=([^&$]*)')
fromの後のEとか、substringの引数の指定の仕方とか、UPDATE文にFROMやWHEREがあるところとか。
多分上級者の人ならピンと来るんだと思うんですが、できれば若干の解説を・・・。
orz
下記のような空白交じりの情報を出力するとき、
空白が1つの場合はそのままで、
空白が2つの場合は空白を1つにして出力することはできますでしょうか?
あい うえ お
あい(空白)うえ(空白)(空白)お
1つか2つしか無いのであれば
空白2つを1つにREPLACEすればいいんじゃないの
回答ありがとうございます。
3つ以上もありえるんです。
重複する空白を1つにする方法をご存じないでしょうか。
>>949 PostgreSQLのsubstringの仕様はマニュアルをググってね。
Eはエスケープするよん宣言。Eなしで [?&] でも良さそうだけど。
UPDATE ... FROM ... WHEREは結合(JOIN)している。
SELECT * FROM urlTable JOIN enginTable ON urlTable.url ~ ('^' || enginTable.engin);
と同じようなこと。
>>952 DBは? PostgreSQLなら
regexp_replace( 文字列 , ' +', ' ')
訂正
×regexp_replace( 文字列 , ' +', ' ')
○regexp_replace( 文字列 , ' +', ' ' ,'g')
955 :
935:2009/08/30(日) 20:45:51 ID:IiFjmKoL
>>954 なるほど!
やっと内容が把握できました。確かにこれならイケます。
でもこれ、Mysql(実行環境がmysql5.0なんです)で実行できるんだろうか(汗)
mysqlで出来る出来ないは置いといて、超勉強になりました!
956 :
935:2009/08/30(日) 20:46:45 ID:IiFjmKoL
>>953 回答ありがとうございます。
DBはMysqlです。
>>950 mysqlの正規表現は
>>945が言ってる通りMySQLの正規表現で部分抽出や置換が出来ない。
プログラムで対処するしかない。
再帰的にREPLACEする関数を作ればいいんじゃないの
960 :
NAME IS NULL:2009/09/03(木) 16:35:27 ID:gPIw7unu
DB:MySQL5.1
insert into AAA ( date1 ) values ( last_day(date_add(NOW(),interval 1 year)) );
この場合だと1年後の月末の00:00:00が入ります。
やりたいのは1年後の月末の23:59:59(ここが固定)で投入したいのです。
方法がありましたら教えてください。
23:59:59 足せばいいんでないの??
>>961 できた!ADDTIMEを知りませんでした・・・。
select addtime(date_format(last_day(date_add(now(),interval 1 year)),'%Y/%m/%d %H:%i:%S'),"23:59:59");
ありがとうございます。
963 :
NAME IS NULL:2009/09/03(木) 20:41:36 ID:x4DugVd9
t
↑すいません。
accessでインポートしてきた、テーブル1を更新クエリを使ってnull値を埋めたいと思っています。
F1 F2 F3
ke ek 03
oe 0w 93
qi 93
oq 92
zp ie 32
こんなテーブルを、更新クエリ
レコードの更新:[テーブル1].[F1] = [テーブル1].[F1]-1
抽出条件: Is Null
または、
レコードの更新:[テーブル1].[F2] = [テーブル1].[F2]-1
抽出条件: Is Null
で、更新しようとしたのですが、更新すべき件数を認識してくれますが、
データは反映されません。
初歩的な質問な気がしますが、ヒントだけでもお願いします。
SQL を勉強してから来い
Oracle10gを使用しています。
MERGE文で、
WHEN MATCHED AND TBL_1.CD_A <> TBL_2.TCD_A THEN
....
という感じで指定したいのですけど、
Oracleではどのように指定するのでしょうか?><
MERGE INTO TBL_1
USING TBL_2
ON (TBL_1.CD_A <> TBL_2.TCD_A)
WHEN MATCHED THEN
...
という感じじゃね
>>967 ご回答ありがとうございます。
いろいろ勘違いしてたみたいです。
969 :
NAME IS NULL:2009/09/05(土) 18:22:57 ID:GS7w5l+v
access 2000使ってます
2つのテーブルがあり、
片方のテーブルには
[データ名]フィールドと
[ID1]フィールドと
[ID2]フィールドがあります。
もう片方のテーブルには
[データ内容]フィールドと
[ID3]フィールドがあります
[ID1]と[ID2]の値を連結した8桁の文字列が[ID3]に対応します。
以上の内容で[ID3][データ名][データ内容]の入ったクエリを作成したいのですが、
SQLだとFROMの部分がうまく指定できません。
初歩的な質問でしょうが、どうかお願いいたします。
select * from tbl1, tbl2
where tbl1.id1 + tbl1.id2 = tbl2.id3
こんな簡単に出来たんすか・・
すいません、ありがとうございました
MySQL5.1 Tritonn でDBを構築しています.
特定のクエリがどうしても遅いので高速化したいのですが,行き詰ってしまいました.
現在次のような3つのテーブルがあります.
TableA (RIDとRCodeは二つ揃って一意 RID一つに対して複数のRCodeIDを登録)
RID: INTEGER
RCodeID: INTEGER
TableB
ID: INTEGER
TableA_ID: INTEGER
Text: Text
Master
ID: INTEGER
Code: Text
TableBのText内に任意の文字列が含まれている項目を抽出し
Master.Codeごとにどれだけ使われているのか取得したいのです.
現在次のようなクエリを発行しています.
SELECT COUNT(Master.ID), Master.Code
FROM TableA
LEFT OUTER JOIN TableB ON TableA.RID = TableB.TableA_ID
LEFT OUTER JOIN Master ON TableA.RCodeID = Master.id
WHERE match(TableB.text) against( 'Term')
GROUP BY Master.id ORDER BY count(Master.id) DESC;
Explainしてみると,
1, 'SIMPLE', 'TableA', 'index', '', 'PRIMARY', '8', '', 1417619, 'Using index; Using temporary; Using filesort'
1, 'SIMPLE', 'TableB', 'ref', 'Index1', 'Index1', '4', 'DBName.TableA.RID', 1, 'Using where'
1, 'SIMPLE', 'Master', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'DBName.TableA.RCodeID', 1, ''
となりました.
まずTableAのインデックス追加が必須のようなのですが,
RID,RCodeID,RCodeID RID, RID RCodeID
と無駄があるのも承知で4つ(Index BTREE)を作成しましたが改善されません.
どなたかご助力いただけませんでしょうか
MYSQLてフルテキストインデックスて無いんだっけ?
974 :
972:2009/09/07(月) 00:38:04 ID:???
975 :
972:2009/09/07(月) 17:16:52 ID:???
自己レスです.
うまくいったので内容を記述します.
Where句を
WHERE match(TableB.text) against( 'Term')
↓
WHERE TableB.TableA_ID > 0 AND match(TableB.text) against( 'Term')
これでうまくいきました.
TableB.Table_IDはすべて1以上の値が入っているので結果は変わらないのですが,
これにすることでIndexが有効に使われるようになったようです.
うまくいったのはいいのですが,
なぜうまくいくのか理由がわからないので,
次回のためにもどなたか解説いただけませんでしょうか.
976 :
NAME IS NULL:2009/09/08(火) 01:34:20 ID:LRxN+yRN
下記のテーブルがありまして、
TABLE_A
TABLE_B
TABLE_C
その中に、COLUMN_KEYという同じ種類の列があります。
この3つのテーブルの中で、
(1)COLUMN_KEYが3つのテーブルにあるもの
(2)COLUMN_KEYが3つのテーブルにあるもの
のデータを取得したいのですが、一回のSQLで書く方法はありますか?
一時TABLEを作って、GROUP BYとHAVINGを使って処理する方法は思いついたのですが、
一時TABLEを作わずに、一回のSQLで処理する方法が分かりません。
データベースは、MYSQL5+WindowsXPです。
宜しくお願いします。
977 :
NAME IS NULL:2009/09/08(火) 01:35:13 ID:LRxN+yRN
すみません。
コピペミスです。
> (2)COLUMN_KEYが3つのテーブルにあるもの
は(2)COLUMN_KEYが2つのテーブルにあるもの、の間違いです。
大変失礼しました。
select count(column_key) from
(
select column_key from table_a
union all
select column_key from table_b
union all
select column_key from table_c
)
group by column_key having count(column_key) = 3(もしくは2);
単純にだとこうかなぁ。
>>976 (1)と(2)のそれぞれのSQLが知りたいのか?
それとも(1)と(2)同時にとりたいのか?
前者の(1)なら普通にJOINすればいいだけなんだから、(1)がわからないのはあり得ないか?
なら後者? でもどういう出力が欲しいのかわからないので、出力サンプル出してみ。
ああ、(1)はJOINでよかったかorz
>>975 最適化以前にいくつか気になることがあるんだが
1.TableAとMasterを外部結合させているが、内部結合にすることはできないのか?
TableA.RCodeID = Master.idを満たさない場合、Master.ID, Master.CodeともにNULLとなる。
有効なMaster.ID+NULLとなったMaster.IDをカウントしたい様に見えるが、
COUNT(Master.ID)としているため、NULLとなったMaster.IDはカウントされない
2.TableBも外部結合させているが、TableA.RID = TableB.TableA_IDを満たさない場合、TableB.textはNULLになるため、内部結合でも良い様に見える。
3.蛇足だけど、count(Master.id)を二カ所に記述しているのが気になる.
MySQL 5.1は表式が使えるようなので、
SELECT * FROM (
SELECT COUNT(Master.ID) AS ID_COUNT, Master.Code
FROM TableA
LEFT OUTER JOIN TableB ON TableA.RID = TableB.TableA_ID
LEFT OUTER JOIN Master ON TableA.RCodeID = Master.id
WHERE match(TableB.text) against( 'Term')
GROUP BY Master.Code
) V
ORDER BY ID_COUNT DESC
とすると、どうなるだろうか?
「説明のための簡略化で、取得列数を減らしているだけで、実際はもっと多いんです」と言う状況か
その場合でも、提示されたクエリで絞り込んだ結果セットとほかの実テーブルを改めて結合したらいいんじゃないのかな、と思った。
Ooo3.1.1-Base使ってます。
original.csvファイル
111111,aaaa
222222,bbbb
・
・
・
の全レコードを作成済みテーブル(sub)にIDを先頭に追加した形でコピーしたいです。
ID | DATE | DATA
--+------+-----
1 | 111111 | aaaa
2 | 222222 | bbbb
・
・
単純にコピーなどでできたらいいんですが、レコード行数が限界を超えてしまったための策です。
お願いします。
>>976 どこか一つのテーブルのcolumn_keyが必ずNULLでないのなら、
以下の様に書ける(table_aのcolumn_keyがNULLでないと仮定)
select
v.column_key,
sum(case when v. column_key_count = 2 then 1 else 0) as column_key_count2,
um(case when v. column_key_count = 3 then 1 else 0) as column_key_count3
from (
select
a.column_key,
1
+ (case when b.column_key is null then 0 else 1 end)
+ (case when c.column_key is null then 0 else 1 end) as column_key_count
from table_a a
left outer join table_b b a.column_key = b.column_key
left outer join table_c c a.column_key = c.column_key
) v
group by
v.column_key
full outer joinがつかえると、上の仮定なく取得出来るが、どうもMySQLには無いらしい
ちなみにfull outer joinだと、内側のクエリを、
select
coalesce(a.column_key, b.column_key, c.column_key) as column_key
(case when a.column_key is null then 0 else 1 end)
+ (case when b.column_key is null then 0 else 1 end)
+ (case when c.column_key is null then 0 else 1 end) as column_key_count
from table_a a
full outer join table_b b a.column_key = b.column_key
full outer join table_c c a.column_key = c.column_key
と変更する。
未確認なので、雰囲気だけ感じてくださいな
>>983の自己レス
外側間違ってた
select
v.column_key,
sum(case when v. column_key_count = 2 then 1 else 0 end) as column_key_count2,
um(case when v. column_key_count = 3 then 1 else 0 end) as column_key_count3
from (...) v
group by
v.column_key