我需要订购记录并将“热门”(推广)记录放在首位。如果记录的hot_expires_at
列不为空且未来,则该记录为“热门”。目前我有这个简单明了的解决方案:
ORDER BY
IF( hot_expires_at IS NOT NULL AND hot_expires_at > NOW(),
hot_expires_at, from_unixtime(0)) DESC,
created_at DESC
然而,这需要一个文件分区,并且随着时间的推移变得非常慢,因为我有数十万条记录。 (如果有帮助的话,其中只有一小部分是“热门”。)
我知道我可以运行一个额外的工作,每隔几分钟计算一次rank
字段 - 这将足够接近实时。但这似乎是一种蛮力的解决方案。
我还可以将查询拆分为两个(“hot”和“not”),并添加组合结果的外部逻辑,但这也很粗糙且容易出错。
我正在寻找在MySQL中使用MySQL设施的正确方法。
答案 0 :(得分:0)
我会以与现在略有不同的方式解决此问题。首先,我会废除时间戳字段hot_expires_at
的概念,对于旧记录而言NULL
,而对于#34; hot"而不是NULL
。记录。相反,我会将名称更改为expires_at
,我会确保每个记录都有这样的字段。关于这种设计的清洁之处在于,它使您不必存储记录是否热的状态。相反,时间戳本身包含确定标签所需的所有信息。
出于报告的目的,您可以SELECT
确定给定记录是否为热点"只需检查它是否会在将来的某个时间点到期。因此,以下类型的查询应该完成这项工作:
SELECT *, CASE WHEN expires_at > NOW() THEN "hot" ELSE "not" END AS is_hot
FROM your_table
ORDER BY expires_at DESC, created_at DESC
答案 1 :(得分:0)
当您使用函数NOW()时,它每次都会返回一个值来评估每条记录。正如您所提到的,您拥有数十万条记录,因此他们的评估需要花费很多时间。我认为你必须修改用于IF语句的值,例如在查询开始之前使用由NOW()初始化的变量或者使用SYSDATE()函数。
“另外,SET TIMESTAMP语句会影响NOW()而不是SYSDATE()返回的值。这意味着二进制日志中的时间戳设置对SYSDATE()的调用没有影响。将时间戳设置为a非零值会导致NOW()的每次后续调用返回该值。将timestamp设置为零会取消此效果,以便NOW()再次返回当前日期和时间。“