AIと戦って、あなたの人生のリスク診断 >>

DB:Oracle9i
SQLのIN句のカッコ内は、何個まで書けるなど、制限はあるのでしょうか?
PRO_KEY = IN (no1, no2, no3・・・)など、カッコ内が可変で、数百個、もしくは数千個ある場合、IN句を使用しデータを一度に取得するのではなく、PRO_KEY = no1のSELECT処理を発行、PRO_KEY = no2のSELECT処理を発行・・・し、ARRAYに検索結果を1つずつ詰めていく方が良いのでしょうか?

初心者で恐縮ですが、どなたかご教授ください。

A 回答 (3件)

INの指定は1000個までなので、


”IN(1000個) OR IN(1000個)”
などと、1000個づつORで区切ると良いです。
パフォーマンス的には、1件づつSELECTは圧倒的に遅くなります。
なぜなら、テーブル(もしくはインデックス)をSELECTのたびに検索するからです。
IN指定方式ならば、テーブル(もしくはインデックス)をなめるのは一回で済みます。件数が多いほど、顕著に差が出そうですね。

また、SELECTを何のプログラムから発行しているかにもよりますが、1回1回のSQL発行によるオーバヘッド(通信・wait時間)なども、回数が多くなると蓄積して大きなものとなるので、SQL発行回数自体も多くなりすぎないよう配慮が必要となります。

可能ならば、一度両方バージョン作ってみて時間を比較されると勉強になって良いと思いますよ。トレースも取ってみてみると良いと思いますわ。
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2008/10/07 00:24

1000個以上のデータをin句に入れるよりは、いったん一時テーブルに格納して、副問い合わせにしたほうがいいのでは。

    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2008/10/07 00:25

こんばんは。



IN句の中に入れることのできる要素数の限界は1000個です。以前、この制限に引っかかったことがあって、1000個ずつ取ったことがありました。
SELECT文を大量に投げるのはちょっと負担になるような。

それ以前にIN句はあまり使いたくないですよね。

この回答への補足

ご回答ありがとうございます!
ORの方が良いのでしょうか?
要素数が可変の場合は、普通はどうするのでしょうか?
ORを使用して、ORの条件文が数百?数千?になるのと、SQLを一回一回発行するのとでは、どちらが良いのでしょうか?

補足日時:2008/02/05 22:23
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QMAX値を条件にデータを取得するには?

SQL文で困っています。
ご教授下さい。


下記のようなデータがあった場合、それぞれの区分毎に
年月が最大(最新)のデータを取得したいです。
(実際には1レコードにその他項目があり、それらも取得します。)
<検索対象データ>
区分 年月   金額
-----------------------------
A   200412  600
A   200503  560
B   200311  600
B   200508  1000
B   200504  560
C   200508  400
C   200301  1100


<取得したいデータ>

区分 年月   金額
-----------------------------
A   200503  560
B   200508  1000
C   200508  400

よろしくお願いします。

Aベストアンサー

テーブル名をXXXとすると次のようなSQLでよいと思います。(最善の方法かどうかは自信がないですが)

select B.* from (select 区分, max(年月) as 年月 from XXX group by 区分) As A
inner join XXX as B on A.区分 = B.区分 and A.年月 = B.年月
order by B.区分

Q3つの表の外部結合

表A、B、Cの3つがあり、Aのすべての行を出力したいと考えています。
外部結合を用いるのだとは思うのですが、3つの表に対して行う場合の
書き方がわからず困っています。
ご教授いただけないでしょうか?
select * from a,b,c
where a.商品ID =b.商品ID (+) and b.商品ID (+) =c.商品ID (+)
としてみましたが、うまくいきませんでした。

Aベストアンサー

ansi構文の趣旨からいえば、結合条件と絞り込み条件は分けて書くので・・

select *
from a
left join b on (a.商品ID =b.商品ID)
left join c on (b.商品ID =c.商品ID)
where a.年月 = 任意の値

と書くのが一般的でしょうね。

Q実行計画の「COST」と「BYTE」について教えていただきたいです。

実行計画の「COST」と「BYTE」について教えていただきたいです。

書籍には
COST・・・・CBOによって見積もられた操作コスト。
BYTE・・・・アクセスされるバイト数のCBOのアプローチによる見積もり。
と書かれていますが、いまいちピンときません。


私は、
COSTは、検索するテーブルのデータ量が多いほうがコスト値が大きくなる。
BYTEは、検索条件に合致して取得できるデータが多いほうがバイト値が大きくなる。
と思っているのですが、正しいでしょうか?

