Answers:
除了@delmadord的答案和您的评论:
当前没有在FROM
子句中创建子查询的方法,因此您需要手动使用raw语句,然后,如有必要,将合并所有绑定:
$sub = Abc::where(..)->groupBy(..); // Eloquent Builder instance
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery()) // you need to get underlying Query Builder
->count();
请注意,您需要以正确的顺序合并绑定。如果还有其他绑定子句,则必须将它们放在mergeBindings
:
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
// ->where(..) wrong
->mergeBindings($sub->getQuery()) // you need to get underlying Query Builder
// ->where(..) correct
->count();
$sub
查询是Eloquent Builder,那么您仍然需要该->getQuery()
部件,否则会出错,因为此方法是针对Query\Builder
类进行类型化提示的。
添加了Laravel v5.6.12(2018-03-14)fromSub()
和fromRaw()
查询生成器(#23476)的方法。
可接受的答案是正确的,但可以简化为:
DB::query()->fromSub(function ($query) {
$query->from('abc')->groupBy('col1');
}, 'a')->count();
上面的代码片段产生以下SQL:
select count(*) as aggregate from (select * from `abc` group by `col1`) as `a`
@JarekTkaczyk的解决方案正是我想要的。我唯一想念的是在使用DB::table()
查询时该怎么做
。在这种情况下,这就是我的做法:
$other = DB::table( DB::raw("({$sub->toSql()}) as sub") )->select(
'something',
DB::raw('sum( qty ) as qty'),
'foo',
'bar'
);
$other->mergeBindings( $sub );
$other->groupBy('something');
$other->groupBy('foo');
$other->groupBy('bar');
print $other->toSql();
$other->get();
特别注意mergeBindings
不使用getQuery()
方法的制作方法
DB::raw()
确实为我完成了工作
从laravel 5.5开始,有一种专用的子查询方法,您可以像这样使用它:
Abc::selectSub(function($q) {
$q->select('*')->groupBy('col1');
}, 'a')->count('a.*');
要么
Abc::selectSub(Abc::select('*')->groupBy('col1'), 'a')->count('a.*');
Call to undefined method subSelect()
似乎subSelect
不存在。
selectSub
。我已经更新了我的回复。
我喜欢做这样的事情:
Message::select('*')
->from(DB::raw("( SELECT * FROM `messages`
WHERE `to_id` = ".Auth::id()." AND `isseen` = 0
GROUP BY `from_id` asc) as `sub`"))
->count();
它不是很优雅,但是很简单。
我无法让您的代码执行所需的查询,AS仅是表的别名abc
,而不是派生表的别名。Laravel查询生成器不隐式支持派生表别名,为此很可能需要DB :: raw。
我能想到的最直接的解决方案几乎与您的解决方案相同,但是会根据您的要求生成查询:
$sql = Abc::groupBy('col1')->toSql();
$count = DB::table(DB::raw("($sql) AS a"))->count();
产生的查询是
select count(*) as aggregate from (select * from `abc` group by `col1`) AS a;
此答案中描述的正确方法:https : //stackoverflow.com/a/52772444/2519714 当前最受欢迎的答案并不完全正确。
这种方式https://stackoverflow.com/a/24838367/2519714在某些情况下是不正确的:子选择具有where绑定,然后将表联接到子选择,然后将其他位置添加到所有查询。例如查询:
select * from (select * from t1 where col1 = ?) join t2 on col1 = col2 and col3 = ? where t2.col4 = ?
要进行此查询,您将编写如下代码:
$subQuery = DB::query()->from('t1')->where('t1.col1', 'val1');
$query = DB::query()->from(DB::raw('('. $subQuery->toSql() . ') AS subquery'))
->mergeBindings($subQuery->getBindings());
$query->join('t2', function(JoinClause $join) {
$join->on('subquery.col1', 't2.col2');
$join->where('t2.col3', 'val3');
})->where('t2.col4', 'val4');
在执行此查询期间,他的方法$query->getBindings()
将以不正确的顺序返回绑定,例如['val3', 'val1', 'val4']
在这种情况下,它会['val1', 'val3', 'val4']
针对上述原始sql 正确。
一种更正确的时间执行此操作:
$subQuery = DB::query()->from('t1')->where('t1.col1', 'val1');
$query = DB::query()->fromSub($subQuery, 'subquery');
$query->join('t2', function(JoinClause $join) {
$join->on('subquery.col1', 't2.col2');
$join->where('t2.col3', 'val3');
})->where('t2.col4', 'val4');
绑定也将自动正确地合并到新查询中。
belongsToMany
选择,则必须添加getQuery()
两次=>$sub->getQuery()->getQuery()