Laravel Eloquent: distintos () y count () no funcionan correctamente juntos

95

Entonces estoy tratando de obtener el número de pids distintos en una consulta, pero el valor devuelto es incorrecto.

Esto es lo que trato de hacer:

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

lo que devuelve el valor "2", mientras que el valor que debería devolver, debería ser "1".

Como solución alternativa, estoy haciendo esto:

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

lo que funciona bien y devuelve "1"

¿Existe alguna regla en la que recuento y diferenciado no puedan estar en la misma consulta? Encuentro que la solución es "pesada", me gustaría que la consulta original funcione :(

Iñigo EC
fuente
¿Qué tienes en tu tabla de muestra en la base de datos? ¿Y qué quieres lograr? Ahora probablemente debería obtener un número de valores distintos en la pidcolumna, por lo que si tiene en su tabla 2 registros, uno con pid 1, segundo con pid 2, el recuento debe devolver 2.
Marcin Nabiałek
simplemente puede reemplazar get con count de esta manera: $count = DB::table('tablename')->count(DB::raw('DISTINCT pid')); también puede hacer: DB::table('tablename')->distinct('pid')->count('pid');
bharat

Respuestas:

124

Lo siguiente debería funcionar

$ad->getcodes()->distinct('pid')->count('pid');
Suresh Bala
fuente
2
Tuve un problema similar y parece que simplemente omitir el groupByhace el truco.
jeteon
8
Distinct no acepta argumentos. Llamar a different () al construir su consulta solo establece el valor booleano protegido en verdadero, el argumento se ignora.
Matt McDonald
En L5.1 y esto todavía no funciona. El uso count()parece deshabilitar o soltar el distinct(). Úselo groupBy()como se describe a lo largo de la pregunta. Editar: descubro que even groupBy()proporciona una diferencia en count()comparación con la get()siguiente al contar la matriz resultante.
Jason
@Jason Hice la misma observación que tú. Vea mi respuesta para una solución.
Zoon
21
La distinct()función no acepta argumentos. Puede cambiarlo a $ad->getcodes()->distinct()->count('pid');con el mismo resultado.
Trevor Gehman
26

Una respuesta más genérica que me hubiera ahorrado tiempo y, con suerte, otras:

No funciona (devuelve el recuento de todas las filas):

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

La solución:

DB::table('users')
            ->distinct()
            ->count('first_name');
Andrés
fuente
17

¿Alguien más se ha encontrado con esta publicación y no encuentra las otras sugerencias que funcionen?

Dependiendo de la consulta específica, es posible que se necesite un enfoque diferente. En mi caso, necesitaba contar los resultados de un GROUP BY, por ejemplo

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

o use COUNT(DISTINCT b):

SELECT COUNT(DISTINCT b) FROM a

Después de algunas dudas, me di cuenta de que no había una función Laravel incorporada para ninguno de estos. Entonces, la solución más simple fue usar usar DB::rawcon el countmétodo.

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

Recuerde, no lo use groupByantes de llamar count. Puede solicitarlo groupBymás tarde, si lo necesita para obtener filas.

Zoon
fuente
¿De dónde vino $ builder?
Andrew
1
@Andrew El generador de consultas de Laravel que está utilizando para la consulta. Por ejemplo, un objeto Eloquent$books = Book::where(...)->count(...)
Zoon
->count(DB::raw('DISTINCT b'))generar la misma consulta SQL que->distinct()->count('b')
Trevor Gehman
5

Tuve un problema similar y encontré una manera de solucionarlo.

El problema es la forma en que el generador de consultas de Laravel maneja los agregados. Toma el primer resultado devuelto y luego devuelve el valor 'agregado'. Por lo general, esto está bien, pero cuando combina count con groupBy, devuelve un recuento por elemento agrupado. Entonces, el agregado de la primera fila es solo un recuento del primer grupo (por lo que es probable que sea algo bajo como 1 o 2).

Entonces, el recuento de Laravel está fuera, pero combiné el generador de consultas de Laravel con algo de SQL sin procesar para obtener un recuento preciso de mis resultados agrupados.

Para su ejemplo, espero que lo siguiente funcione (y le permita evitar el get):

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

Si desea asegurarse de no perder el tiempo seleccionando todas las columnas, puede evitarlo al crear su consulta:

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

Me encontré con el mismo problema.

Si instala la barra de depuración de laravel, puede ver las consultas y, a menudo, ver el problema

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

cambiar a

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

Debe establecer los valores para que se devuelvan como distintos. Si no establece los campos de selección, devolverá todas las columnas de la base de datos y todas serán únicas. Por lo tanto, establezca la consulta en distinta y solo seleccione las columnas que componen su valor 'distinto', es posible que desee agregar más. ->select('pid','date')para obtener todos los valores únicos para un usuario en un día

Brett
fuente
4

Puede utilizar la siguiente forma para obtener los datos únicos según sus necesidades de la siguiente manera,

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

$count = $data->count();

Espero que esto funcione.

Shahrukh Anwar
fuente
1

¿No funcionaría esto?

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

Vea aquí para discusión.

JonnyFoley
fuente
3
Esta no es una buena solución, porque la get()llamada ejecutará la consulta y devolverá los resultados de la base de datos, y luego se count()ejecutará en la Colección.
Trevor Gehman
1
$solution = $query->distinct()
            ->groupBy
            (
                [
                    'array',
                    'of',
                    'columns',
                ]
            )
            ->addSelect(
                [
                    'columns',
                    'from',
                    'the',
                    'groupby',
                ]
            )
            ->get();

Recuerde que el grupo por es opcional, esto debería funcionar en la mayoría de los casos cuando desea que un grupo de recuento excluya valores de selección duplicados, addSelect es un método de instancia de querybuilder.

Daniel Santos
fuente
0

Distinct no toma argumentos, ya que agrega DISTINCT en su consulta sql, sin embargo, PUEDE necesitar definir el nombre de la columna con la que desea seleccionar distinto. Por lo tanto, si tiene Flight->select('project_id')->distinct()->get()es equivalente a SELECT DISTINCT 'project_id' FROM flightsy ahora puede agregar otros modificadores como count () o incluso consultas elocuentes sin procesar.

Karl Anthony Baluyot
fuente
0

Según los documentos de Laravel para consultas sin procesar , pude obtener el recuento de un campo seleccionado para trabajar con este código en el modelo de producto.

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

Esta fachada funcionó para obtener el mismo resultado en el controlador:

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

El volcado resultante para ambas consultas fue el siguiente:

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

Esto funcionó para mí, así que intente esto: $ ad-> getcodes () -> distinto ('pid') -> count ()

Sushant Yadav
fuente
Hola, bienvenido a SO. Cuando responda una pregunta, proporcione información adicional sobre el código que proporciona. Contribuciones como esta son bienvenidas, pero otras en el futuro pueden beneficiarse de una explicación de tiro
Deepend
-3

prueba esto

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