2017-09-05 10 views
1

をサブにがスピードアップ(書き換え?)ではない私が取得しようとしている表から選択クエリ

a)の表に、キー/値の組み合わせで開催された一定の基準を満たすユーザー

試してみて、フランスに住んでいるか、まだその場所を追加していない人、私はユーザーを見つけるために、例えば、したがって、すべての

でそのキー/値の組み合わせを持っていない

OR

b)のユーザーこの(簡略化された)クエリを使用して:

SELECT * 
FROM 
    current_users 
    JOIN current_users um_location ON current_users.id = um_location.id 
WHERE 
    (
     (um_location.meta_key = 'location' AND um_location.meta_value = 'France') 
    OR 
     (current_users.id NOT IN 
      (SELECT current_users.id FROM current_users WHERE current_users.meta_key = 'location') 
     ) 
    ) 

問題は、もちろん、ORサブ選択クエリを実行すると(それが呼び出されている場合)、クエリが大幅に遅くなっていることです。また、完全なクエリには約5〜6つのサブ選択があるため、処理速度が遅すぎます。

おそらくこれを行う別の方法はありますか?より速い方法?

答えて

0
これは、可能な限り最も簡潔であるべき
SELECT * FROM 
    current_users 
    JOIN current_users um_location ON current_users.id = um_location.id 
WHERE 
    um_location.meta_key = 'location' AND um_location.meta_value = 'France' 
UNION 
SELECT * FROM 
    current_users 
    JOIN current_users um_location ON current_users.id = um_location.id 
WHERE 
    current_users.id NOT IN 
    (SELECT current_users.id FROM current_users WHERE 
    current_users.meta_key='location') 
0

UNIONクエリとしてあなたのOR条件を変更する代わりに、OR

SELECT * 
FROM current_users 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE um_location.meta_value = 'France' 
    OR um_location.meta_value IS NULL 
; 

...しかしisaaceの解答のヒントとして、MySQLは処理しませんOR条件が理想的です。 これはこれより優れている可能性があります。

SELECT * 
FROM current_users 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE um_location.meta_value = 'France' 
UNION 
SELECT * 
FROM current_users 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE um_location.meta_value IS NULL 
; 

です。ただし、me​​ta_valueのインデックスが作成されている場合は、おそらく違いがあります。 MySQLはORで提示されたときにインデックスを無視する傾向があるためです。


編集:スキーマ設計のタイプを使用し始めるために、参加の左側に行として「場所」のエントリを使用してこれらのクエリを持ついくつかの奇妙な問題があるかもしれません。代わりにこれを試してください。

SELECT * 
FROM current_users AS non_location 
LEFT JOIN current_users AS um_location 
    ON current_users.id = um_location.id 
    AND um_location.meta_key = 'location' 
WHERE non_location.meta_key != 'location' 
    AND (um_location.meta_value = 'France' 
     OR um_location.meta_value IS NULL 
     ) 
; 
0

まずはお寄せいただきありがとうございます。残念ながら、私は彼らが参加として働くようにすることができませんでした

LEFT JOIN current_users AS um_location 
ON current_users.id = um_location.id 
AND um_location.meta_key = 'location' 

まだ彼らの場所を入力していないそれらのユーザーのレコードを返しませんでした。

しかし、多くの作業の後、私は問題を解決することができました。それはエレガントではありませんが動作します:

  1. いくつかの基本的な基準を満たすユーザーのサブセットで一時テーブルを作成します。
  2. シンプルなINSERT IGNORE INTO ... SELECT DISTINCT FROM current_usersに、ダミー情報を含む 'location'が追加されました。

その後、最終的なクエリは、これを含まれています:

um_location.meta_value = 'France' 
or 
um_location.meta_value = 'dummyinfo' 

それは猛烈に速くはありませんが、これは彼らだけが待つ余裕ができ、管理者ユーザーのためのバックエンドで動作するプロセスであるため、...;)

もう一度、ありがとうございます!

+0

私は問題を理解したと思う、私の編集を参照してください。 – Uueerdo

関連する問題