【问题标题】:Mixed sorting of dates in MySQLMySQL中日期的混合排序
【发布时间】:2015-04-29 12:03:37
【问题描述】:

我有一个日期列,其中包含日期值或空值。我用它来保存产品的有效期。我想编写一个查询以按以下顺序获取它们:尚未过期、未过期(null)和已过期。

例如,假设今天是 5 月 15 日:

prd_id   prd_name   Expiry Date
-----------------
1    name1         May 16
2    name2         May 17
3    name3         May 18
4    name4         May 21
5    namex         null
6    namex         null
7    namex         null
8    namex         May 14
9    namex         May 12

(空值表示没有过期)

我该怎么做?

【问题讨论】:

  • 如果它是一个日期列,mysql 将正确排序日期。只需使用order by date
  • 你有没有尝试过?
  • @AgeDeO php 将对它们进行升序或降序排序,但我需要的是它们的组合,请检查示例
  • 提供你的表定义和一些示例数据集
  • @sgtBOSE 是的,我无法得到 asc 和 desc 的组合。截至目前,我正在 php 中获取和排序它们。我正在寻找唯一的 mysql 解决方案。

标签: php mysql


【解决方案1】:

您可以尝试以下语法:-

SELECT *
FROM YOUR_TABLE
ORDER BY CASE WHEN expire_date > CURDATE() THEN 1 END,
WHEN expire_date IS NULL THEN 2 Desc END,
WHEN expire_date < CURDATE() THEN 3 Desc END;

【讨论】:

  • 我在这里有几个疑问 1)“case”的顺序是什么 2)当 expire_date > CURDATE() 和 desc 在其他条件下,asc 排序在哪里完成
  • Case 应用 Just a condin order by 子句。对于 Asc 和 Desc,请立即查看 mu 编辑
  • 小心!我看到了三个问题: 必须使用IS NULL or IS NOT NULL 而不是仅使用=、 来测试null,您需要处理到期日期为当前日期的情况,以及查询doesn't actually work
  • @ChrisForrence,您的 NULL 点已被接受。并纠正和休息,我认为是正确的。
  • @AnkitBajpai - 我建议设置一个表进行测试; NULL 检查不是我在第三点中提出的问题;这是您对 CASE 语句的使用。
【解决方案2】:

基本上,您将把三个单独的查询连接在一起:

SELECT * FROM (SELECT * FROM `product_entries` WHERE expires_on IS NOT NULL AND expires_on > CURDATE()
    ORDER BY expires_on ASC) a
  UNION ALL
SELECT * FROM (SELECT * FROM `product_entries` WHERE expires_on IS NULL) b
  UNION ALL
SELECT * FROM (SELECT * FROM `product_entries` WHERE expires_on IS NOT NULL AND expires_on <= CURDATE() 
    ORDER BY expires_on DESC) c

第一个返回没有过期的,第二个返回没有过期的,第三个返回过期的。

请记住,您希望为 expires_on 列编制索引。此外,正如您在第三个查询中看到的那样,我将当前日期计算为过期。如果您希望当天算作未过期,则在第三个查询中将&lt;= 更改为&lt;,在第一个查询中将&gt; 更改为&gt;=


另一种选择是使用 CASE 子句(如果您不关心每个条目的顺序,只要未过期的在顶部,永久产品在中间,过期的条目在底部)

mysql> SELECT * FROM product_entries ORDER BY CASE 
    ->     WHEN expires_on >= CURDATE() THEN 3
    ->     WHEN expires_on IS NULL THEN 2
    ->     WHEN expires_on < CURDATE() THEN 1
    -> END DESC;

+----+-------------+
| id | expire_date |
+----+-------------+
|  9 | 2015-05-11  |
|  8 | 2015-05-06  |
|  7 | 2015-05-01  |
| 10 | NULL        |
|  6 | 2015-04-26  |
|  5 | 2015-04-21  |
|  4 | 2015-04-16  |
|  3 | 2015-04-11  |
|  2 | 2015-04-06  |
|  1 | 2015-04-01  |
+----+-------------+

【讨论】:

  • 我的原始查询与 UNION 和 ORDER BY 有一个小问题;此问题已修复。
  • 你觉得怎么样??这个查询优化了吗?还是这是正确的逻辑??
  • @AnkitBajpai 是否尽可能高效?不。但是,它很清楚,更重要的是,它有效。
  • 只有工作不是正确的逻辑解决方案。在编程领域,您必须具体并优化以获得更好的吞吐量和结果。
  • @AnkitBajpai - 不;首先是让它正确,然后是优化。您绝对确定您的查询确实有效吗?你试过运行它吗?
猜你喜欢
  • 1970-01-01
  • 2016-04-07
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 2011-09-04
  • 1970-01-01
相关资源
最近更新 更多