2017-08-07 85 views
0

我在我的導軌模型上有一個範圍,它應該可以幫助我對對象進行排序。這是如下圖所示:ORDER BY CASE子句的作用域不能正常工作

scope :active, ->(u = nil, now = "NOW()") { 
    published_and_private(u).eager_load(:images) 
    .where("(listing = 1 AND complete = 0) OR " +          # LISTING 
     "(online_only = 1 AND scheduled_end_time + INTERVAL 1 DAY >= #{now}) OR " + # TIMED 
     "(online_only = 0 AND listing = 0 AND starts_at + INTERVAL 1 DAY >= #{now})") # LIVE 
    .order("complete, CASE WHEN sort_index IS NOT NULL THEN sort_index " + 
     "WHEN scheduled_end_time IS NOT NULL THEN scheduled_end_time " + 
     "WHEN starts_at IS NOT NULL THEN starts_at ELSE #{now} + INTERVAL 10 YEAR END") 
} 

下面是從返回當查詢被運行數據庫中的數據:

select id, name, complete, sort_index, starts_at, scheduled_end_time from auctions where published = 1 ORDER BY complete, CASE WHEN sort_index IS not NULL THEN sort_index WHEN scheduled_end_time IS NOT NULL THEN scheduled_end_time WHEN starts_at IS NOT NULL THEN starts_at ELSE (NOW() + INTERVAL 10 YEAR) END; 


+----+-----------------------------------+----------+------------+---------------------+---------------------+ 
| id | name        | complete | sort_index | starts_at   | scheduled_end_time | 
+----+-----------------------------------+----------+------------+---------------------+---------------------+ 
| 21 | Listing: Mountain Cabin Estate |  0 |   1 | NULL    | NULL    | 
| 17 | Multi-Item Online Only   |  0 |   2 | 2017-08-07 06:48:00 | 2017-08-21 12:48:00 | 
| 9 | Multi-item Live Auction   |  0 |  NULL | 2017-08-21 18:48:02 | NULL    | 
| 19 | Many Item LIVE Auction   |  0 |  NULL | 2017-08-21 18:48:02 | NULL    | 
| 10 | Single Item Online Only   |  0 |  NULL | 2017-08-07 18:48:03 | 2017-08-22 00:48:02 | 
| 18 | MANY Item Timed Auction   |  0 |  NULL | 2017-08-07 18:48:03 | 2017-08-22 00:48:02 | 
| 22 | LISTING: Multi-parcel Real Estate |  0 |  NULL | NULL    | NULL    | 
| 20 | Bad Images      |  0 |   3 | 2017-08-21 14:48:00 | NULL    | 
| 8 | Single Item Live Auction   |  1 |  NULL | 2017-08-21 18:48:02 | NULL    | 
+----+-----------------------------------+----------+------------+---------------------+---------------------+ 

我的問題是,隨着3排序索引的對象是出地方,這發生在2以上的任何數字,我完全喪失了爲什麼這可能是。我期待查詢將該對象放在sort_index爲2的那個下面。

任何幫助,指導或見解都將不勝感激。

+0

如果你想想你的BY子句順序並沒有太大的意義。你將整數與日期混合在一起。這些應該如何排序? –

回答

0

還有就是不要把所有的這些條件爲CASE... WHEN的方式。 CASE ... WHEN有效地在您的WHERE子句中創建一個僞列。所以你做的沒有什麼不同:

SELECT *, CASE /* your logic */ END AS sort_logic 
/* 
    Notice that the sort_logic column doesn't actually exist in the table. Instead 
    MySQL calculates the value and for the duration of this query 
*/ 
WHERE /* <stuff> */ 
ORDER BY sort_logic 

你真正想要的是一系列的列值。 @Darshan有一種方法之上,這基本上是創建一系列布爾列,並添加那些排序:

complete, ISNULL(sort_index) DESC, 
      /* 
      Desc and ASC are important here. You want NOT NULL values to float to 
      the top, but you want the columns to work in ascending order. 
      */ 
      sort_index ASC, 
      ISNULL(scheduled_end_time) DESC, scheduled_end_time ASC, 
      ISNULL(starts_at) DESC, starts_at ASC, 

也有違約的列值到MySQL最大值的選項。在這種情況下'9999-12-31'表示highest possible date,和~0represents the max int value

complete, 
    ISNULL(sort_index, ~0), 
    ISNULL(scheduled_end_time, '9999-12-31'), 
    ISNULL(starts_at, '9999-12-31') 

在這種情況下,邏輯爲「排序complete,如果sort_index不爲空使用該排序,否則拋出結果的端部sort_index不爲空......「的列表以及所有其他列都遵循相同的邏輯。

1

了,你能ISNULL嘗試代替,例如:

.order("complete, ISNULL(sort_index), sort_index, " + 
     "ISNULL(scheduled_end_time), scheduled_end_time " + 
     "ISNULL(starts_at), starts_at") 
+0

這也不完全正確。排序索引是正確的,但那時需要按時間排序的排序順序不正確 –

+0

您是否在'scheduled_end_time'排序中得到空值? –

0

也許你正在尋找的順序條款是:

order by complete, 
     Coalesce(
      sort_index, 
      scheduled_end_time, 
      starts_at, 
      #{now} + INTERVAL 10 YEAR 
     ) 

但是,你在這種日期比較整數,所以我不知道如何去上班 - 可能通過隱式類型轉換,這不太可能導致期望的結果。

也許你的意思是:

order by complete, 
     sort_index, 
     Coalesce(
      scheduled_end_time, 
      starts_at, 
      #{now} + INTERVAL 10 YEAR 
     ) 
0

嘗試排序NULL值持續使用-value伎倆。我也加入了合併,就像其他人一樣,這真的會清理案件陳述。

ORDER BY 
    complete, 
    -sort_index DESC, -- Sort ascending with nulls last 
    COALESCE(scheduled_end_time, starts_at, now() + INTERVAL 10 YEAR) 
; 

您還可以檢查我的sqlfiddle