是否可以根据 Laravel 的 ORM 中的多个列删除重复项?
Posted
技术标签:
【中文标题】是否可以根据 Laravel 的 ORM 中的多个列删除重复项?【英文标题】:Is it possible to remove duplicates based on multiple columns in Laravel's ORM? 【发布时间】:2022-01-05 16:58:44 【问题描述】:用户可以重新提交比赛结果,它会更新记分板上的结果,但是,它还会为“何时返回”功能创建结果保存,以便能够查看以前的结果以查看改进分数。
我遇到的问题是某些月份存在重复条目,数据库中唯一更改的是主键id
、created_at
和updated_at
。如果列值:discipline_n
wheren
is one
到 six
与任何其他列值都相同,则不应查询,即:
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();
【问题讨论】:
【参考方案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 ,也感谢您提供参数绑定建议。我已经相应地重构了我的答案。以上是关于是否可以根据 Laravel 的 ORM 中的多个列删除重复项?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在 laravel ORM 的增量中添加 tinyInteger 或 smallInteger?
是否有一个带有/ORM(Laravel、Cake、Codeigniter)的 PHP 框架,我们可以在其中覆盖数据交互以从 rest api 中获取数据?