如何以某种方式对这些SQL结果进行排序?
我正在制作一款活动日历应用程序。用户主页上显示了两种类型的事件:如何以某种方式对这些SQL结果进行排序?,sql,postgresql,sqlalchemy,Sql,Postgresql,Sqlalchemy,我正在制作一款活动日历应用程序。用户主页上显示了两种类型的事件: 附近活动-计划日期在未来3天内或过去1小时内的活动 正常事件-没有计划日期或计划日期超过3天的事件 这是事件表:id、用户id、内容、发生时间、创建时间 目前,我正在显示这些按日期排序的事件,创建这些事件是为了首先显示新添加的内容 我想要的是先显示所有附近的事件并按计划日期排序,然后显示正常事件并按创建日期排序。我认为这有助于更好的用户体验,但我不知道如何去做 更新 最后是这个查询,它是几个答案的组合 orderbycoalesc
id、用户id、内容、发生时间、创建时间
目前,我正在显示这些按日期排序的事件,创建这些事件是为了首先显示新添加的内容
我想要的是先显示所有附近的事件并按计划日期排序,然后显示正常事件并按创建日期排序。我认为这有助于更好的用户体验,但我不知道如何去做
更新
最后是这个查询,它是几个答案的组合
orderbycoalesce(发生在:min\u时间和发生在<:max\u时间,0)DESC、发生在ASC、创建于
orderby
子句可以包含任意逻辑,而不仅仅是字段名,因此,在伪代码中,您可以
SELECT ...
...
ORDER BY (date_diff(occurs_at, now) <= '3 days'), occurs_at DESC, created_at DESC
选择。。。
...
ORDER BY(date_diff(occurs_at,now)我将通过一个字段来扩展SELECT子句,确定它是否在“附近”(在时间,而不是地点)
选择
id、用户id、内容、发生时间、创建时间、,
case when date_diff(d,occurs_at,now)正如@MarcB所提到的,您可以通过一个表达式进行排序,尽管对于PostgreSQL,该表达式看起来有些不同
SELECT * FROM Events
ORDER BY CASE WHEN (occurs_at - '3 days'::interval) < CURRENT_TIMESTAMP
THEN occurs_at
ELSE '9999-01-01'::timestamp
END, created_at;
从事件中选择*
按案例排序(发生时间为-'3天::间隔)<当前时间戳
然后发生在
ELSE“9999-01-01”::时间戳
结束,创建于;
请注意,“9999-01-01”在某种程度上是一个任意选择的日期,如果有人知道“maxdate”的PostgreSQL常量,我会感兴趣:)Verbose格式
更容易解释/理解
WITH x AS (
SELECT *
, COALESCE(occurs_at <= (now() + interval '3 days'), FALSE) AS nearby
FROM events
WHERE occurs_at >= now() - interval '1 hour' -- exclude older events
OR occurs_at IS NULL
) -- CTE is not strictly necessary, just to make ORDER BY clearer
SELECT *
FROM x
ORDER BY
nearby DESC
, CASE WHEN nearby THEN occurs_at ELSE created_at END
如果可以避免,就不要这样做。它迫使Postgres为每一行计算一个值,并使普通索引无法使用。更多信息在此
简单版本
短一点,快一点
SELECT *
FROM events
WHERE occurs_at >= now() - interval '1h'
OR occurs_at IS NULL
ORDER BY
COALESCE( occurs_at <= (now()::date + 3), FALSE) DESC
, CASE WHEN occurs_at <= (now()::date + 3)
THEN occurs_at ELSE created_at END;
选择*
从事件中
其中发生在>=now()处-间隔“1h”
或在为空时发生
订购人
合并(发生在您使用的数据库管理系统中?MySQL?SQL Server?PostgreSQL,通过SQLAlchemy的方式。您可以添加假排序列来实现这一点(Beth的回答)。但在检索事件后,您可以很容易地在内存中重新排列SA查询的结果。Postgres为您准备了一些东西。:)。在v8.3之前,这些仅适用于类型时间戳
。从v8.4开始,它们也为日期工作。但是我不认为我们需要在这个例子中使用无限
(以及更高!)。顺便说一句,+1提供一个工作的SQLFIDLE。我我想你错过了过去的事件和没有时间表的事件。我的回答中有详细内容。
date_diff(d,occurs_at, now) <= 3 -- date_diff is also tSQL, not Postgres
SELECT *
FROM events
WHERE occurs_at >= now() - interval '1h'
OR occurs_at IS NULL
ORDER BY
COALESCE( occurs_at <= (now()::date + 3), FALSE) DESC
, CASE WHEN occurs_at <= (now()::date + 3)
THEN occurs_at ELSE created_at END;