【问题标题】:Is it possible to remove duplicates based on multiple columns in Laravel's ORM?是否可以根据 Laravel 的 ORM 中的多个列删除重复项?
【发布时间】:2022-01-05 16:58:44
【问题描述】:

用户可以重新提交比赛结果,它会更新记分板上的结果,但是,它还会为“何时返回”功能创建结果保存,以便能够查看以前的结果以查看改进分数。

我遇到的问题是某些月份存在重复条目,数据库中唯一更改的是主键idcreated_atupdated_at。如果列值:discipline_n wheren is onesix 与任何其他列值都相同,则不应查询,即:

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();

【问题讨论】:

    标签: php sql laravel laravel-8


    【解决方案1】:

    根据我前段时间提出的一个问题,我对它进行了一些尝试。

    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 MySQL : Find duplicate records but EXCLUDE the first one from the list

    之前

    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",
         },
       ]
    
    

    【讨论】:

    • 非常感谢,非常感谢您也将您的问题联系起来。这是接近它的好方法!虽然,我怀疑这里有一个没有转义 $username 内容的 SQLi,所以我现在将研究如何在 Laravel 中使用 RAW SQL 查询同时使用准备好的语句。
    • 对于未来的观众,这可以像 PDO 中的正常情况一样在by binding the parameters 完成
    • @Jaquarh ,也感谢您提供参数绑定建议。我已经相应地重构了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 2019-01-14
    • 2015-04-27
    • 2021-02-09
    • 2017-03-02
    • 1970-01-01
    相关资源
    最近更新 更多