sql >> データベース >  >> RDS >> Mysql

MySQLIN句のカンマ区切り値

    @Jeremy SmithのFIND_IN_SET()の例に基づいて、結合を使用して実行できるため、サブクエリを実行する必要はありません。

    SELECT * FROM table t
    JOIN locations l ON FIND_IN_SET(t.e_ID, l.city) > 0
    WHERE l.e_ID = ?
    

    これは、テーブルスキャンを実行し、FIND_IN_SET()関数をすべて評価する必要があるため、パフォーマンスが非常に低いことが知られています。 tableの行の組み合わせ およびlocations 。インデックスを利用することはできず、それを改善する方法はありません。

    悪いデータベース設計を最大限に活用しようとしているとあなたが言ったことは知っていますが、これがどれほど劇的に悪いかを理解する必要があります。

    説明:最初、中間、または最後の頭文字が「J」である電話帳で全員を検索するように依頼したとします。とにかくすべてのページをスキャンする必要があるため、この場合、本の並べ替え順序が役立つ方法はありません。

    LIKE @fthiellaによって与えられた解決策には、パフォーマンスに関して同様の問題があります。インデックスを付けることはできません。

    データベースの列に区切りリストを保存するのは本当に悪いですか? 非正規化されたデータを保存するこの方法の他の落とし穴について。

    インデックスを保存するための補足テーブルを作成できる場合は、場所を都市リストの各エントリにマップできます。

    CREATE TABLE location2city (
     location INT,
     city INT,
     PRIMARY KEY (location, city)
    ); 
    

    考えられるすべての都市のルックアップテーブルがあると仮定します(tableに記載されている都市だけではありません)。 )マッピングを作成するために、非効率性に一度耐えることができます:

    INSERT INTO location2city (location, city)
      SELECT l.e_ID, c.e_ID FROM cities c JOIN locations l
      ON FIND_IN_SET(c.e_ID, l.city) > 0;
    

    これで、はるかに効率的なクエリを実行して、table内のエントリを見つけることができます。 :

    SELECT * FROM location2city l
    JOIN table t ON t.e_ID = l.city
    WHERE l.e_ID = ?;
    

    これはインデックスを利用できます。ここで、locationsの行のINSERT/UPDATE/DELETEに注意する必要があります。 また、対応するマッピング行をlocation2cityに挿入します 。



    1. T-SQLで日付から年を取得する方法

    2. PostgreSql:横方向結合を使用した行へのJson配列

    3. 初心者向けSQLMAX()

    4. 制約違反に関するユーザーフレンドリーなエラーメッセージを表示する方法はありますか