のような単純なクエリで
SELECT *
FROM table
WHERE id='x' OR id='y'
WHERE
句の1つだけを取得するように優先順位を付けるにはどうすればよいですか?
id='x'
で行を取得することを意味します。行がない場合のみ、id='y'
で行を取得します。
つまり、id='y'
の行がある場合はid='x'
を使用しないでください。
SELECT *
FROM table
WHERE id IN ('x', 'y')
AND (id='x' OR NOT EXISTS(SELECT id FROM table WHERE id='x'))
トリックを実行する必要があります(警告:私はMSSQLの人であり、mySQLで試したことがありませんが、構文も問題なく受け入れられていると思われます)。ただし、効率は最初のフィルタリング句に一致する行の数によって異なります。 (id='x' OR id='y'
に一致するすべての行について、EXISTS
部分のサブクエリは、クエリプランナーが外部クエリの何にも依存しないことを確認できるほど明るくなければ、おそらく実行されます結果の再利用-期待されるのが2つだけの場合(これはid
のような列名を使用している場合です)これは問題ではありません)
私もMySQLの人ではありませんが、これでうまくいくと思います。
SELECT SQL_CALC_FOUND_ROWS *
FROM table
WHERE id='x'
UNION ALL
SELECT *
FROM table
WHERE FOUND_ROWS() = 0 AND id='y'
免責事項:これが文書化された/保証された動作であるかどうかはわかりません。
あなたはUNION ALL
およびLIMIT
。
SELECT *
FROM table
WHERE id=x
UNION ALL
SELECT *
FROM table
WHERE id=y
ORDER BY id='x'
LIMIT 1;
とにかくPostgreSQLで動作します。
CREATE TABLE foo
AS
SELECT
x::int % 7 AS a,
5 AS b
FROM generate_series(1,1e6::int)
AS gs(x);
CREATE INDEX ON foo (a);
ANALYZE foo;
explain analyze SELECT * FROM foo WHERE a=5 UNION ALL SELECT * FROM foo WHERE b = 5 LIMIT 1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..0.04 rows=1 width=8) (actual time=0.026..0.027 rows=1 loops=1)
-> Append (cost=0.00..45287.67 rows=1143767 width=8) (actual time=0.025..0.025 rows=1 loops=1)
-> Seq Scan on foo (cost=0.00..16925.00 rows=143767 width=8) (actual time=0.024..0.024 rows=1 loops=1)
Filter: (a = 5)
Rows Removed by Filter: 4
-> Seq Scan on foo foo_1 (cost=0.00..16925.00 rows=1000000 width=8) (never executed)
Filter: (b = 5)
Planning time: 0.203 ms
Execution time: 0.061 ms
(9 rows)
(never executed)
は、ジョブが完了したことを意味します。