Count 在 Laravel Query Builder 中没有按预期工作
Count does not work as expected in Laravel Query Builder
我正在尝试获取数据库中有多少个名字。为此,我使用这样的查询生成器:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->count();
是说24,这是不正确的,因为如果我会这样写代码:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get();
结果对象包含 247 个元素,这是正确的。我试过 skip/take,但仍然没有结果。我哪里错了?感谢您的帮助。
犬烧说得对
(id, name_id),
(1,1),
(2,1),
(3,2),
(4,3)
有四行,所以 get() 方法将 return 4 行
但是如果你使用 groupBy 则有三个组 [name_id]
1 (1,1)
2 (2)
3 (3)
现在计数将 return 3
希望这会有所帮助。
我认为情况恰恰相反,您没有得到 24 个组。您将在第一组中获得 24 个元素。该配置导致以下查询:
SELECT
COUNT(*) AS 'aggregate',
`name_id`
FROM `names_to_options`
WHERE EXISTS(
{your $havingRaw sub-query}
)
GROUP BY `name_id`;
您最终得到的结果将如下所示:
+---------------+---------+
| aggregate | name_id |
+---------------+---------+
| 24 | 1 |
+---------------+---------+
| 5 | 2 |
+---------------+---------+
| 30 | 3 |
+---------------+---------+
| ... and so on | 4 |
+---------------+---------+
Query\Builder
只是没有意识到当涉及 count()
时您可以获得不止一个结果。
虽然你自己已经非常接近正确答案了。
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get();
get()
returns Support\Collection
的子 Eloquent\Collection
,它有自己版本的 count 方法。所以你的答案只是:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get()
->count();
如果您真的希望在 MySQL 中发生这种情况,您希望发生的查询将如下所示:
SELECT COUNT(*) FROM (
SELECT
`name_id`
FROM `names_to_options`
WHERE EXISTS(
{your $havingRaw sub-query}
)
GROUP BY `name_id`
) AS temp;
为此,您可以这样做:
$query = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having);
$sql = $query->toSql();
$values = $query->getBindings();
$count = DB::table(DB::raw('('.$sql.') AS `temp`'))
->selectRaw("COUNT(*) AS 'aggregate'", $values)
->first()
->aggregate;
MySQL 要求它编写这样的临时表时,性能可能会变得有点毛茸茸,所以你必须试验一下,看看哪个选项更快。
我正在尝试获取数据库中有多少个名字。为此,我使用这样的查询生成器:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->count();
是说24,这是不正确的,因为如果我会这样写代码:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get();
结果对象包含 247 个元素,这是正确的。我试过 skip/take,但仍然没有结果。我哪里错了?感谢您的帮助。
犬烧说得对
(id, name_id),
(1,1),
(2,1),
(3,2),
(4,3)
有四行,所以 get() 方法将 return 4 行
但是如果你使用 groupBy 则有三个组 [name_id]
1 (1,1)
2 (2)
3 (3)
现在计数将 return 3
希望这会有所帮助。
我认为情况恰恰相反,您没有得到 24 个组。您将在第一组中获得 24 个元素。该配置导致以下查询:
SELECT
COUNT(*) AS 'aggregate',
`name_id`
FROM `names_to_options`
WHERE EXISTS(
{your $havingRaw sub-query}
)
GROUP BY `name_id`;
您最终得到的结果将如下所示:
+---------------+---------+
| aggregate | name_id |
+---------------+---------+
| 24 | 1 |
+---------------+---------+
| 5 | 2 |
+---------------+---------+
| 30 | 3 |
+---------------+---------+
| ... and so on | 4 |
+---------------+---------+
Query\Builder
只是没有意识到当涉及 count()
时您可以获得不止一个结果。
虽然你自己已经非常接近正确答案了。
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get();
get()
returns Support\Collection
的子 Eloquent\Collection
,它有自己版本的 count 方法。所以你的答案只是:
$namesIdsCount = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having)
->get()
->count();
如果您真的希望在 MySQL 中发生这种情况,您希望发生的查询将如下所示:
SELECT COUNT(*) FROM (
SELECT
`name_id`
FROM `names_to_options`
WHERE EXISTS(
{your $havingRaw sub-query}
)
GROUP BY `name_id`
) AS temp;
为此,您可以这样做:
$query = DB::table('names_to_options')
->select('name_id')
->groupBy('name_id')
->havingRaw($having);
$sql = $query->toSql();
$values = $query->getBindings();
$count = DB::table(DB::raw('('.$sql.') AS `temp`'))
->selectRaw("COUNT(*) AS 'aggregate'", $values)
->first()
->aggregate;
MySQL 要求它编写这样的临时表时,性能可能会变得有点毛茸茸,所以你必须试验一下,看看哪个选项更快。