4

たとえば、次のように、精度を下げてテーブル内の単一の行を検索したい場合はどうすればよいでしょうか。

SELECT * FROM image WHERE name LIKE 'text' AND group_id = 10 LIMIT 1

これで結果が得られない場合は、次のことを試してください。

SELECT * FROM image WHERE name LIKE 'text' LIMIT 1

これで結果が得られない場合は、次のことを試してください。

SELECT * FROM image WHERE group_id = 10 LIMIT 1

たった一つの式でそれを行うことは可能ですか?

また、検索パラメータが 2 つではなく 3 つ以上ある場合にも問題が発生します。そのための一般的な解決策はありますか?もちろん、検索結果が関連性でソートされている場合に便利です。

4

4 に答える 4

4

LIKEワイルドカード文字なしは と同等=です。あなたが実際に意味したと仮定しますname = 'text'

インデックスはパフォーマンスの鍵です。

テスト設定

CREATE TABLE image (
  image_id serial PRIMARY KEY
, group_id int NOT NULL
, name     text NOT NULL
);

理想的には、(主キーに加えて) 2 つのインデックスを作成します。

CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);

2 番目、データの配布やその他の詳細によっては必要ない場合があります。ここでの説明:

クエリ

これは、あなたのケースで可能な限り最速のクエリになるはずです:

SELECT * FROM image WHERE name = 'name105' AND group_id = 10
UNION ALL
SELECT * FROM image WHERE name = 'name105'
UNION ALL
SELECT * FROM image WHERE group_id = 10
LIMIT  1;

SQL フィドル。

このLIMIT句はクエリ全体に適用されます。Postgres は十分賢くUNION ALLLIMIT. したがって、クエリの最初 の一致の場合、 の出力は次のようになります (右にスクロールしてください! )。SELECTEXPLAIN ANALYZE

制限 (コスト=0.00..0.86 行=1 幅=40) (実際の時間=0.045..0.046 行=1 ループ=1)
  バッファ: ローカル ヒット = 4
  -> 結果 (コスト=0.00..866.59 行=1002 幅=40) (実際の時間=0.042..0.042 行=1 ループ=1)
        バッファ: ローカル ヒット = 4
        -> 追加 (コスト=0.00..866.59 行=1002 幅=40) (実際の時間=0.039..0.039 行=1 ループ=1)
              バッファ: ローカル ヒット = 4
              -> イメージで image_name_grp_idx を使用したインデックス スキャン (コスト=0.00..3.76 行=2 幅=40) (実際の時間=0.035..0.035行=1 ループ=1 )
                    索引条件: ((name = 'name105'::text) AND (group_id = 10))
                    バッファ: ローカル ヒット = 4
              -> イメージの image_name_grp_idx を使用したインデックス スキャン (cost=0.00..406.36 rows=500 width=40) (決して実行されません)
                    索引条件: (name = 'name105'::text)
              -> イメージの image_grp_idx を使用したインデックス スキャン (cost=0.00..406.36 rows=500 width=40) (実行されません)
                    索引条件: (group_id = 10)
総実行時間: 0.087 ミリ秒

大胆強調鉱山。

句を追加しないでくださいORDER BY。効果が無効になります。その場合、Postgres は一番上の行を返す前にすべての行を考慮する必要があります。

最終質問

そのための一般的な解決策はありますか?

これ一般的な解決策です。必要な数のステートメントを追加しSELECTます。

もちろん、検索結果が関連性でソートされている場合に便利です。

の結果には 1 行しかありませんLIMIT 1。一種の空隙選別。

于 2013-01-16T18:53:58.263 に答える
3

遅くなり、完全な解決策を書き出す気はありませんが、これが必要な場合は、顧客タイプ、レコード、またはテーブルを返す顧客関数をおそらく作成します (必要に応じて)。これの利点は、レコードを見つけたら停止できることです。

パラメータの数を動的にすると、少し難しくなります。PostgreSQL のバージョン (および利用可能な拡張機能) によっては、hstoreまたは json を渡してクエリを動的に構築できる場合があります。

おそらく最高のSOの答えではないかもしれませんが、それはコメント以上のものであり、うまくいけば思考の糧です.

于 2013-01-16T05:09:18.677 に答える
2

必要な結果が見つかるまで、これらのクエリを個別に実行しても問題はないと思います。これらを 1 つのクエリに結合する方法はありますが、それらはより複雑で遅くなり、望んでいたものではありません。

すべてのクエリを 1 つのトランザクションで実行することを検討する必要があります。おそらく、反復可能な読み取りの分離レベルが最適です。これにより、一貫した結果が得られ、反復トランザクションを設定するオーバーヘッドも回避できます。さらに、準備済みステートメントを適切に使用すると、3 つのクエリすべてを 1 つの結合ステートメントで実行するのとほぼ同じオーバーヘッドが発生します。

于 2013-01-16T16:23:48.577 に答える
1
SELECT *, 
CASE WHEN name like 'text' AND group_id = 10 THEN 1
WHEN name like 'text' THEN 2
WHEN group_id = 10 THEN 3
ELSE 4
END ImageRank
FROM image
WHERE ImageRank <> 4
ORDER BY ImageRank ASC
LIMIT 1

これは疑似ソリューションのアプローチですが、シナリオの構文でそれが可能かどうかは完全にはわかりません。

于 2013-01-15T14:27:33.263 に答える