稀に SQL の検索結果の最初の1件だけが欲しい場合がある(副問い合わせのときなど)。やり方はいろいろあると思うが、ここでは Oracle の ROWNUM を使うやり方をメモしておく。
準備
以下のテーブルを用意する。
T_SAMPLE:
create table T_SAMPLE (
PARENT varchar2(6) not null,
CHILD varchar2(6) not null,
SORTNO number(2,0) default 1 not null,
constraint PK_T_SAMPLE primary key (PARENT, CHILD) using index
)
/
insert into T_SAMPLE (PARENT, CHILD, SORTNO) values ('IDC8JT', 'IDVZ1O', 1)
/
insert into T_SAMPLE (PARENT, CHILD, SORTNO) values ('IDF8CM', 'IDVZ1O', 2)
/
insert into T_SAMPLE (PARENT, CHILD, SORTNO) values ('IDCQJJ', 'IDI50N', 1)
/
insert into T_SAMPLE (PARENT, CHILD, SORTNO) values ('ID3JF6', 'IDVZ1O', 3)
/
| PARENT* | CHILD* | SORTNO |
|---|---|---|
| 'IDC8JT' | 'IDVZ1O' | 1 |
| 'IDF8CM' | 'IDVZ1O' | 2 |
| 'IDCQJJ' | 'IDI50N' | 1 |
| 'ID3JF6' | 'IDVZ1O' | 3 |
(* は primary key 項目)
ROWNUM を使って最初の1件のみを取得する
select PARENT, SORTNO from T_SAMPLE where CHILD = 'IDVZ1O'
これで以下の結果を取得できる。
| PARENT | SORTNO |
|---|---|
| 'IDC8JT' | 1 |
| 'IDF8CM' | 2 |
| 'ID3JF6' | 3 |
ここで SORTNO が最大のレコードの PARENT のみが欲しい場合はこうする。
select TBL.PARENT as PARENT
from (select PARENT, SORTNO from T_SAMPLE where CHILD = 'IDVZ1O' order by SORTNO desc) TBL
where rownum = 1
| PARENT |
|---|
| 'ID3JF6' |
元の SQL 文に rownum = 1 条件を入れると order by でソートする前の状態で条件が効いてしまうので、いったん
select PARENT, SORTNO from T_SAMPLE where CHILD = 'IDVZ1O' order by SORTNO desc
でソートした状態に対して rownum = 1 条件をセットする。
まっ、本当はこんな羽目に陥らないようにテーブル設計すべきなんだろうけど、改造仕事はこういうイレギュラーがよくあるのよ。
ROWNUM を使いたくないなら
今回の例で CHILD に対して SORTNO 値のダブりがないと言えるなら
select PARENT
from T_SAMPLE
where CHILD = 'IDVZ1O'
and SORTNO = (select max(SORTNO) from T_SAMPLE where CHILD = 'IDVZ1O')
という手が使えなくもない。ん~、ちょっと苦しいかな? テーブルのフルアクセスが2回発生するからなぁ。
【おまけ】 LIMIT を使って最初の1件のみを取得する
ついでに。
MySQL の場合は ROWNUM ではなく LIMIT が使える。
select PARENT, SORTNO from T_SAMPLE where CHILD = 'IDVZ1O' order by SORTNO desc limit 1
Oracle の ROWNUM とちがい, LIMIT の場合は order by を含めた文全体に対して効く。