【问题标题】:Order by created_date if less than 1 month old, else sort by updated_date如果不到 1 个月,则按 created_date 排序,否则按 updated_date 排序
【发布时间】:2017-01-12 05:23:11
【问题描述】:

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 排序。我还想按updated_date 对order_index = 1 的行进行排序

【问题讨论】:

    标签: postgresql postgresql-9.3


    【解决方案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;
    

    当排序列的类型不同时,这种方法很有用。

    【讨论】:

    • 这没有给出正确的结果。另外,您可以使用order_index。我计划为order_index 添加更多值,所以它不应该被取出。
    • 哎呀。订单索引。比较难用,计算列只能按位置引用,所以不能在表达式中使用。
    猜你喜欢
    • 2013-06-05
    • 1970-01-01
    • 2018-03-21
    • 2019-07-15
    • 2012-09-11
    • 1970-01-01
    • 2016-10-03
    • 2019-05-27
    • 1970-01-01
    相关资源
    最近更新 更多