Além da resposta de @ delmadord e seus comentários:
Atualmente não há nenhum método para criar uma subconsulta na FROM
cláusula, então você precisa usar manualmente a instrução bruta e, se necessário, mesclar todas as ligações:
$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();
Lembre-se de que você precisa mesclar as ligações na ordem correta . Se você tiver outras cláusulas vinculadas, deve colocá-las após 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();
belongsToMany
getQuery()
$sub->getQuery()->getQuery()
toSql
. Leia sobre o PDO php.net/manual/en/book.pdo.php e veja o resultado de seu$query->toSql()
$sub
consulta for um Eloquent Builder , então você ainda precisa da->getQuery()
parte, caso contrário, obterá um erro, uma vez que este método é baseado em tipo contra aQuery\Builder
classe.Laravel v5.6.12 (14/03/2018) adicionado
fromSub()
efromRaw()
métodos para o construtor de consultas (# 23476) .A resposta aceita está correta, mas pode ser simplificada em:
O snippet acima produz o seguinte SQL:
fonte
A solução do @JarekTkaczyk é exatamente o que eu procurava. A única coisa que sinto falta é como fazer quando você está usando
DB::table()
consultas. Nesse caso, é assim que eu faço:Atenção especial como fazer
mergeBindings
sem usar ogetQuery()
métodofonte
DB::raw()
fez o trabalho para mimNo laravel 5.5 há um método dedicado para subconsultas e você pode usá-lo assim:
ou
fonte
Call to undefined method subSelect()
parecesubSelect
que não existe.selectSub
. Eu atualizei minha resposta agora.Eu gosto de fazer algo assim:
Não é muito elegante, mas é simples.
fonte
Não consegui fazer seu código para fazer a consulta desejada, o AS é um alias apenas para a tabela
abc
, não para a tabela derivada. O Laravel Query Builder não suporta implicitamente apelidos de tabela derivados, DB :: raw é provavelmente necessário para isso.A solução mais direta que encontrei é quase idêntica à sua, mas produz a consulta que você solicitou:
A consulta produzida é
fonte
A maneira correta descrita nesta resposta: https://stackoverflow.com/a/52772444/2519714 A resposta mais popular no momento atual não é totalmente correta.
Desta forma, https://stackoverflow.com/a/24838367/2519714 não é correto em alguns casos como: sub select has where bindings, a seguir juntando a tabela para sub select, então outro where adicionado a todas as consultas. Por exemplo, consulta:
select * from (select * from t1 where col1 = ?) join t2 on col1 = col2 and col3 = ? where t2.col4 = ?
Para fazer esta consulta, você escreverá um código como:Durante a execução dessa consulta, seu método
$query->getBindings()
retornará ligações em ordem incorreta, como['val3', 'val1', 'val4']
neste caso, em vez de corrigir['val1', 'val3', 'val4']
para sql bruto descrito acima.Mais uma vez a maneira correta de fazer isso:
Além disso, as ligações serão automaticamente e corretamente mescladas na nova consulta.
fonte