是否可以根据 Laravel 的 ORM 中的多列删除重复项?

Is it possible to remove duplicates based on multiple columns in Laravel's ORM?

用户可以重新提交比赛结果,它会更新记分牌上的结果,但是,它还会为“Way back when”功能创建结果保存,以便能够查看之前的结果分数的提高。

我遇到的问题是某些月份存在重复条目,数据库中唯一发生变化的是主键 idcreated_atupdated_at。如果列值:discipline_n wheren is one through six are all the same as any other others shouldn't be queried, ie:

id 1                                     id 2
username foo                             username foo
discipline_one 4                         discipline_one 4
discipline_two 5                         discipline_two 5
discipline_three 8                       discipline_three 8
discipline_four 9                        discipline_four 9
discipline_five 4                        discipline_five 4
discipline_six 6                         discipline_six 6
created_at yesterday for example         created_at today for example
updated_at yesterday for example         updated_at today for example

应被视为重复项,因此应从结果中删除。我已经尝试使用内置于 Laravel 的 ORM 中的 distinct() 函数,但我仍然得到重复项。这可以只用 SQL 来完成吗?我在这里的预期输出是:

id 2
username foo
discipline_one 4
...

其中 id 1 作为重复项被忽略。我试过:

$waybackWhen = \App\Models\ResultSave::where('username', $result->username)
    ->distinct([
        'discipline_one',
        'discipline_two',
        'discipline_three',
        'discipline_four',
        'discipline_five',
        'discipline_six',
    ])
    ->get();

我从前段时间问过的一个问题开始对它进行了一些研究。

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER
    (PARTITION BY username, discipline_one, discipline_two, discipline_three,
     discipline_four, discipline_five, discipline_six ORDER BY id DESC) rn
    FROM results
)

SELECT id, username, discipline_one, discipline_two, discipline_three,
     discipline_four, discipline_five, discipline_six, created_at, updated_at
FROM cte
WHERE rn = 1

致谢:@tim-biegeleisen

之前

id username discipline_one discipline_two discipline_three discipline_four discipline_five discipline_six created_at updated_at
1 qivr 489 23 1 2 89 34 2021-11-21 17:49:28 2021-11-25 18:40:26
7 foo 4 5 8 9 4 6 2021-11-01 19:45:01 2021-11-01 19:45:42
8 foo 4 5 8 9 4 6 2021-11-02 19:45:15 2021-11-02 19:45:46
9 foo 4 5 8 9 4 6 2021-11-03 19:45:20 2021-11-03 19:45:50

之后

id username discipline_one discipline_two discipline_three discipline_four discipline_five discipline_six created_at updated_at
1 qivr 489 23 1 2 89 34 2021-11-21 17:49:28 2021-11-25 18:40:26
9 foo 4 5 8 9 4 6 2021-11-03 19:45:20 2021-11-03 19:45:50

Laravel


    public static function waybackWhen($result)
    {
        $username = $result->username;

        config()->set('database.connections.mysql.strict', false);
        DB::reconnect(); // Important as the existing connection if any would be in strict mode.

        $resultSet = DB::select("
            WITH cte AS (
                SELECT *, ROW_NUMBER() OVER
                (PARTITION BY username, discipline_one, discipline_two, discipline_three,
                 discipline_four, discipline_five, discipline_six ORDER BY id DESC) rn
                FROM results
            )
            
            SELECT id, username, discipline_one, discipline_two, discipline_three,
                 discipline_four, discipline_five, discipline_six, created_at, updated_at
            FROM cte
            WHERE rn = 1 AND username = ? 
       ", [ $username ]);

        // Now changing back the strict ON.
        config()->set('database.connections.mysql.strict', true);
        DB::reconnect();

        return $resultSet;

    }

输出

=> [
     {#3409
       +"id": 9,
       +"username": "foo",
       +"discipline_one": "4",
       +"discipline_two": "5",
       +"discipline_three": "8",
       +"discipline_four": "9",
       +"discipline_five": "4",
       +"discipline_six": "6",
       +"created_at": "2021-11-03 19:45:20",
       +"updated_at": "2021-11-03 19:45:50",
     },
   ]