Sqlite 3では、最小値に基づいて行を選択する方法を理解しようとしています。 Googleを効果的に検索するのに十分な関連用語がわからないため、制限があると思います。
テーブルは次のようになります。
num text num2
---------- ---------- ----------
0 a 1
0 a 2
1 a 3
1 b 4
num2
が1, 2
、および4
である行を取得したい。テキスト列の一意の値ごとに、numの最小値に基づいて選択を行います。
したがって、text = 'a'
の場合、num
の最小値は0
なので、行1と2が必要です。text = 'b'
の場合、num
の最小値は1
なので、行4
が必要です。
Group byのさまざまな組み合わせを使用して、行1
および2
または行1
および4
を取得できます。自分のやりたいことを実行するSQLコンポーネントがないように感じますが、それが何であるかを理解することができませんでした。
このタイプのクエリを実行する適切な方法は何ですか?
aこれを行う方法を見つけました。自分の質問に答えるほど評判がよくないので、ここで更新を行っています。それが常に正しいのか、それとも効率がどの程度なのかはわかりません。コメントは大歓迎です。
1つのクエリでテキストの一意の値ごとにnumの最小値を見つける、複合selectステートメントを使用しました。
sqlite> select num, text from t group by text having num = min( num );
num text
---------- ----------
0 a
1 b
次に、これをテーブル全体と結合して、これら2つの列に一致するすべての行を取得します。
sqlite> with u as
( select num, text from t group by text having num = min( num ) )
select t.* from t join u on t.num = u.num and t.text = u.text;
num text num2
---------- ---------- ----------
0 a 1
0 a 2
1 b 4
ご覧のとおり、単純なGROUP BYは機能しません。グループごとに1つのレコードしか返されないためです。
結合は正常に機能します。大きなテーブルの場合、結合列(num
およびtext
)にインデックスがある場合にのみ効率的です。
または、相関サブクエリを使用することもできます。
SELECT *
FROM t
WHERE num = (SELECT MIN(num)
FROM t AS t2
WHERE t2.text = t.text);
このクエリは、実行時に一時テーブルを必要としません(クエリはu
の結果に対して実行します)が、t
の各レコードに対してサブクエリを実行するため、text
にインデックスを付ける必要があります。 (または、text
とnum
の両方にインデックスを使用して カバーするインデックス を取得します。)
私は外部自己結合でこのタイプのことをする傾向があります:
SELECT
M1.Num,
M1.Text,
M1.Num2
FROM
MyDb M1
LEFT OUTER JOIN
MyDB M2
ON
M1.text = M2.text
AND
M1.num > m2.num
WHERE
M2.num is null
これは基本的に言っています。より高い値を持たないすべてのレコード、つまりnullを取得してください。
では、次回、自分で質問の答えを自分で見つけるにはどうすればよいでしょうか。私の意見では、それはロジックを分解してフォローすることによるものです。そしてあなたはそれを正しく理解しました:
テキスト列の一意の値ごとにnumの最小値に基づいて選択を行いたい
これは次のように変換されます。
select text, min(num) from t group by text;
(これはhaving
クエリと同等である必要があります。num
がNULLに等しい行を確認するのは興味深いかもしれません。より正確には、nullのある行がどのような影響を与えるか見てください、最初にwhere num is not null
で除外することができます)
ここから、次の方法で目的の結果を得ることができます。
select * from t where (num, text) in ( *insert query above* )
または結合を使用:
select t1.* from t t1,
(select text, min(num) as n from t group by text) t2
where t1.num = t2.n and t1.text = t2.text.
また、テーブルのパフォーマンスが十分でない場合は、より複雑なステートメントを調べてください。