SQL小提琴:http://sqlfiddle.com/#!15/1da00/5
我有一张看起来像这样的表:
products
+-----------+-------+--------------+--------------+
| name | price | created_date | updated_date |
+-----------+-------+--------------+--------------+
| chair | 50 | 10/12/2016 | 1/4/2017 |
| desk | 100 | 11/4/2016 | 12/27/2016 |
| TV | 500 | 12/1/2016 | 1/2/2017 |
| computer | 1000 | 12/28/2016 | 1/1/2017 |
| microwave | 100 | 1/3/2017 | 1/4/2017 |
| toaster | 20 | 1/9/2017 | 1/9/2017 |
+-----------+-------+--------------+--------------+
我想以这样的方式订购此表:如果产品创建时间少于30天,那么结果应首先显示(并按更新日期排序)。如果产品是在30天或更多天前创建的,我希望它在之后显示(并按照该组中的更新日期排序)
这就是结果应该是这样的:
products - desired results
+-----------+-------+--------------+--------------+
| name | price | created_date | updated_date |
+-----------+-------+--------------+--------------+
| toaster | 20 | 1/9/2017 | 1/9/2017 |
| microwave | 100 | 1/3/2017 | 1/4/2017 |
| computer | 1000 | 12/28/2016 | 1/1/2017 |
| chair | 50 | 10/12/2016 | 1/4/2017 |
| TV | 500 | 12/1/2016 | 1/2/2017 |
| desk | 100 | 11/4/2016 | 12/27/2016 |
+-----------+-------+--------------+--------------+
我开始编写此查询:
SELECT *,
CASE
WHEN created_date > NOW() - INTERVAL '30 days' THEN 0
ELSE 1
END AS order_index
FROM products
ORDER BY order_index, created_date DESC
但只会将created_date
的行减少到30天,然后按created_date
排序。我还希望按order_index
updated_date
= 1的行进行排序
答案 0 :(得分:1)
不幸的是,在版本9.3中,order by
中只能使用位置列号或涉及表列的表达式,因此order_index
根本无法使用case
,其位置不是定义良好的因为它出现在列列表中的*
之后。
这样可行。
order by
created_date <= ( current_date - 30 ) , case
when created_date > ( current_date - 30 ) then created_date
else updated_date end desc
或者,可以使用公用表表达式来包装结果,然后可以按任何列对其进行排序。
WITH q AS(
SELECT *,
CASE
WHEN created_date > NOW() - INTERVAL '30 days' THEN 0
ELSE 1
END AS order_index
FROM products
)
SELECT * FROM q
ORDER BY
order_index ,
CASE order_index
WHEN 0 THEN created_date
WHEN 1 THEN updated_date
END DESC;
第三种方法是利用空值。
order by
case
when created_date > ( current_date - 30 ) then created_date
end desc nulls last,
updated_date desc;
当排序列具有不同类型时,此方法非常有用。