Laravel Eloquent: distinti () e count () non funzionano correttamente insieme


95

Quindi sto cercando di ottenere il numero di pid distinti su una query, ma il valore restituito è sbagliato.

Questo è quello che cerco di fare:

$ad->getcodes()->groupby('pid')->distinct()->count()

ciò che restituisce il valore "2", mentre il valore che dovrebbe restituire, dovrebbe essere "1".

Come soluzione alternativa, sto facendo questo:

count($ad->getcodes()->groupby('pid')->distinct()->get())

ciò che funziona bene e restituisce "1"

Esiste una regola in cui il conteggio e la distinzione non possono essere sulla stessa query? Trovo che la soluzione alternativa sia "pesante", vorrei far funzionare la query originale :(


Cosa hai nella tua tabella di esempio nel database? E cosa vuoi ottenere? Ora dovresti probabilmente ottenere il numero di valori distinti nella pidcolonna, quindi se hai nella tabella 2 record - uno con pid 1, il secondo con pid 2, il conteggio dovrebbe restituire 2.
Marcin Nabiałek

puoi semplicemente sostituire get con count in questo modo: $count = DB::table('tablename')->count(DB::raw('DISTINCT pid')); puoi anche fare: DB::table('tablename')->distinct('pid')->count('pid');
bharat

Risposte:


123

Quanto segue dovrebbe funzionare

$ad->getcodes()->distinct('pid')->count('pid');

2
Ho avuto un problema simile e sembra che solo tralasciare groupByil trucco.
jeteon

8
Distinct non accetta argomenti. La chiamata a separate () durante la creazione della query imposta semplicemente il valore booleano protetto su true, l'argomento viene ignorato.
Matt McDonald

Su L5.1 e questo ancora non funziona. L'uso count()sembra disabilitare o eliminare il file distinct(). Utilizzare groupBy()come descritto in tutta la domanda. Modifica: sto trovando che persino groupBy()fornisce un diverso count()rispetto a get()seguito dal conteggio della matrice risultante.
Jason

@ Jason ho fatto la tua stessa osservazione. Vedi la mia risposta per una soluzione.
Zoon

21
La distinct()funzione non accetta argomenti. Puoi cambiarlo in $ad->getcodes()->distinct()->count('pid');con lo stesso risultato.
Trevor Gehman

26

Una risposta più generica che mi avrebbe fatto risparmiare tempo e, si spera, altri:

Non funziona (restituisce il conteggio di tutte le righe):

DB::table('users')
            ->select('first_name')
            ->distinct()
            ->count();

La correzione:

DB::table('users')
            ->distinct()
            ->count('first_name');

17

Qualcun altro si è imbattuto in questo post e non ha trovato gli altri suggerimenti per funzionare?

A seconda della query specifica, potrebbe essere necessario un approccio diverso. Nel mio caso, avevo bisogno di contare i risultati di un GROUP BY, ad es

SELECT COUNT(*) FROM (SELECT * FROM a GROUP BY b)

oppure usa COUNT(DISTINCT b):

SELECT COUNT(DISTINCT b) FROM a

Dopo alcuni dubbi, mi sono reso conto che non esisteva alcuna funzione Laravel incorporata per nessuno di questi. Quindi la soluzione più semplice era usare l'uso DB::rawcon il countmetodo.

$count = $builder->count(DB::raw('DISTINCT b'));

Ricorda, non usare groupByprima di chiamare count. Puoi candidarti in groupByseguito, se ne hai bisogno per ottenere righe.


Da dove viene $ builder?
Andrew

1
@Andrew Il generatore di query Laravel che stai utilizzando per la query. Ad esempio, un oggetto eloquente$books = Book::where(...)->count(...)
Zoon

->count(DB::raw('DISTINCT b'))generare la stessa query SQL di->distinct()->count('b')
Trevor Gehman,

5

Ho avuto un problema simile e ho trovato un modo per aggirarlo.

Il problema è il modo in cui il generatore di query di Laravel gestisce gli aggregati. Accetta il primo risultato restituito e quindi restituisce il valore "aggregato". Di solito va bene, ma quando combini count con groupBy restituisci un conteggio per elemento raggruppato. Quindi l'aggregato della prima riga è solo un conteggio del primo gruppo (quindi è probabile qualcosa di basso come 1 o 2).

Quindi il conteggio di Laravel è finito, ma ho combinato il generatore di query Laravel con un SQL grezzo per ottenere un conteggio accurato dei miei risultati raggruppati.

Per il tuo esempio, mi aspetto che quanto segue dovrebbe funzionare (e ti consenta di evitare il get):

$query = $ad->getcodes()->groupby('pid')->distinct();
$count = count(\DB::select($query->toSql(), $query->getBindings()));

Se vuoi assicurarti di non perdere tempo a selezionare tutte le colonne, puoi evitarlo durante la creazione della query:

 $query = $ad->select(DB::raw(1))->getcodes()->groupby('pid')->distinct();

4

Mi sono imbattuto nello stesso problema.

Se installi la barra di debug di laravel puoi vedere le query e spesso vedere il problema

$ad->getcodes()->groupby('pid')->distinct()->count()

cambia in

$ad->getcodes()->distinct()->select('pid')->count()

È necessario impostare i valori da restituire come distinti. Se non si impostano i campi di selezione, verranno restituite tutte le colonne nel database e tutte saranno uniche. Quindi imposta la query su distinto e seleziona solo le colonne che compongono il tuo valore "distinto" che potresti voler aggiungere di più. ->select('pid','date')per ottenere tutti i valori univoci per un utente in un giorno


4

È possibile utilizzare il seguente modo per ottenere i dati univoci secondo le proprie necessità come segue,

$data = $ad->getcodes()->get()->unique('email');

$count = $data->count();

Spero che funzioni.


1

Non funzionerebbe?

$ad->getcodes()->distinct()->get(['pid'])->count();

Vedi qui per la discussione ..


3
Questa non è una buona soluzione, perché la get()chiamata eseguirà la query e restituirà i risultati dal database, quindi verrà count()eseguita sulla raccolta.
Trevor Gehman

1
$solution = $query->distinct()
            ->groupBy
            (
                [
                    'array',
                    'of',
                    'columns',
                ]
            )
            ->addSelect(
                [
                    'columns',
                    'from',
                    'the',
                    'groupby',
                ]
            )
            ->get();

Ricorda che il gruppo per è facoltativo, dovrebbe funzionare nella maggior parte dei casi quando desideri che un gruppo di conteggio escluda i valori di selezione duplicati, addSelect è un metodo di istanza di querybuilder.


0

Distinct non accetta argomenti poiché aggiunge DISTINCT nella query sql, tuttavia, POTREBBE essere necessario definire il nome della colonna con cui si desidera selezionare distinto. Quindi, se hai Flight->select('project_id')->distinct()->get()è uguale a SELECT DISTINCT 'project_id' FROM flightse ora puoi aggiungere altri modificatori come count () o anche query eloquenti grezze.


0

Sulla base dei documenti di Laravel per le query non elaborate, sono stato in grado di ottenere il conteggio per un campo selezionato per lavorare con questo codice nel modello di prodotto.

public function scopeShowProductCount($query)
{
    $query->select(DB::raw('DISTINCT pid, COUNT(*) AS count_pid'))
          ->groupBy('pid')
          ->orderBy('count_pid', 'desc');
}

Questa facciata ha funzionato per ottenere lo stesso risultato nel controller:

$products = DB::table('products')->select(DB::raw('DISTINCT pid, COUNT(*) AS count_pid'))->groupBy('pid')->orderBy('count_pid', 'desc')->get();

Il dump risultante per entrambe le query era il seguente:

#attributes: array:2 [
  "pid" => "1271"
  "count_pid" => 19
],
#attributes: array:2 [
  "pid" => "1273"
  "count_pid" => 12
],
#attributes: array:2 [
  "pid" => "1275"
  "count_pid" => 7
]

-1

Questo funzionava per me, quindi prova questo: $ ad-> getcodes () -> separate ('pid') -> count ()


Ciao benvenuto a SO. Quando si risponde a una domanda, fornire ulteriori informazioni sul codice fornito. Contributi come questo sono i benvenuti, ma altri in futuro potrebbero beneficiare di una spiegazione del colpo
Deepend

-3

prova questo

$ad->getcodes()->groupby('pid')->distinct()->count('pid')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.