質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

6回答

1481閲覧

SQL文で、ソート条件の場合分け

avantgarden

総合スコア121

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

1クリップ

投稿2019/02/18 06:53

登録日から30日以内の場合は、先頭にもってきて登録日降順

そうでない場合は、下に持ってきて「Number」カラムの値降順(Numberはint型の数値カラムです)

を実現したいです。

途中は省きますが、現状では

ORDER BY CASE WHEN Created >= DATE_ADD(NOW(), INTERVAL -30 DAY) THEN 1(1) ELSE 2(2) END, Created DESC

と書いていて、これだと(1)も(2)も登録日降順で並びます。

(1)の場合は登録日降順
(2)の場合は「Number」カラム降順

とするには、どのようにSQLに追記すればいいのでしょうか。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ORDER BYでどうこうするのではなく、ORDER BYで制御しやすい値を生成してあげるのが通常の手法かと思います。
2案考えましたが、どちらも一長一短。

案1
同じCASEが2回登場するので冗長です。

SQL

1SELECT 2 CASE 3 WHEN Created >= DATE_ADD(NOW(), INTERVAL -30 DAY) THEN 2 4 ELSE 1 5 END AS ORDER1, 6 CASE 7 WHEN Created >= DATE_ADD(NOW(), INTERVAL -30 DAY) THEN 30-DateDiff(NOW(), Created) 8 ELSE Number 9 END AS ORDER2, 10 11ORDER BY 12 ORDER1 DESC, ORDER2 DESC

案2
案1を1カラムにまとめました。
仮に10000と20000にしています。
Numberデータが4桁より大きい場合は桁を増やしてください。
上限が決められないような場合、この案は使えません。

SQL

1SELECT 2 CASE 3 WHEN Created >= DATE_ADD(NOW(), INTERVAL -30 DAY) THEN 20000 + (30 - DateDiff(NOW(), Created)) 4 ELSE 10000 + Number 5 END AS ORDER1, 6ORDER BY 7 ORDER1 DESC

投稿2019/02/18 07:30

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2019/02/18 10:23

日付型とint型で型が違うものをcaseの出力にするのは型の違いでエラーにならないですか? 仮に型を合わせるとしても、別体系になるように扱わないと正しくソートされないのでは?
ttyp03

2019/02/18 11:56

型は合わせてるつもりですが。 時間がなかったので厳密に正しく書けてないかもしれません。 間違ってたらご指摘願います。
sazi

2019/02/18 12:03

datediffで数値にしてるって事でしたか。 (暗黙変換はしてくれるんでしょうけどdatediffの戻型が今更ながら分からない・・・) 20000と10000でブロック分けしているのはあくまで例って事なんですね。
ttyp03

2019/02/18 23:46

ブロック分けは例ではないですよ。 20000台に30日以内のレコード、10000台にそれ以外のレコードが来るように重み付けをしています。 20000台は20000~20030なのでいいですが、10000台はレコード数によっては19999を超える可能性があるので、桁を増やすなり別の対応が必要ですってことです。
guest

0

登録日から30日以内の場合は、先頭にもってきて登録日降順、
そうでない場合は、下に持ってきて「Number」カラムの値降順(Numberはint型の数値カラムです)

上記は3つのソート項目に分解できます。

A.登録日から30日以内かどうか
B.登録日降順
C.「Number」カラムの値降順

ポイントとしては、Aの条件に該当しないBやCは同じ値にする事です。

SQL

1order by 2 CASE WHEN Created >= DATE_ADD(NOW(), INTERVAL -30 DAY) THEN 1 ELSE 2 end 3 , CASE WHEN Created >= DATE_ADD(NOW(), INTERVAL -30 DAY) THEN Created end desc 4 , CASE WHEN Created < DATE_ADD(NOW(), INTERVAL -30 DAY) THEN Number end

※上記の場合は値を与えない(=Null)としています。

投稿2019/02/18 07:58

編集2019/02/18 08:10
sazi

総合スコア25197

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

mst10806様が仰ってるとおり、unionでやるのがわかりやすくていいと思います。
また、KCBR6502様の質問文をそのまま使うならば、この形でしょうか。

SQL

1order by 2 case 3 when 4 Created >= CURRENT_DATE - 30 then ((select min(Number) from table_name)-1) 5 else 6 Number 7 end, 8 Created

※なお、当方Postgresqlでの確認ですので、方言をMysqlに直してご利用下さい。

投稿2019/02/18 07:36

Batoh33789

総合スコア136

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ざっくり回答で申し訳ないですが(テーブル定義やサンプルデータが不明でもありますし)、
「登録日から30日以内」のデータと「登録日から30日以降」のデータを別個で取得してUNIONするのが一番良さそうに思います。

投稿2019/02/18 07:02

編集2019/02/18 07:02
m.ts10806

総合スコア80852

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

今日が仮に2019-02-18だとして
※Numberを利用して結合データをソートするならzerofillしておくのがラク
(ただし想定する最大値を以上の桁を用意すること)

SQL

1create table tbl (id int primary key,Number int(11) unsigned zerofill,Created date); 2insert into tbl values 3(1,10,'2018-01-01'), 4(2,20,'2018-01-01'), 5(3,15,'2019-01-01'), 6(4,5,'2019-01-01'), 7(5,1,'2019-02-01'), 8(6,10,'2019-02-02'), 9(7,10,'2019-02-01');
  • とりあえず表示

SQL

1select *,case when Created >= curdate() - interval 30 day then concat('1_',number) 2else concat('2_',Created) end as odrder_data 3from tbl;
  • orderby

SQL

1select * from tbl 2order by case when Created >= curdate() - interval 30 day then concat('1_',number) 3else concat('2_',Created) end desc;

投稿2019/02/18 07:19

編集2019/02/18 07:20
yambejp

総合スコア114883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  • 登録日から30日以内の場合は登録日を返す
  • 30日を超える場合は 1970-01-01 などの固定の値を返す

を CASE 式で出力して、降順ソート。
固定の値に関しては Number カラムで降順ソート。
とすれば良いのではないですか?

投稿2019/02/18 07:03

mather

総合スコア6753

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問