Comment faire cela dans Laravel, sous-requête où

121

Comment puis-je faire cette requête dans Laravel:

SELECT 
    `p`.`id`,
    `p`.`name`, 
    `p`.`img`, 
    `p`.`safe_name`, 
    `p`.`sku`, 
    `p`.`productstatusid` 
FROM `products` p 
WHERE `p`.`id` IN (
    SELECT 
        `product_id` 
    FROM `product_category`
    WHERE `category_id` IN ('223', '15')
)
AND `p`.`active`=1

Je pourrais aussi faire cela avec une jointure, mais j'ai besoin de ce format pour les performances.

Marc Buurke
la source

Réponses:

199

Considérez ce code:

Products::whereIn('id', function($query){
    $query->select('paper_type_id')
    ->from(with(new ProductCategory)->getTable())
    ->whereIn('category_id', ['223', '15'])
    ->where('active', 1);
})->get();
Lukaserat
la source
1
Accepté cette réponse, la question est obsolète car elle concernait Laravel 3, et les réponses à venir sont pour Laravel 4, la réponse ci-dessous fonctionnera également pour 4.
Marc Buurke
3
@lukaserat la requête en question applique le ET p. active= 1 vérification sur les tables de produits alors que votre requête l'applique à la table de ProductCategory .... non ?? ou y a-t-il quelque chose qui me manque ..?
hhsadiq
@hhsadiq oui, cela fait référence à ProductCategory.
lukaserat
1
Belle approche avec le nom de la table. C'est un plus pour moi
Alwin Kesler
Fonctionne bien pour laravel 5.5
Oleg Shakhov
53

Jetez un œil à la documentation Wheres avancée pour Fluent: http://laravel.com/docs/queries#advanced-wheres

Voici un exemple de ce que vous essayez d'accomplir:

DB::table('users')
    ->whereIn('id', function($query)
    {
        $query->select(DB::raw(1))
              ->from('orders')
              ->whereRaw('orders.user_id = users.id');
    })
    ->get();

Cela produira:

select * from users where id in (
    select 1 from orders where orders.user_id = users.id
)
Drewjoh
la source
Cela se rapproche, et je suis perplexe avec des requêtes similaires depuis un certain temps maintenant. Mais where_in (laravel 3) nécessite 2 arguments, le second étant un tableau. Une idée de comment y parvenir? De plus, je ne pense pas que laravel 3 supporte la méthode from.
Marc Buurke
Ah, Laravel3 ... Ouais, ça va être difficile alors. Et je pense que dans Laravel3, vous utilisez la table()méthode au lieu du from(). Je n'ai pas eu cette situation en L3, désolé!
drewjoh
Je ne peux pas voir une méthode whereIn qui prend un lambda dans Illuminate \ Database \ Query \ Builder a-t-il été renommé whereSub?
nbranspar
20

Vous pouvez utiliser la variable en utilisant le mot-clé "use ($ category_id)"

$category_id = array('223','15');
Products::whereIn('id', function($query) use ($category_id){
   $query->select('paper_type_id')
     ->from(with(new ProductCategory)->getTable())
     ->whereIn('category_id', $category_id )
     ->where('active', 1);
})->get();
Ramesh
la source
5

Le code suivant a fonctionné pour moi:

$result=DB::table('tablename')
->whereIn('columnName',function ($query) {
                $query->select('columnName2')->from('tableName2')
                ->Where('columnCondition','=','valueRequired');

            })
->get();
Aditya Singh
la source
3

Vous pouvez utiliser Eloquent dans différentes requêtes et rendre les choses plus faciles à comprendre et à maintenir:

$productCategory = ProductCategory::whereIn('category_id', ['223', '15'])
                   ->select('product_id'); //don't need ->get() or ->first()

puis on met tout ensemble:

Products::whereIn('id', $productCategory)
          ->where('active', 1)
          ->select('id', 'name', 'img', 'safe_name', 'sku', 'productstatusid')
          ->get();//runs all queries at once

Cela générera la même requête que celle que vous avez écrite dans votre question.

Philipe
la source
2

Le script est testé dans Laravel 5.x et 6.x. La staticfermeture peut améliorer les performances dans certains cas.

Product::select(['id', 'name', 'img', 'safe_name', 'sku', 'productstatusid'])
            ->whereIn('id', static function ($query) {
                $query->select(['product_id'])
                    ->from((new ProductCategory)->getTable())
                    ->whereIn('category_id', [15, 223]);
            })
            ->where('active', 1)
            ->get();

génère le SQL

SELECT `id`, `name`, `img`, `safe_name`, `sku`, `productstatusid` FROM `products` 
WHERE `id` IN (SELECT `product_id` FROM `product_category` WHERE 
`category_id` IN (?, ?)) AND `active` = ?
Madan Sapkota
la source
1

Laravel 4.2 et au-delà, peut utiliser l'interrogation de relation d'essai: -

Products::whereHas('product_category', function($query) {
$query->whereIn('category_id', ['223', '15']);
});

public function product_category() {
return $this->hasMany('product_category', 'product_id');
}
LC Yoong
la source
0
Product::from('products as p')
->join('product_category as pc','p.id','=','pc.product_id')
->select('p.*')
->where('p.active',1)
->whereIn('pc.category_id', ['223', '15'])
->get();
panqingqiang
la source
0

en utilisant une variable

$array_IN=Dev_Table::where('id',1)->select('tabl2_id')->get();
$sel_table2=Dev_Table2::WhereIn('id',$array_IN)->get();
a3rxander
la source
-2

Veuillez essayer cet outil en ligne sql2builder

DB::table('products')
    ->whereIn('products.id',function($query) {
                            DB::table('product_category')
                            ->whereIn('category_id',['223','15'])
                            ->select('product_id');
                        })
    ->where('products.active',1)
    ->select('products.id','products.name','products.img','products.safe_name','products.sku','products.productstatusid')
    ->get();
liquide207
la source