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

ご注文を確認することができます。整数を日付と混合しています。それらはどのように分類されるべきですか? –

答えて

0

CASE... WHENにそれらの条件のすべてを置くために方法はありません。 CASE ... WHENは、WHERE節に1つの擬似列を効果的に作成します。あなたがしたことは、次のものと変わることはありません。

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は、基本的にはboolean型の列のシリーズを作成して、ソートにそれらを追加している、上記の一つのアプローチがあります。

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表す:sort_indexがnull使用がソートのため、別段の最後に結果を投げることはない場合

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

この場合は、ロジックは、「complete並べ替えであります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

-valueトリックを使用して、最後のNULLをソートしてみます。私は他のものと同様に合体も追加しました。これは本当にその事例を浄化します。

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

また、あまり意味がありませんby句私のあなたが考えてみればsqlfiddle

関連する問題