假设我有一个这样的用户表:
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1@mail.com | 24 |
| 2 | Josh | josh99@mail.com | 29 |
| 3 | Joseph | joseph410@mail.com | 21 |
| 4 | George | gge.48@mail.com | 28 |
| 5 | Joseph | jh.city89@mail.com | 24 |
| 6 | Kim | kimsd@mail.com | 32 |
| 7 | Bob | bob.s@mail.com | 38 |
| 8 | Joseph | psa.jos@mail.com | 34 |
| 9 | Joseph | joseph.la@mail.com | 28 |
| 10 | Jonathan | jonhan@mail.com | 22 |
+----+-----------+---------+------------+------+
实际上,数据库由更多的数据组成,其中一些数据是重复的,有两条以上的记录。但问题是,我只想得到包含"Joseph"名称的重复行的第一行和第二行,我如何才能做到这一点?到目前为止我的代码。。。
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 1')->get();
使用该代码,结果将检索到:
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1@mail.com | 24 |
| 2 | Josh | josh99@mail.com | 29 |
| 3 | Joseph | joseph410@mail.com | 21 |
| 4 | George | gge.48@mail.com | 28 |
| 6 | Kim | kimsd@mail.com | 32 |
| 7 | Bob | bob.s@mail.com | 38 |
| 10 | Jonathan | jonhan@mail.com | 22 |
+----+-----------+---------+------------+------+
我用这个代码试图获得第二个重复的行:
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 2')->get();
结果仍然与上面提到的相同:
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1@mail.com | 24 |
| 2 | Josh | josh99@mail.com | 29 |
| 3 | Joseph | joseph410@mail.com | 21 |
| 4 | George | gge.48@mail.com | 28 |
| 6 | Kim | kimsd@mail.com | 32 |
| 7 | Bob | bob.s@mail.com | 38 |
| 10 | Jonathan | jonhan@mail.com | 22 |
+----+-----------+---------+------------+------+
我希望结果是得到id为"5"、名称为"Joseph"的记录,如下所示:
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1@mail.com | 24 |
| 2 | Josh | josh99@mail.com | 29 |
| 4 | George | gge.48@mail.com | 28 |
| 5 | Joseph | jh.city89@mail.com | 24 |
| 6 | Kim | kimsd@mail.com | 32 |
| 7 | Bob | bob.s@mail.com | 38 |
| 10 | Jonathan | jonhan@mail.com | 22 |
+----+-----------+---------+------------+------+
但似乎只检索到了第一个重复行,而我无法获得第二个重复行。有人能给我建议吗?
让我们从您的查询开始
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 1')->get();
这将显示计数等于1或更多的所有行组。这是对CCD_ 1的描述。
如果只想获得重复的记录,则应该获得计数大于1的组。
这里需要注意的另一件事是,将随机选择一个非聚集列。因为当您获得一个名称并计数时,例如,如果您选择name,count(name), email
(电子邮件不在按子句分组-不聚合(,并且4行具有相同的名称。所以你会看到:
+--------+-------------+-------+
| Name | Count(Name) | Email |
+--------+-------------+-------+
| Joseph | 4 | X |
+--------+-------------+-------+
你期待什么而不是X
?4封电子邮件中的哪一封?实际上,在SQLServer中,禁止选择非聚集列,而其他数据库只会给您一个计数为3的随机列。有关详细信息,请参阅这个答案,它解释得很好:SELECT列表中的所有列都必须出现在GROUP BY子句中吗
因此,我们将使用having count(name) > 1
,只选择聚合列name
DB::from('users')->select('name')->groupBy('name')->havingRaw('count("name") > 1')->get();
这应该会给你(没有测试(这个:
+--------+-------------+
| name | Count(name) |
+--------+-------------+
| Joseph | 4 |
+--------+-------------+
这将为您提供具有2个或更多实例的所有名称。您可以在haven子句中确定重复项的数量。例如,having count(name) = 3
将为您提供正好有3个重复项的所有名称。
那么如何获得第二个副本呢?我有一个问题:
第一份(原件(是什么?是created_at
最老的还是updated_at
最老的?或者其他情况?。因此,您应该使用order by
子句进行另一个查询,以最方便的顺序提供重复项。例如:
select * from `users` where `name` in (select `name` from users group by `name` having count(`name`) > 1) order by `id` asc
将给出:
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 3 | Joseph | joseph410@mail.com | 21 |
| 5 | Joseph | jh.city89@mail.com | 24 |
| 8 | Joseph | psa.jos@mail.com | 34 |
| 9 | Joseph | joseph.la@mail.com | 28 |
+----+-----------+---------+------------+------+