私はこのようなテーブルを持っています:
ID | Val | Kind
----------------------
1 | 1337 | 2
2 | 1337 | 1
3 | 3 | 4
4 | 3 | 4
各SELECT
の最初の行だけを返し、Val
の順に並べるKind
を作成します。
出力例:
ID | Val | Kind
----------------------
2 | 1337 | 1
3 | 3 | 4
このクエリを作成するにはどうすればよいですか?
このソリューションもkeep
を使用しますが、val
とkind
は、サブクエリを使用せずに、各グループに対して単純に計算することもできます。
select min(id) keep(dense_rank first order by kind) id , val , min(kind) kind from mytable group by val;
ID | VAL |種類 -:| ---:| ---: 3 | 3 | 4 2 | 1337 | 1
dbfiddle ここ
KEEP…FIRSTおよびKEEP…LASTは、アグリゲートのOracle固有の機能です。Oracleドキュメントで here 、または Oracle_BASE について読むことができます。
FIRST関数とLAST関数を使用して、順序付けられたシーケンスの最初または最後の値を返すことができます
共通テーブル式 (CTE)と ROW_NUMBER のようなウィンドウ処理/ランキング/分割関数を使用します。
このクエリは、ORDEREDと呼ばれるメモリ内テーブルを作成し、1からNまでの数字のシーケンスであるrnの追加の列を追加します。 PARTITION BY は、値がValが変更され、Kindの最小値で行を並べ替えます。
WITH ORDERED AS
(
SELECT
ID
, Val
, kind
, ROW_NUMBER() OVER (PARTITION BY Val ORDER BY Kind ASC) AS rn
FROM
mytable
)
SELECT
ID
, Val
, Kind
FROM
ORDERED
WHERE
rn = 1;
上記のアプローチは、ROW_NUMBER()関数を実装したRDBMSで機能します。 Oracleには mikの回答 で表されるようなエレガントな機能がいくつかあります。これにより、一般にこの回答よりも優れたパフォーマンスが得られます。
bilinkcの解決策は問題なく機能しますが、私も同じように取り除きます。それは同じコストですが、より速いかもしれません(または遅いです、私はそれをテストしていません)。違いは、Row_NumberではなくFirst_Valueを使用することです。私たちは最初の値にのみ関心があるので、私の心の中でそれはもっと簡単です。
SELECT ID, Val, Kind FROM
(
SELECT First_Value(ID) OVER (PARTITION BY Val ORDER BY Kind) First, ID, Val, Kind
FROM mytable
)
WHERE ID = First;
テストデータ。
--drop table mytable;
create table mytable (ID Number(5) Primary Key, Val Number(5), Kind Number(5));
insert into mytable values (1,1337,2);
insert into mytable values (2,1337,1);
insert into mytable values (3,3,4);
insert into mytable values (4,3,4);
必要に応じて、これは同等のCTEです。
WITH FirstIDentified AS (
SELECT First_Value(ID) OVER (PARTITION BY Val ORDER BY Kind) First, ID, Val, Kind
FROM mytable
)
SELECT ID, Val, Kind FROM FirstIdentified
WHERE ID = First;
keep
を使用して、各グループからid
を選択できます。
select * from mytable where id in ( select min(id) keep (dense_rank first order by kind, id) from mytable group by val );
ID | VAL |種類 -:| ---:| ---: 2 | 1337 | 1 3 | 3 | 4
dbfiddle ここ
SELECT MIN(MyTable01.Id) as Id,
MyTable01.Val as Val,
MyTable01.Kind as Kind
FROM MyTable MyTable01,
(SELECT Val,MIN(Kind) as Kind
FROM MyTable
GROUP BY Val) MyTableGroup
WHERE MyTable01.Val = MyTableGroup.Val
AND MyTable01.Kind = MyTableGroup.Kind
GROUP BY MyTable01.Val,MyTable01.Kind
ORDER BY Id;
select * from(select t1。*、ROW_NUMBER()OVER(PARTITION BY Val ORDER BY Val desc)as seqnum from tablename t1)where seqnum = 1;