En plus de la réponse de @ delmadord et de vos commentaires:
Actuellement, il n'y a pas de méthode pour créer une sous-requête dans la FROM
clause, vous devez donc utiliser manuellement l'instruction brute, puis, si nécessaire, vous fusionnerez toutes les liaisons:
$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();
N'oubliez pas que vous devez fusionner les liaisons dans le bon ordre . Si vous avez d'autres clauses liées, vous devez les mettre aprè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
sous-sélection, vous devez ajoutergetQuery()
deux fois =>$sub->getQuery()->getQuery()
toSql
. Lisez à propos de PDO php.net/manual/en/book.pdo.php et voyez le résultat de votre$query->toSql()
$sub
requête est un Eloquent Builder , vous avez toujours besoin de la->getQuery()
partie, sinon vous obtenez une erreur, car cette méthode est associée à uneQuery\Builder
classe.Laravel v5.6.12 (2018-03-14) ajouté
fromSub()
etfromRaw()
méthodes pour le générateur de requêtes (# 23476) .La réponse acceptée est correcte mais peut être simplifiée en:
L'extrait de code ci-dessus produit le SQL suivant:
la source
La solution de @JarekTkaczyk c'est exactement ce que je recherchais. La seule chose qui me manque, c'est comment le faire lorsque vous utilisez des
DB::table()
requêtes. Dans ce cas, voici comment je fais:Une attention particulière comment faire le
mergeBindings
sans utiliser lagetQuery()
méthodela source
DB::raw()
fait le travail pour moiÀ partir de laravel 5.5, il existe une méthode dédiée pour les sous-requêtes et vous pouvez l'utiliser comme ceci:
ou
la source
Call to undefined method subSelect()
semblesubSelect
n'existe pas.selectSub
. J'ai mis à jour ma réponse maintenant.J'aime faire quelque chose comme ça:
Ce n'est pas très élégant, mais c'est simple.
la source
Je n'ai pas pu faire votre code pour faire la requête souhaitée, l'AS est un alias uniquement pour la table
abc
, pas pour la table dérivée. Laravel Query Builder ne prend pas implicitement en charge les alias de table dérivés, DB :: raw est très probablement nécessaire pour cela.La solution la plus simple que j'ai pu trouver est presque identique à la vôtre, mais produit la requête comme vous l'avez demandé:
La requête produite est
la source
La manière correcte décrite dans cette réponse: https://stackoverflow.com/a/52772444/2519714 La réponse la plus populaire à l'heure actuelle n'est pas totalement correcte.
De cette façon, https://stackoverflow.com/a/24838367/2519714 n'est pas correct dans certains cas comme: la sélection de sous a où les liaisons, puis la jonction de la table à la sous-sélection, puis d'autres endroits ajoutés à toutes les requêtes. Par exemple, requête:
select * from (select * from t1 where col1 = ?) join t2 on col1 = col2 and col3 = ? where t2.col4 = ?
Pour effectuer cette requête, vous allez écrire du code comme:Pendant l'exécution de cette requête, sa méthode
$query->getBindings()
retournera les liaisons dans un ordre incorrect comme['val3', 'val1', 'val4']
dans ce cas plutôt correct['val1', 'val3', 'val4']
pour le SQL brut décrit ci-dessus.Encore une façon correcte de le faire:
Les liaisons seront également automatiquement et correctement fusionnées avec la nouvelle requête.
la source