0

0

Laravel ORM:基于多列去除重复数据的高效方法

花韻仙語

花韻仙語

发布时间:2025-10-30 10:22:28

|

514人浏览过

|

来源于php中文网

原创

laravel orm:基于多列去除重复数据的高效方法

本文旨在解决在使用 Laravel ORM 时,如何基于多个列的值来移除重复记录的问题。通过使用 SQL 的窗口函数 `ROW_NUMBER()`,结合 Laravel 的 DB facade,提供了一种高效且易于理解的解决方案,避免了循环遍历和复杂的逻辑判断,并附带详细代码示例,帮助开发者快速实现该功能。

在使用 Laravel ORM 进行数据查询时,有时需要根据多个字段的值来判断记录是否重复,并只保留其中的一条。例如,在保存用户提交的比赛结果时,如果只更新分数,而不希望每次提交都创建一条新记录,就需要去除基于用户和各个科目的分数相同的重复记录,只保留最新的那一条。Laravel 提供的 distinct() 方法通常只能用于单个字段的去重,无法满足这种多列去重的需求。以下介绍一种使用 SQL 窗口函数结合 Laravel DB facade 实现多列去重的方案。

使用 SQL 窗口函数 ROW_NUMBER() 去重

核心思路是利用 SQL 的窗口函数 ROW_NUMBER() 为每个分组(基于需要去重的列)内的记录分配一个序号,然后只保留序号为 1 的记录。

ROW_NUMBER() OVER (PARTITION BY column1, column2, ... ORDER BY column_to_order DESC)

  • PARTITION BY column1, column2, ...: 指定分组的列,具有相同值的记录将被分到同一个组。
  • ORDER BY column_to_order DESC: 指定组内记录的排序方式,通常按照主键或时间戳倒序排列,以便保留最新的记录。

以下是一个 SQL 示例,假设我们有一个名为 results 的表,需要基于 username、discipline_one 到 discipline_six 这几个字段去重,并保留 id 最大的那条记录:

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

这个SQL语句首先使用Common Table Expression (CTE) cte,计算每个分组内的行号,并将结果存储在名为 rn 的列中。然后,从 cte 中选择 rn = 1 的记录,即每个分组内的第一条记录,也就是最新的记录。

MVM mall 网上购物系统
MVM mall 网上购物系统

采用 php+mysql 数据库方式运行的强大网上商店系统,执行效率高速度快,支持多语言,模板和代码分离,轻松创建属于自己的个性化用户界面 v3.5更新: 1).进一步静态化了活动商品. 2).提供了一些重要UFT-8转换文件 3).修复了除了网银在线支付其它支付显示错误的问题. 4).修改了LOGO广告管理,增加LOGO链接后主页LOGO路径错误的问题 5).修改了公告无法发布的问题,可能是打压

下载

在 Laravel 中实现多列去重

为了在 Laravel 中使用上述 SQL 语句,可以借助 Laravel 的 DB facade,它允许直接执行原始 SQL 查询。

use Illuminate\Support\Facades\DB;

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

    // 临时关闭 MySQL 严格模式 (可选,如果需要)
    config()->set('database.connections.mysql.strict', false);
    DB::reconnect(); // 重新连接数据库,使配置生效

    $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 ]);

    // 恢复 MySQL 严格模式 (可选)
    config()->set('database.connections.mysql.strict', true);
    DB::reconnect();

    return $resultSet;
}

代码解释:

  1. DB::select(): 使用 DB facade 的 select() 方法执行 SQL 查询。
  2. SQL 查询: 使用上面提到的 SQL 语句,注意使用 ? 占位符来防止 SQL 注入。
  3. [ $username ]: 将 $username 变量作为参数传递给 SQL 查询,替换占位符。
  4. 严格模式: 如果MySQL开启了严格模式,执行此查询可能会报错。通过config()->set('database.connections.mysql.strict', false);可以临时关闭严格模式,并在查询完成后恢复。需要注意的是,修改配置后需要重新连接数据库才能生效。

使用示例:

$result = App\Models\Result::find(1); // 假设有一个 $result 对象
$waybackWhen = App\Models\Result::waybackWhen($result);

// $waybackWhen 现在包含了去重后的结果集
dd($waybackWhen);

注意事项

  • SQL 注入: 在使用 DB facade 执行原始 SQL 查询时,务必使用参数绑定(? 占位符)来防止 SQL 注入攻击。
  • 性能: 对于大数据量的表,使用窗口函数可能会影响性能。可以考虑添加合适的索引来优化查询。
  • 数据库兼容性: 不同的数据库系统对窗口函数的支持可能略有不同。请根据实际使用的数据库系统调整 SQL 语句。
  • 严格模式: 在MySQL严格模式下,如果SQL语句不符合严格模式的要求,可能会报错。需要根据实际情况选择是否临时关闭严格模式。

总结

本文介绍了一种基于 SQL 窗口函数和 Laravel DB facade 实现多列去重的方案。该方案简洁高效,避免了复杂的循环遍历和逻辑判断,能够有效地解决 Laravel ORM 在多列去重方面的不足。通过合理地使用 SQL 窗口函数,可以极大地简化数据处理逻辑,提高开发效率。

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

319

2024.04.09

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

277

2024.04.09

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

370

2024.04.09

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

371

2024.04.10

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

81

2025.08.05

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

65

2025.08.05

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

68

2025.08.05

数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

686

2023.10.12

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

41

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.9万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 810人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号