2016-12-02 48 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端使用的兩個記錄的方法嗎?

我只是尋找的想法,因爲我試圖避免一個N + 1查詢問題,必須單獨查詢每個列表。

回答

2

依靠動態查詢是凌亂的。你最好是拉動運營商進入查詢WHERE一部分,並與一個或配對:

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 *想要創建一個動態查詢,很難做到一步到位,but it is definitely doable

+0

我正在探索你的第二個選項,在加入語句中的邏輯,但我看到一個奇怪的事情。在這種情況下,'(lists.ordered = 1 AND cnt1.id ATLChris

相關問題