2016-08-13 23 views
0

私はクイズのウェブサイト上で作業しており、ユーザーが直前に行ったクイズに基づいてユーザーが好きなクイズを提案する必要があります。基本的に、彼らがちょうど取ったクイズにタグがある場合、同じタグで別のクイズを引く必要があります。それ以外の場合は、同じカテゴリから別のクイズを引きます。複数のテーブル条件に基づいたMySQLの選択

私が持っているものは、私がそれを望む方法で90%働いていますが、それは私には非常にかさばるようです。 10%は有効ではありません。アクティブなクイズだけを引き出す条件を追加するのを忘れてしまいました。 WHERE q.active = 1のようなものですが、どこでどのように条件を追加しても、計画どおりに動作しません。私は、条件が追加される前に受け取っていた空のセットまたは同じ結果を取得します。

EDIT:

私は私の最初のWHERE句にAND q.active = 1を追加し、同じタグを持つ唯一の他のクイズがあり、それがある場合は... @RiggsFollyによってコメントを読んだ後、

を明確にしますアクティブではないカテゴリ選択ステートメントから結果を受け取る代わりに、空のセットを受け取ります。タグ選択文ではなく、カテゴリ選択文だけにAND q.active = 1を追加すると、同じタグを持つクイズがない場合でも適切な結果が返されます。

SELECT 
    IFNULL(q.meta_title, q.title) AS title, 
    IFNULL(url, title) AS url, 
    1 istag 
FROM tag_index t 
LEFT JOIN tag_index ti 
    ON ti.tag_id = t.tag_id 
LEFT JOIN quizzes q 
    ON q.id = ti.quiz_id 
WHERE t.quiz_id = :quiz_id 
    AND ti.quiz_id != t.quiz_id 

UNION ALL 

SELECT 
    IFNULL(q.meta_title, q.title) AS title, 
    IFNULL(url, title) AS url, 
    0 istag 
FROM category_index c 
LEFT JOIN category_index ci 
    ON ci.category_id = c.category_id 
LEFT JOIN quizzes q 
    ON q.id = ci.quiz_id 
WHERE c.quiz_id = :quiz_id 
    AND ci.quiz_id != c.quiz_id 
    AND NOT EXISTS 
     (SELECT 1 FROM tag_index WHERE quiz_id = :quiz_id) 
ORDER BY RAND() LIMIT 1 

ご意見やご感想をお寄せください。

+0

このSQLは、より多くの行、空白行、インデントで美しくする必要があります。 –

+1

次に、where句に 'AND q.active = 1'を追加してください。 – RiggsFolly

+0

@ Tiberiu-IonuţStanSQL文をきれいにすることは、私の強い訴訟の一つではありません。私はそれを少し読みやすくするために私の投稿を編集しました。提案していただきありがとうございます! – Jay

答えて

0

はまた、あなたの副選択にactive = 1条件を追加する必要があります:あなたはすべてのその副選択は必要ありません。しかし

SELECT 
    IFNULL(q.meta_title, q.title) AS title, 
    IFNULL(url, title) AS url, 
    1 istag 
FROM tag_index t 
LEFT JOIN tag_index ti 
    ON ti.tag_id = t.tag_id 
LEFT JOIN quizzes q 
    ON q.id = ti.quiz_id 
WHERE t.quiz_id = :quiz_id 
    AND ti.quiz_id != t.quiz_id 
    AND q.active = 1 

UNION ALL 

SELECT 
    IFNULL(q.meta_title, q.title) AS title, 
    IFNULL(url, title) AS url, 
    0 istag 
FROM category_index c 
LEFT JOIN category_index ci 
    ON ci.category_id = c.category_id 
LEFT JOIN quizzes q 
    ON q.id = ci.quiz_id 
WHERE c.quiz_id = :quiz_id 
    AND ci.quiz_id != c.quiz_id 
    AND q.active = 1 
    AND NOT EXISTS 
     (SELECT 1 
     FROM tag_index t 
     JOIN tag_index ON ti.tag_id = t.tag_id 
     JOIN quizzes ON q.id = ti.quiz_id 
     WHERE t.quiz_id = :quiz_id 
      AND ti.quiz_id != t.quiz_id 
      AND q.active = 1) 
ORDER BY RAND() LIMIT 1 

することができます最初istagでわずか順:

SELECT 
    IFNULL(q.meta_title, q.title) AS title, 
    IFNULL(url, title) AS url, 
    1 istag 
FROM tag_index t 
LEFT JOIN tag_index ti 
    ON ti.tag_id = t.tag_id 
LEFT JOIN quizzes q 
    ON q.id = ti.quiz_id 
WHERE t.quiz_id = :quiz_id 
    AND ti.quiz_id != t.quiz_id 
    AND q.active = 1 

UNION ALL 

SELECT 
    IFNULL(q.meta_title, q.title) AS title, 
    IFNULL(url, title) AS url, 
    0 istag 
FROM category_index c 
LEFT JOIN category_index ci 
    ON ci.category_id = c.category_id 
LEFT JOIN quizzes q 
    ON q.id = ci.quiz_id 
WHERE c.quiz_id = :quiz_id 
    AND ci.quiz_id != c.quiz_id 
    AND q.active = 1 
ORDER BY istag DESC, RAND() LIMIT 1 
+0

ご返信ありがとうございます。残念ながら、同じタグを持つクイズが1つしかなく、まだアクティブでない場合は空のセットを返します。 – Jay

+0

2回目の参加を忘れました。あなたの元の状態は意味をなしませんでした。「存在しないでください。**任意の**タグ:qiuz_id」と読むことができます。 –

0

Easy Solution

私の意見では、問題のクイズのtag_idとcategory_idを読み込みます。次に、しようとしているようなUNIONを使って簡単なクエリを実行します。それは物事を単純化し、結合の数を減らします。ここでは、大きなクエリと

SELECT 
    quiz_pool.quiz_id id, 
    IFNULL(q.meta_title, q.title) AS title, 
    IFNULL(q.url, q.title) AS url 
FROM (

    /* IDs of all quizzes with same tag */ 
    SELECT ti.quiz_id, istag = 1 
    FROM tag_index ti 
    WHERE ti.tag_id IN(SELECT tag_id FROM tag_index WHERE quiz_id = :quiz_id) 
     AND ti.quiz_id <> :quiz_id 
    LIMIT 0, :quiz_count 

    UNION ALL 

    /* IDs of all quizzes with same category */ 
    SELECT ci.quiz_id, istag = 0 
    FROM category_index ci 
    WHERE ci.category_id IN(SELECT category_id FROM category_index WHERE quiz_id = :quiz_id) 
     AND ci.quiz_id <> :quiz_id 
    LIMIT 0, :quiz_count 

) quiz_pool 
INNER JOIN quizzes q ON q.id = quiz_pool.quiz_id AND q.active = 1 
ORDER BY quiz_pool.istag DESC, RAND() 
LIMIT 0, :quiz_count 

をそれをすべて行うに

、あなたはを設定することができます、あなたのロジックに従って取得したいクイズの数としてをquiz_count。最初に、同じタグを持つクイズを探し、同じカテゴリからクイズを作成し、クイズもランダム化します。

希望します。

+0

返信いただきありがとうございます!私はこの方法がうまくいくことを期待していました。なぜなら、このようにすれば条件を追加しやすくなりますが、タグ内のクイズがアクティブでないときに空のセットを受け取ります。 – Jay

関連する問題