Aベストアンサー

このあたりを参考にしてください。
COSTはデータ量だけではなく、その表やViewのアクセスに要する時間やSortや結合が必要なら、そのために必要なCPU時間等も考慮されています。
表があるHDDのアクセス速度なんかも考慮されているし、表のエクステントが複数になっているかとかも考慮されています。
書籍はわかりにくいかもしれませんが、嘘は少ないと思います。著者が思い違いをしてないとは言い切れませんが。

参考URL:http://otn.oracle.co.jp/forum/message.jspa?messageID=35016743

QInner join と Left joinの明確な違いは?

Inner join と Left joinの違いがよくわかりません。
教えてください。

Aベストアンサー

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
4               NULL
5               NULL
6               NULL
の6レコードが出力されますが、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 INNER JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
の3レコードしか出力されません。

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3           ...続きを読む

QSELECTで1件のみ取得するには?

こんにちわ。
いまORACLE9iを使用している者です。

ACCESSでは
SELECT TOP 1 項目名 FROM テーブル名
ORDER BY 項目名;
で並べ替えたデータ群のうち,先頭の1件だけを
取ることができますが,
ORACLEでそのような機能(SQL)はあるでしょうか?
教えてください。
よろしくお願いします。

Aベストアンサー

order by と rownum を併用する場合は注意が必要です。

[tbl01]
cola | colb
------------
1000 | aaaa
1001 | bbbb

というデータがある場合、
select cola from tbl01 where rownum < 1 order by cola desc;
とすると、「1001」ではなく、「1000」が返されます。
これは、order by の前に rownum < 1 が適用されてしまうからです。

解決するには、
select aaa from (select cola aaa from tbl01 order by cola desc) where rownum = 1;
とすれば良いです。

QSELECT文でINを使わずに検索したい

DBはoracle10gです。
テーブル(A_TBL)は以下の4つのカラムで構成されています。
seq_no(連番),key_1(個人番号),key_2(更新日),status(状態)
key_1が同一のレコードは、
最新のレコード(最新とは更新日の大きいレコード)以外のstatusを'0'から'4'にします。
例として実行前と実行後のテーブルは以下のような状態です。

【実行前】
seq_no,key_1,key_2,status
1,001,20080101,1
2,001,20080102,0
3,002,20080101,0
4,003,20080101,0
5,003,20080102,0
6,003,20080103,0
7,004,20080101,0
8,004,20080102,2

【実行後】
seq_no,key_1,key_2,status
1,001,20080101,1
2,001,20080102,0
3,002,20080101,0
4,003,20080101,4
5,003,20080102,4
6,003,20080103,0
7,004,20080101,4
8,004,20080102,2

以下のようなSQLを作成し、更新しようとしました。

update A_TBL
set status = '4'
where status = '0'
and seq_no not in (
select wk2.seq_no
from A_TBL wk2,
(select max(key_2) as key_2,
key_1 as key_1
from A_TBL
group by key_1) wk1
where wk2.key_1 = wk1.key_1
and wk2.key_2 = wk1.key_2
and wk2.status = '0'
)

このSQLはin句を使っていますが、
in句を使わずに同様の更新を実現することは出来るでしょうか?

DBはoracle10gです。
テーブル(A_TBL)は以下の4つのカラムで構成されています。
seq_no(連番),key_1(個人番号),key_2(更新日),status(状態)
key_1が同一のレコードは、
最新のレコード(最新とは更新日の大きいレコード)以外のstatusを'0'から'4'にします。
例として実行前と実行後のテーブルは以下のような状態です。

【実行前】
seq_no,key_1,key_2,status
1,001,20080101,1
2,001,20080102,0
3,002,20080101,0
4,003,20080101,0
5,003,20080102,0
6,003,20080103,0
7,004,20080101,0
8,004,200...続きを読む

Aベストアンサー

昨日(No.2)は簡単に済ませて失礼しました。眠かったもので(笑)。

> in句でもカンマ区切りで指定した場合は1000件までで、
> 副問合せであれば問題なしという記述もありました。

こちらが正解でしょう。1000件というのは「式のリスト」の制限ですね。
下はマニュアルの抜粋です。

> カンマで区切られた式のリストには、最大1000個の式を指定できます。
> カンマで区切られた式の集合のリストには、任意数の式の集合を含める
> ことができますが、各集合に指定できる式は最大1000個です。

http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19201-02/expressions.html

SELECT文で指定してやる分には問題ないと思いますよ。

【実験】

