我有一组数据需要同时以多种方式排序。
简化后,该表可以总结为:
任务
- 编号
- 组(国际) 日期
- (日期)
- 完成 (0/1)
我需要生成这些任务的列表,主要按"完成"排序,其次按"日期"排序,然后按"组"分组。
该组是导致我出现问题的原因,我有一种感觉,这可能最好用 PHP 实现,因为它可能无法作为查询的一部分 - 欢迎有关解决此问题的最佳方法的提示,它当然不必是纯 mysql。
目前我正在使用:
ORDER BY complete, group, date
这非常适合"未分组"任务,所有未完成的 (0) 任务都在顶部,完成的 (1) 任务在底部;每组完成/未完成的任务按日期排序。
但是,组最终可能会聚集在底部,在更广泛的上下文中日期顺序不正确 - 组本身不会给定其任务日期。下面是不需要的输出(已订购)的示例:
Task #2 - Group(false), Complete(0), date(2013-11-01)
Task #4 - Group(false), Complete(0), date(2013-12-01)
Task #5 - Group(1), Complete(0), date(2013-10-01)
Task #3 - Group(1), Complete(0), date(2013-12-01)
Task #1 - Group(false), Complete(1), date(2013-11-01)
如您所见,分组项目的日期排序不正确,排序发生在组内。任务 #5 排在第三位,即使它的日期最早。
我希望看到的输出如下:
Task #5 - Group(1), Complete(0), date(2013-10-01)
Task #3 - Group(1), Complete(0), date(2013-12-01)
Task #2 - Group(false), Complete(0), date(2013-11-01)
Task #4 - Group(false), Complete(0), date(2013-12-01)
Task #1 - Group(false), Complete(1), date(2013-11-01)
即,如果组中的任务的日期早于单个任务,则应首先对整个组进行排序(想象一下,对于一个组,您只能看到"顶部"任务,因此任务#3将在视觉上折叠)。
我尝试更改"ORDER BY"子句的顺序,但似乎没有任何组合可以实现我所追求的 - 某些东西总是在错误的地方结束。
任何帮助非常感谢。
像这样的事情怎么样:
SELECT t1.ID, t1.`Group`, t1.Complete, t1.Due
FROM task t1
LEFT JOIN (
SELECT Complete,
t.`Group`,
MIN(Due) AS MinDate
FROM task t
GROUP BY Complete, t.`Group` ) t2 ON t1.complete = t2.complete AND t1.`Group` = t2.`Group`
ORDER BY t1.complete, IFNULL(t2.MinDate, t1.Due), `Group`, t1.Due
对于每个组记录,将其连接到该组中最早的记录,然后您可以按最早的组日期排序(如果未分组,则仅按日期排序)。
SQLFiddle
所以你想按组中的最早日期排序,然后将整个组放在一起?
您可以使用 YourTable 上的聚合来获取每个组的最低日期。然后,您可以主要按该最小日期排序,然后按其他字段进行排序。
select
t.id,
t.group,
t.date,
t.complete
from
YourTable t
left join
(select
m.group,
min(m.date) as mindate
from
YourTable m) mt on mt.group = t.group
order by
/* Coalesce for individual tasks, which don't have a mindate */
coalesce(mt.mindate, t.date),
t.group,
t.complete,
t.date
然后,您可以开始尝试在该聚合中包含其他字段(如"完成")。例如,此查询应从包含未完成任务和未完成单个任务的组开始。之后是已完成的任务和仅包含已完成任务的组。在组中,仍然应用排序,将未完成的任务放在已完成任务的上方,然后按日期对它们进行排序。如您所见,许多额外的逻辑只对查询进行了很小的更改:
select
t.id,
t.group,
t.date,
t.complete
from
YourTable t
left join
(select
m.group,
min(m.date) as mindate,
min(m.complete) as groupcomplete
from
YourTable m) mt on mt.group = t.group
order by
coalesce(mt.groupcomplete, t.complete),
coalesce(mt.mindate, t.date),
t.group,
t.complete,
t.date