0

我有一组需要同时以多种方式排序的数据。

简化后,该表可概括为:

任务

  • ID
  • 组(整数)
  • 日期(日期)
  • 完成 (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”子句的顺序,但似乎任何组合都无法达到我所追求的效果——某些东西总是出现在错误的位置。

非常感谢任何帮助。

4

2 回答 2

1

所以你想按组中最早的日期排序,然后将整个组保持在一起?

您可以在 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

然后,您可以开始尝试在该聚合中包含其他字段(如 Complete)。例如,此查询应从包含不完整任务和不完整单个任务的组开始。之后是已完成的任务和仅包含已完成任务的组。在组内,仍然应用排序,将未完成的任务放在上面已完成的任务上,然后按日期对它们进行排序。正如你所看到的,很多额外的逻辑只需要对查询进行很小的更改:

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
于 2013-11-11T13:25:02.323 回答
1

怎么样:

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

于 2013-11-11T13:31:33.037 回答