首页 > 解决方案 > 如何在 laravel 5.5 中只获取第二条重复记录?

问题描述

假设我有一个这样的用户表:

+----+-----------+----------------------+------+
| 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   |
    +----+-----------+---------+------------+------+

但似乎只检索到第一个重复行,我无法获得第二个重复行,有人可以给我建议吗?

标签: mysqldatabaselaravellaravel-5eloquent

解决方案


让我们从您的查询开始

User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 1')->get();

这将显示计数等于或大于 1 的所有行组。这是 的描述DISTINCT

如果您只想获取重复记录,您应该获取计数大于 1 的组。

这里要注意的另一件事是,将随机选择一个非聚合列。因为当您获得一个名称并且它是计数时,例如,如果您选择name,count(name), email(电子邮件不在 group by 子句中 - 未聚合),并且 4 行具有相同的名称。所以你会看到:

+--------+-------------+-------+
| Name   | Count(Name) | Email |
+--------+-------------+-------+
| Joseph | 4           | X     |
+--------+-------------+-------+

你期望什么而不是X?4 封电子邮件中的哪一封?实际上,在 SQLServer 中,禁止选择非聚合列,其他数据库只会给你一个随机的 3 个。有关更多详细信息,请参阅此答案,它的解释很好:Do all columns in a SELECT list have to appear in一个 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 个或更多实例的所有名称。您可以确定have子句中的重复数。例如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   |
+----+-----------+---------+------------+------+

推荐阅读