2016-12-02 2 views
0

一意のリストごとに最新のレコードまたは古いレコードを取得するために、それ自身で結合するクエリがあります。MySQLのCASEに基づいて演算子を動的に定義する方法はありますか?

SELECT 
    lists.ordered, 
    cnt1.* 
FROM 
    cnt_lists as cnt1 
    LEFT JOIN 
     lists 
     on 
      cnt1.list_id = lists.id 
    LEFT JOIN 
     cnt_lists as cnt2 
     on 
      (cnt1.list_id = cnt2.list_id AND cnt1.id < cnt2.id) 

WHERE 
    cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296') and cnt1.listable_type = 'Movie'; 

このクエリは素晴らしい作品が、lists.orderedは0または1 lists.ordered = 0のいずれかになります私はon文のオペレータがcnt1.id < cnt2.idになりたいけどlists.ordered = 1は、私はそれがcnt1.id > cnt2.idを逆転させることを希望する場合。

CASEステートメントに基づいて演算子を動的に定義する方法はありますか?以下は動作しませんが、私はアイデアを持って遊んでいました。

SELECT 
    lists.ordered, 
    CASE 
     WHEN lists.ordered = 1 THEN '>' 
     ELSE '<' 
    END AS operator, 
    cnt1.* 
FROM 
    cnt_lists as cnt1 
    LEFT JOIN 
     lists 
     on 
      cnt1.list_id = lists.id 
    LEFT JOIN 
     cnt_lists as cnt2 
     on 
      (cnt1.list_id = cnt2.list_id AND cnt1.id operator cnt2.id) 

WHERE 
    cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296') and cnt1.listable_type = 'App\\Models\\Movie'; 

何各リストのために、最上位と最下位の両方を引っ張り、私はPHP側で使用するために、2つのレコードのかを判断できるの仕方は?

私は個々のリストを個別に照会するというN + 1問合せの問題を回避しようとしているので、アイデアを探しています。

答えて

2

動的クエリに依拠するのは面倒です。あなたは、クエリのWHERE一部にその作業を引っ張っ方がいいでしょうし、ORとペアリング:

SELECT 
    lists.ordered, 
    cnt1.* 
FROM 
    cnt_lists as cnt1 
    LEFT JOIN 
     lists 
     on 
      cnt1.list_id = lists.id 
    LEFT JOIN 
     cnt_lists as cnt2 
     on 
      (cnt1.list_id = cnt2.list_id) 

WHERE 
    cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296') 
    and cnt1.listable_type = 'Movie' 
    AND (
     cnt2.id IS NULL /* Including this here because you have a LEFT JOIN */ 
     (lists.ordered = 1 AND cnt1.id < cnt2.id) OR 
     (lists.ordered = 0 AND cnt1.id > cnt2.id) 
    ); 

あなたの他のオプションは、直接参加ロジックにそのロジックを置くことです。これは読みやすいかもしれません。

SELECT 
    lists.ordered, 
    cnt1.* 
FROM 
    cnt_lists as cnt1 
    LEFT JOIN 
     lists 
     on 
      cnt1.list_id = lists.id 
    LEFT JOIN 
     cnt_lists as cnt2 
     on 
      (cnt1.list_id = cnt2.list_id AND (
     (lists.ordered = 1 AND cnt1.id < cnt2.id) OR 
     (lists.ordered = 0 AND cnt1.id > cnt2.id) 
    )) 

WHERE 
    cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296') 
    and cnt1.listable_type = 'Movie' 
    ; 

あなたはあなたの最終的な出力で<を含むためのオプションを持っているが、それは特に有用ではないだろう。

* REALLY *動的クエリを作成したい場合は、1つのステップで行うことは難しいbut it is definitely doable

+0

私はあなたの2番目のオプションをjoinステートメントのロジックで調べていますが、私は奇妙なことが1つあります。この場合 '(lists.ordered = 1 AND cnt1.id ATLChris

関連する問題