SQL> select count(*)
2 from (
3 select level
4 from dual
5 connect by level <= 2000
6 );

COUNT(*)
--------
2000

1行が選択されました。

SQL> select ename, sal
2 from emp
3 where sal in (
4 select level
5 from dual
6 connect by level <= 2000
7 );

ENAME SAL
---------- --------
SMITH 800
ALLEN 1600
WARD 1250
MARTIN 1250
TURNER 1500
ADAMS 1100
JAMES 950
MILLER 1300

8行が選択されました。

# inの使用に問題がないのであれば……

update A_TBL
set status = '4'
where seq_no in (
select seq_no
from (
select seq_no, key_2, status,
max(key_2) over (partition by key_1) as max_key_2
from A_TBL
)
where key_2 <> max_key_2 and status = '0'
)

でいいかもしれません。

昨日(No.2)は簡単に済ませて失礼しました。眠かったもので(笑)。

> in句でもカンマ区切りで指定した場合は1000件までで、
> 副問合せであれば問題なしという記述もありました。

こちらが正解でしょう。1000件というのは「式のリスト」の制限ですね。
下はマニュアルの抜粋です。

> カンマで区切られた式のリストには、最大1000個の式を指定できます。
> カンマで区切られた式の集合のリストには、任意数の式の集合を含める
> ことができますが、各集合に指定できる式は最大1000個です。

http:...続きを読む

Qsqlplusで表示が変なので、出力を整形したい。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------

上記のように意味不明な形式で出てきます。

例えばこんな風に

select カラム1,カラム2,カラム3 from hoge;

カラム1 1の値
---------------------------
カラム2 2の値
---------------------------
カラム3 3の値

等のように分かりやすく表示できないでしょうか?

ちなみにOracle9iR2を使用しています。
sqlに関するツールは使用できないルールでして、あくまでsqlplusのコマンド上でみやすくしなければなりません。

分かりづらくですいませんが、皆さま、ご教授お願いします。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
-----------------------...続きを読む

Aベストアンサー

SQLPLUSを起動して、

SQL>set linesize 列数

でどうだ。

SQL>show linesize

で確認ができる。

Qテーブルからのselectにおいてデータの有無により結果をわけたい

id | point
----+-------
1 | 10
2 | 9
3 | 5
....
というテーブルがあるとします.
idを指定してpointを得たいのですが、そのidがこのテーブルに存在しない場合は空の結果ではなく0を返したいのです.
plpgsqlなどを使いif文で場合分けすればできることはわかっているのですがSQL文だけで(それもできれば1文で)これを実現する方法はあるでしょうか?
よろしくお願い致します。

Aベストアンサー

変則的ですが、これでよければidがユニークでなくても大丈夫ですし、集合関数を使わなくてもOKです。

select dm.id,case when ex1.point is null then 0 else ex1.point end from
(select ? as id) as dm left join ex1 on dm.id = ex1.id;

?を適当に変えてください。
chukenkenkouさんの発想はこれですよね。

Q「いずれか」と「いづれか」どっちが正しい!?

教えて下さいっ!
”どちらか”と言う意味の「いずれか」のかな表記として
「いずれか」と「いづれか」のどちらが正しいのでしょう???

私は「いずれか」だと思うんですが、辞書に「いずれか・いづ--。」と書いてあり、???になってしまいました。
どちらでもいいってことでしょうか?

Aベストアンサー

「いずれか」が正しいです.
「いづれ」は「いずれ」の歴史的かな遣いですので,昔は「いづれ」が使われていましたが,現代では「いずれ」で統一することになっていますので,「いずれ」が正しいです.

QOracle(オラクル)で、日付時刻型の検索方法について

質問させていただきます。
データベースはオラクルを使っていて、
SQL文で、抽出するときにエラーが出て困っています。

日付時刻型が「2005/05/26 19:13:00」という感じで入ってます。
2005/05/26 を抽出したいのですが、
BETWEEN '2005/05/26 00:00:00' AND '2005/05/26 23:59:59'

だと、エラーでできません。
どなた様か、ご教授よろしくお願いしますm(_ _)m

Aベストアンサー

日付検索を行う場合は、以下のように書式を含める必要があります。

col BETWEEN TO_DATE('2005/05/26 00:00:00','YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2005/05/26 23:59:59','YYYY/MM/DD HH24:MI:SS')

ただ、厳密には

col >= TO_DATE('2005/05/26', 'YYYY/MM/DD')
AND
col < TO_DATE('2005/05/27', 'YYYY/MM/DD')

と書くべきでしょうね。


人気Q&Aランキング