Laravel Eloquent groupBy orderBy 在 MariaDB 中给出不同的结果
Posted
技术标签:
【中文标题】Laravel Eloquent groupBy orderBy 在 MariaDB 中给出不同的结果【英文标题】:Laravel Eloquent groupBy orderBy gives different results in MariaDB 【发布时间】:2019-12-01 05:17:55 【问题描述】:我已经在 SO 和 MariaDB 中阅读过这方面的内容,并且了解 mysql 和 Mariadb 之间的这种不兼容性。但我不确定如何在 Laravel Eloquent / DB 查询中解决这个问题。
我的问题: groupBy
orderBy
查询在 MariaDB 和 MySql 中给出了不同的结果。它在 mySql 中运行良好,因为 MariaDB 中的结果顺序不同。
这是我的查询:
$messages = ChatMessages::select(DB::raw('t.*'))
->from(DB::raw('(SELECT * FROM chat_messages ORDER BY created_at DESC) t'))
->whereIn('message_id', $messageIds)
->groupBy('message_id')
->orderBy('created_at', 'DESC')
->paginate(3);
例如,假设这是chat_messages
表:
+----+----------+---------------------+-----------+
| id | message_id | created_at | name |
+----+----------+---------------------+-----------+
| 1 | 1000 | 2017-01-01 06:03:40 | Anna |
+----+----------+---------------------+-----------+
| 2 | 1007 | 2017-01-02 07:13:20 | Becky |
+----+----------+---------------------+-----------+
| 3 | 1000 | 2017-01-03 08:20:12 | Christina |
+----+----------+---------------------+-----------+
| 4 | 1004 | 2017-01-03 08:20:15 | Dorothy |
+----+----------+---------------------+-----------+
| 5 | 1004 | 2017-01-04 09:25:45 | Emma |
+----+----------+---------------------+-----------+
| 6 | 1000 | 2017-01-05 10:30:10 | Fiona |
+----+----------+---------------------+-----------+
| 7 | 1007 | 2017-01-05 10:33:23 | Gigi |
+----+----------+---------------------+-----------+
| 8 | 1007 | 2017-01-06 12:46:34 | Heidi |
+----+----------+---------------------+-----------+
| 9 | 1000 | 2017-01-06 12:46:34 | Irene |
+----+----------+---------------------+-----------+
| 10 | 1007 | 2017-01-07 14:58:37 | Jane |
+----+----------+---------------------+-----------+
| 11 | 1007 | 2017-01-07 14:58:37 | Katy |
+----+----------+---------------------+-----------+
查询在 MySql 数据库中运行良好,结果返回如下:
+----+----------+---------------------+-----------+
| id | message_id | created_at | name |
+----+----------+---------------------+-----------+
| 11 | 1007 | 2017-01-07 14:58:37 | Katy |
+----+----------+---------------------+-----------+
| 9 | 1000 | 2017-01-06 12:46:34 | Irene |
+----+----------+---------------------+-----------+
| 5 | 1004 | 2017-01-04 09:25:45 | Emma |
+----+----------+---------------------+-----------+
但是,在 MariaDB 数据库中,返回的结果不正确,如下所示。似乎首先按升序对message_id
进行分组,然后将orderBy
添加到其中:
+----+----------+---------------------+-----------+
| id | message_id | created_at | name |
+----+----------+---------------------+-----------+
| 4 | 1004 | 2017-01-03 08:20:15 | Dorothy |
+----+----------+---------------------+-----------+
| 2 | 1007 | 2017-01-02 07:13:20 | Becky |
+----+----------+---------------------+-----------+
| 1 | 1000 | 2017-01-01 06:03:40 | Anna |
+----+----------+---------------------+-----------+
我尝试将查询更改为使用unique()
,而不是像这样:
ChatMessages::whereIn('message_id', $messageIds)
->orderBy('created_at', 'DESC')
->paginate(3)
->unique('message_id');
虽然它在 MariaDB 和 MySql 中的工作方式相同,但分页是在唯一检查之前应用的,因此返回的结果较少:
+----+----------+---------------------+-----------+
| id | message_id | created_at | name |
+----+----------+---------------------+-----------+
| 11 | 1007 | 2017-01-07 14:58:37 | Katy |
+----+----------+---------------------+-----------+
| 9 | 1000 | 2017-01-06 12:46:34 | Irene |
+----+----------+---------------------+-----------+
我该如何解决这个问题?
【问题讨论】:
【参考方案1】:你很可能试图做一个“groupwise max”。这不能再通过使用带有ORDER BY
的子查询的技巧来完成。
子查询,但定义,没有顺序。但是,在过去,MariaDB 和 MySQL 都会执行ORDER BY
,而这恰好有利于外部查询。
MariaDB 最先忽略了内部的ORDER BY
; MySQL后来接受了它。按照标签 [greatest-n-per-group] 了解各种解决方法。
【讨论】:
感谢您的回复@Rick。我正在考虑的另一种解决方法是使用 php 本身和拆分查询来完成这项工作。例如,第一个查询使用 group by 获取结果,然后使用 php 遍历循环并获取每个查询的最新条目。与之前的联合声明相比,似乎多了很多额外的查询。我会仔细阅读,看看是否还有其他解决方法。以上是关于Laravel Eloquent groupBy orderBy 在 MariaDB 中给出不同的结果的主要内容,如果未能解决你的问题,请参考以下文章
GroupBy() 覆盖我的选择语句 Eloquent Laravel
Laravel Eloquent GroupBy 多对一关系
Laravel 6,MYSQL - 如何使用 Laravel Querybuilder 或 Model Eloquent 将子查询与 GroupBY 左连接?
Laravel Eloquent groupBy() 并且还返回每个组的计数