是否可以根据 Laravel 的 ORM 中的多列删除重复项?
Is it possible to remove duplicates based on multiple columns in Laravel's ORM?
用户可以重新提交比赛结果,它会更新记分牌上的结果,但是,它还会为“Way back when”功能创建结果保存,以便能够查看之前的结果分数的提高。
我遇到的问题是某些月份存在重复条目,数据库中唯一发生变化的是主键 id
、created_at
和 updated_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",
},
]
用户可以重新提交比赛结果,它会更新记分牌上的结果,但是,它还会为“Way back when”功能创建结果保存,以便能够查看之前的结果分数的提高。
我遇到的问题是某些月份存在重复条目,数据库中唯一发生变化的是主键 id
、created_at
和 updated_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",
},
]