2017-08-07 59 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