【问题标题】:Mysql ORDER BY conditions in query depends on date查询中的Mysql ORDER BY条件取决于日期
【发布时间】:2012-06-24 12:42:35
【问题描述】:

我有一个 mysql 查询,它获取设计列表中的行。在这个列表中,我们有“普通”行,它们按它们的 id 排序,还有“特殊”行,它们按“special_end”(这是日期,现在在所有行中为 NULL)参数排序。因此,结果中的“特殊”行应该高于“正常”。

立即查询:

SELECT d.*, DATE_FORMAT(_created, '%d.%m.%Y') as _created_human, count(dp.id) photos_cnt, u.id user_id, u.class_name user_class_name, u.full_name user_full_name
FROM designs d
LEFT JOIN design_photo dp ON d.id=dp.design_id 
LEFT JOIN cms_user u ON d.cms_user_id=u.id
WHERE 1=1  AND d.status_id=1 AND d.published=1 AND u.cms_user_status_id=1 
GROUP BY d.id
ORDER BY d.special_end DESC, id DESC 
LIMIT 20 OFFSET 0

我需要升级此查询中的 ORDER BY 块以使用 special_end 参数对行进行排序,条件为:

  • 如果 d.special_end >= DATE(NOW() ) -> 按 d.special_end DESC 排序,
  • 如果 d.special_end 按 id DESC 排序。

示例(id - row - special_end):

515 design4 2012-07-21
514 design3 2012-06-30
526 design5 null
513 design2 2012-05-30 (this date is <= DATE( NOW() ))
512 design1 null
511 design0 null
.
.
.

我已经尝试过写类似的东西

ORDER BY CASE d.special_end WHEN d.special_end >= DATE( NOW() ) THEN d.special_end WHEN d.special_end <= DATE( NOW() ) THEN d.id END DESC

ORDER BY IF(d.special_end >= DATE( NOW() ), d.special_end, d.id) DESC

但没有结果。

感谢您的帮助。

【问题讨论】:

    标签: mysql if-statement sql-order-by conditional case


    【解决方案1】:

    按条件排序可能会非常慢,我宁愿使用UNION 来达到相同的结果:

    SELECT t.* FROM (
        (
            SELECT d.*, DATE_FORMAT(_created, '%d.%m.%Y') as _created_human, count(dp.id) photos_cnt, u.id user_id, u.class_name user_class_name, u.full_name user_full_name
            FROM designs d
            LEFT JOIN design_photo dp ON d.id=dp.design_id 
            LEFT JOIN cms_user u ON d.cms_user_id=u.id
            WHERE d.special_end >= DATE(NOW()) AND d.status_id=1 AND d.published=1 AND u.cms_user_status_id=1 
            GROUP BY d.id
            ORDER BY d.special_end DESC
        ) UNION (
            SELECT d.*, DATE_FORMAT(_created, '%d.%m.%Y') as _created_human, count(dp.id) photos_cnt, u.id user_id, u.class_name user_class_name, u.full_name user_full_name
            FROM designs d
            LEFT JOIN design_photo dp ON d.id=dp.design_id 
            LEFT JOIN cms_user u ON d.cms_user_id=u.id
            WHERE (d.special_end < DATE(NOW()) OR d.special_end IS NULL) AND d.status_id=1 AND d.published=1 AND u.cms_user_status_id=1 
            GROUP BY d.id
            ORDER BY d.id DESC
        )
    ) t LIMIT 20 OFFSET 0
    

    【讨论】:

    • 感谢您的回答。在 LIMIT 之前应该有一个 extre ")"(否则 - 语法错误消息)。现在我得到“每个派生表都必须有自己的别名”消息。
    • 它可能,只是可能,与UNION ALL 一起工作。我不会相信UNION
    • @VasiliyToporov 哦,抱歉,已修复。 @ypercube UNION ALL 也可以使用,但你为什么不相信UNION
    • 编辑后出现“UNION 和 ORDER BY 的使用不正确”消息。在编辑之前,我得到了有趣的结果:d.special_end DESC 块工作正常,d.id DESC 块(设计过时)按 d.id ASC 排序。
    • @VasiliyToporov 再次抱歉。 MySQL 有非常愚蠢的语法规则,我不得不把括号放回查询。您报告的错误排序没有意义,因为我的查询有错字:) 这个版本应该没问题。
    【解决方案2】:

    当有多个 Group by 或排序要求时,始终使用 UNION 拆分您的查询。 只需使用 UNION 运算符拆分您的查询并进行排序。如下所示

    Select * from Something where <condtion> order by 1 desc
    UNION
    Select * from Something where <condtion> order by 2 desc
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-06
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-28
      相关资源
      最近更新 更多