2015-02-04 18 views
7

Edit:laravel: come utilizzare le tabelle/subquery derivate nel generatore di query laravel

Anche se questa domanda in origine era specifico per la query che sto descrivendo sotto, la risposta che ho ricevuto vale per quasi tutte le questioni connesse per usare le tabelle/subquery derivate in laravel

domanda iniziale:

ultimamente sto un po 'bloccato sul generatore di query laravel. Ha alcune caratteristiche davvero carine, ma mi sembra che non sia costruito per operazioni di database più complesse.

Questa è la domanda che sto cercando di costruire:

select 

'IFNULL(counted.product_count, 0) AS product_count', 
'uncounted.value', 
'uncounted.attribute_id', 
'uncounted.attribute_option_id' 

    from ( 

     select 
     'counted.id', 
     'counted.attribute_id', 
     'counted.value', 
     'count(counted.attribute_id) AS product_count' 

     from `attribute_options` as `counted` 
     where `counted.product_id` in (?, ?, ?, ?, ?) 
     group by `counted.attribute_option_id` 

    ) as 'counted' 

right join 'attribute_options' as 'uncounted' 
     on 'counted.id' = 'uncounted.id' 

    group by 'attribute_option_id' 

Spiegazione della query: Sto costruendo una ricerca sfaccettata per il mio catalogo prodotti in laravel. I prodotti sono ristretti in base ai filtri/attributi forniti dagli utenti. Per una migliore esperienza utente, voglio mostrare la quantità di prodotti rimasti per ciascun filtro, ecco cosa fa la query precedente: contare tutti i prodotti per un determinato attributo DOVE il product_id è IN un array di ID prodotto.

La mia prova:

$productIds = [ 1, 2, 3, 4, 5 ]; 

    $subQuery = \DB::table('attribute_options')->selectRaw('counted.id, counted.attribute_id, counted.value, count(counted.attribute_id) AS product_count') 
        ->from('attribute_options AS counted') 
        ->whereIn('counted.product_id', $productIds) 
        ->groupBy('counted.attribute_option_id') 
        ->mergeBindings($subQuery); 

    $query = Model::selectRaw('IFNULL(counted.product_count, 0) AS product_count, uncounted.value, uncounted.attribute_id, uncounted.attribute_option_id') 
        ->from(\DB::raw(' (' . $subQuery->toSql() . ') AS counted ')) 
        ->rightJoin('attribute_options AS uncounted', 'counted.id', '=', 'uncounted.id') 
        ->groupBy('attribute_option_id') 
        ->get(); 

Please help me, perché non mi piace usare un DB :: grezzo() o DB :: select() dichiarazione. Ciò non avverrebbe "Laravelish" o "Eloquent".

+0

Bene, siete sicuramente andando ad avere per utilizzare almeno un DB: : istruzione raw(), per la selezione ifnull. Per il resto, ti suggerisco di postare ciò che hai già provato. Per favore non aspettarti che facciamo tutto il lavoro per te. –

+0

Caro Joel, non sto assolutamente cercando di farti fare tutto il lavoro per me! Ho provato così tante cose la scorsa settimana, ma non riesco a trovare il modo giusto per tradurre questo SQL per utilizzare il generatore di query. Sono consapevole che l'IFNULL avrebbe bisogno di un'istruzione selectRaw(). Pubblicherò ciò che ho provato. –

+0

Molto meglio, avere un upvote. :) Mi dispiace di non poterti aiutare con questa domanda, ma spero che qualcun altro possa farlo. –

risposta

16

Al primo tentativo sembra piuttosto vicino. Prova questo:

ho rimosso il riferimento namespace lunga e suggerire di aggiungere una dichiarazione use per rendere il codice più leggibile

$productIds = [ 1, 2, 3, 4, 5 ]; 

$subQuery = DB::table('attribute_options AS counted')->selectRaw('counted.id, counted.attribute_id, counted.value, count(counted.attribute_id) AS product_count') 
       ->whereIn('counted.product_id', $productIds) 
       ->groupBy('counted.attribute_option_id') 

$query = AttributeOption::selectRaw('IFNULL(counted.product_count, 0) AS product_count, uncounted.value, uncounted.attribute_id, uncounted.attribute_option_id') 
       ->from(\DB::raw(' (' . $subQuery->toSql() . ') AS counted ')) 
       ->mergeBindings($subQuery->getQuery()) 
       ->rightJoin('attribute_options AS uncounted', 'counted.id', '=', 'uncounted.id') 
       ->groupBy('attribute_option_id') 
       ->get(); 
+0

Ok, wow! questo fa il trucco, grazie mille! È possibile eseguire questo trucco in più selezioni/subquery annidati? Devo solo unire i binding prima di usare get()? –

+0

Sì, dovrebbe funzionare :) – lukasgeiter

+0

Ho notato che hai già pubblicato una [domanda simile] (http://stackoverflow.com/questions/28283483/eloquent-how-to-use-the-query-builder-for-derived- tavoli) Anche questo è risolto? Se sì, suggerirei di eliminare la domanda precedente. – lukasgeiter