关于排序:在MySQL中按GROUP BY名称之前的日期和时间排序

ORDER BY date and time BEFORE GROUP BY name in mysql

我有一个像这样的表:

1
2
3
4
5
name    date         time
tom | 2011-07-04 | 01:09:52
tom | 2011-07-04 | 01:09:52
mad | 2011-07-04 | 02:10:53
mad | 2009-06-03 | 00:01:01

我首先要使用最早的名字:

(->无效!)

现在它应该让我先发疯(早点date),然后再发给tom

但使用GROUP BY name ORDER BY date ASC, time ASC首先给我带来了新的生气,因为它在排序之前就进行了分组!

再次:问题是我无法在分组之前按日期和时间排序,因为GROUP BY必须在ORDER BY之前!


另一种方法:

1
2
3
4
5
6
SELECT *
FROM (
    SELECT * FROM table_name
    ORDER BY date ASC, time ASC
) AS sub
GROUP BY name

GROUP BY会在它匹配的第一个匹配结果上分组。如果第一个匹配项恰好是您想要的匹配项,那么一切都会按预期进行。

我更喜欢这种方法,因为子查询具有逻辑意义,而不是在其他条件下使用它。


由于我不允许对user1908688的答案发表评论,因此以下是MariaDB用户的提示:

1
2
3
4
5
6
7
SELECT *
FROM (
     SELECT *
     ORDER BY date ASC, time ASC
     LIMIT 18446744073709551615
     ) AS sub
GROUP BY sub.name

https://mariadb.com/kb/zh-CN/mariadb/why-is-order-by-in-a-from-subquery-ignored/


我认为这就是您要寻找的:

1
2
3
4
SELECT name, min(date)
FROM myTable
GROUP BY name
ORDER BY min(date)

目前,您必须通过STR_TO_DATE来创建一个mysql日期:

1
STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s')

所以:

1
2
3
4
SELECT name, min(STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s'))
FROM myTable
GROUP BY name
ORDER BY min(STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s'))


这对我有用:

1
2
3
4
5
6
7
SELECT *
FROM your_table
WHERE id IN (
    SELECT MAX(id)
    FROM your_table
    GROUP BY name
);

使用子选择:

1
2
3
4
select name, date, time
from mytable main
where date + time = (select min(date + time) from mytable where name = main.mytable)
order by date + time;

为我工作mysql
选择*从(SELECT number,max(date_added)作为datea FROM sms_chat按数字分组)作为按日期排序的datea desc


在Oracle中,这对我有用

1
2
3
SELECT name, min(date), min(time)
    FROM table_name
GROUP BY name

解决此问题的另一种方法是使用LEFT JOIN,它可能更有效。我首先从一个仅考虑日期字段的示例开始,因为将日期时间存储在一个datetime列中可能更常见,并且我还希望保持查询简单,以便于理解。

因此,在此特定示例中,如果要基于date列显示最旧的记录,并假设表名名为people,则可以使用以下查询:

1
2
3
4
SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date > p2.date
WHERE p2.date is NULL
GROUP BY p.name

LEFT JOIN的作用是,当p.date列为最小值时,在左侧联接上将没有p2.date且其值较小,因此相应的p2.date将为NULL 。因此,通过添加WHERE p2.date is NULL,我们确保仅显示日期最早的记录。

同样,如果要显示最新记录,只需在LEFT JOIN

中更改比较运算符

1
2
3
4
SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date < p2.date
WHERE p2.date is NULL
GROUP BY p.name

现在,对于这个特定的示例,其中日期时间是单独的列,如果要基于合并的两列的日期时间进行查询,则需要以某种方式添加它们,例如:

1
2
3
4
SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date + INTERVAL TIME_TO_SEC(p.time) SECOND > p2.date + INTERVAL TIME_TO_SEC(p2.time) SECOND
WHERE p2.date is NULL
GROUP BY p.name

您可以在"保持某列的分组最大值的行"页面上阅读有关此内容的更多信息(以及其他实现此方法的方法)。


我在这个问题上有一个不同的变体,其中我只有一个DATETIME字段,并且在根据DATETIME字段进行降序排序后,在group bydistinct之后需要一个limit是什么帮助了我:

在这种情况下,如果使用拆分字段,则可以对concat进行排序,那么您可能可以摆脱类似这样的情况:

然后,如果您想限制,则只需将限制语句添加到末尾:


这不是确切的答案,但是对于希望解决在mysql中按组先行排序方法的人们来说,这可能会有所帮助。

当我想找到最新的行(order by date desc,但对于特定的列类型(group by column name)仅获得一个结果时,我来到了该线程。

解决此问题的另一种方法是利用聚合。

因此,我们可以像往常一样运行查询,该查询对asc进行排序并以max(doc) as latest_doc引入新字段,该字段将提供最新日期,并按同一列进行分组。

假设您现在要查找特定列的数据,并且无法完成最大聚合。
通常,要查找特定列的数据,可以使用GROUP_CONCAT aggregator,并使用该列中无法显示的某些唯一分隔符(例如GROUP_CONCAT(string SEPARATOR ' ') as new_column),并且在访问它时,可以拆分/分解new_column字段。

同样,这可能并不对所有人都适用。我做到了,也很喜欢它,因为我写了很少的函数,而且我无法运行子查询。我正在为PHP编写codeigniter框架。

也不确定其复杂性,也许有人可以对此有所了解。

此致:)