2016-11-15 3 views
1

以下のSQLクエリを参照してください。私は、ユーザテーブルのプロフィール画像を持つタスクテーブルのupdated_byおよび/またはcreated_byフィールド(いずれか新しいほうの方)に記録されている人物と一致する簡単なアクティビティフィードを作成しようとしています。このクエリは動作しますが、ON句では、ORテーブルの両方の要素がtrueを返すので、2つのフィールドに異なるユーザーがある場合は重複しますが、ユーザーテーブルの誰かに一致するcreated_byがあります。両方のフィールドが異なるユーザーで満たされている場合は、これを1に制限します。私は、ON句にCASE WHENを追加しようとしましたが、if/elseロジックがないので、両方とも真となり、同じ結果が返されます。このSQLクエリでINNER JOINとONを使用して重複を防止します。

(私は、変数として渡され、ステータス項目でWHERE句で結果を制限する能力を維持する必要があり、クエリはPHPの機能の中に含まれていることに注意してください。)

のアイデア?

SELECT tasks.*, users.profile_pic, 
CASE WHEN tasks.updated_at > tasks.created_at 
THEN tasks.updated_at 
ELSE tasks.created_at 
END AS recent_activity 
FROM tasks 
INNER JOIN users 
ON tasks.updated_by = users.name OR tasks.created_by = users.name 
WHERE status <> :status1 AND status <> :status2 
ORDER BY recent_activity DESC LIMIT 10' 
+0

この場合、created_byはupdated_byより新しいでしょうか? – Uueerdo

+0

SELECT句と同じCASE文をON句に使用します。 –

+0

@Uueerdoすべてのタスクを含めると、作成されたアイテムは、新しいアイテムが頻繁に作成されるため、更新されたアイテムよりも新しいアイテムにすることができます。個々のタスクでは、更新されたタイムスタンプは常に作成されたタイムスタンプよりも新しいものになります。 – seibzehn

答えて

1

あなたは "もし" ORとの論理とANDのようなので、多くのエミュレートすることができます:あなたは選択を持っているものに似

ON (tasks.updated_at > tasks.created_at AND tasks.updated_by = users.name) 
    OR (tasks.updated_at <= tasks.created_at AND tasks.created_by = users.name) 

または使用ロジック:

ON CASE 
     WHEN tasks.updated_at > tasks.created_at 
     THEN tasks.updated_by 
     ELSE tasks.created_by 
     END = users.name 

を代わりに(上記のようなORとより複雑な比較はインデックス作成のメリットを除外しているので)、usersテーブルに2回参加して、選択中のE:

SELECT tasks.* 
    , CASE WHEN tasks.updated_at > tasks.created_at 
    THEN uu.profile_pic 
    ELSE cu.profile_pic 
    END AS recent_profile_pic 
    , CASE WHEN tasks.updated_at > tasks.created_at 
    THEN uu.name 
    ELSE cu.name 
    END AS recent_activity 
FROM tasks 
LEFT JOIN users AS uu ON tasks.updated_by = uu.name 
INNER JOIN users AS cu ON tasks.created_by = cu.name 
WHERE status <> :status1 AND status <> :status2 
ORDER BY recent_activity DESC LIMIT 10 

これは、彼らがの一部であったテーブルを指定しませんでしたあなたが使用するすべてのフィールドがtasksからであったと余分なあいまいさを引き起こすことはありません参加を前提としています。

+0

'updated_by'がNULLである可能性がある場合、LEFT JOINを「更新ユーザー」に使用する必要があります。 –

+0

@PaulSpiegelああ、良いキャッチ、私はちょうど私の最初のパスで素早くカット/ペースト/再エイリアスでした。 – Uueerdo

+1

適切なインデックスを使用すると、join-twice-solutionが最速のものになります。また、 'created_at'が' updatet_at'よりも古いものではない場合、 'tasks.updated_at AS recent_profile_pic'を選択することもできます。 uptadeが作成されていないときに 'updated_by'が常にNULLになっている場合、' COALESCE(uu.profile_pic、cu.profile_pic) 'を選択することができます。そうすれば、コードは複雑に見えなくなります。 –

関連する問題