Laravel Eloquent - distinto () e contagem () não funcionando corretamente juntos


95

Portanto, estou tentando obter o número de pids distintos em uma consulta, mas o valor retornado está errado.

Isso é o que tento fazer:

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

o que retorna o valor "2", enquanto o valor que deve retornar, deve ser "1".

Como solução alternativa, estou fazendo o seguinte:

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

o que funciona bem e retorna "1"

Existe alguma regra em que contagem e distinção não podem estar na mesma consulta? Acho a solução alternativa meio "pesada", gostaria de fazer a consulta original funcionar :(


O que você tem em sua tabela de amostra no banco de dados? E o que você deseja alcançar? Agora você provavelmente deve obter o número de valores distintos na pidcoluna, então se você tiver em sua tabela 2 registros - um com pid 1, o segundo com pid 2, a contagem deve retornar 2.
Marcin Nabiałek

você pode simplesmente substituir get por count desta maneira: $count = DB::table('tablename')->count(DB::raw('DISTINCT pid')); também pode fazer: DB::table('tablename')->distinct('pid')->count('pid');
bharat

Respostas:


123

O seguinte deve funcionar

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

2
Tive um problema semelhante e parece que simplesmente deixar de fora groupByo truque.
jeteon

8
Distinct não aceita nenhum argumento. Chamar distintos () ao construir sua consulta apenas define o booleano protegido como verdadeiro, o argumento é ignorado.
Matt McDonald

Em L5.1 e isso ainda não está funcionando. O uso count()parece desabilitar ou descartar o distinct(). Use groupBy()conforme descrito ao longo da pergunta. Edit: estou descobrindo que mesmo groupBy()está fornecendo uma count()comparação diferente de get()seguido pela contagem da matriz resultante.
Jason

@Jason Eu fiz a mesma observação que você. Veja minha resposta para uma solução.
Zoon

21
A distinct()função não aceita argumentos. Você pode alterá-lo para $ad->getcodes()->distinct()->count('pid');com o mesmo resultado.
Trevor Gehman

26

Uma resposta mais genérica que teria economizado meu tempo e, espero, outras:

Não funciona (retorna a contagem de todas as linhas):

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

O conserto:

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

17

Alguém mais encontrou esta postagem e não encontrou as outras sugestões para funcionar?

Dependendo da consulta específica, uma abordagem diferente pode ser necessária. No meu caso, eu precisava contar os resultados de um GROUP BY, por exemplo

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

ou use COUNT(DISTINCT b):

SELECT COUNT(DISTINCT b) FROM a

Depois de algumas confusões, percebi que não havia nenhuma função embutida do Laravel para nenhum deles. Portanto, a solução mais simples era usar DB::rawcom o countmétodo.

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

Lembre-se, não use groupByantes de ligar count. Você pode se inscrever groupBymais tarde, se precisar, para obter linhas.


De onde $ builder veio?
Andrew

1
@Andrew O construtor de consultas Laravel que você está usando para a consulta. Por exemplo, um objeto Eloquent$books = Book::where(...)->count(...)
Zoon

->count(DB::raw('DISTINCT b'))gere a mesma consulta SQL que->distinct()->count('b')
Trevor Gehman

5

Tive um problema semelhante e encontrei uma maneira de contorná-lo.

O problema é a maneira como o construtor de consultas do Laravel lida com os agregados. Ele pega o primeiro resultado retornado e retorna o valor 'agregado'. Isso geralmente é bom, mas quando você combina a contagem com groupBy, você retorna uma contagem por item agrupado. Portanto, o agregado da primeira linha é apenas uma contagem do primeiro grupo (portanto, algo baixo como 1 ou 2 é provável).

Então a contagem do Laravel acabou, mas eu combinei o construtor de consultas do Laravel com algum SQL bruto para obter uma contagem precisa dos meus resultados agrupados.

Para o seu exemplo, espero que o seguinte funcione (e permita que você evite get):

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

Se quiser ter certeza de que não está perdendo tempo selecionando todas as colunas, você pode evitar isso ao criar sua consulta:

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

4

Eu me deparei com o mesmo problema.

Se você instalar a barra de depuração laravel, você pode ver as consultas e frequentemente ver o problema

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

mudar para

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

Você precisa definir os valores para retornar como distintos. Se você não definir os campos selecionados, todas as colunas do banco de dados serão retornadas e todas serão exclusivas. Portanto, defina a consulta como distinta e selecione apenas as colunas que constituem o seu valor 'distinto' que você deseja adicionar mais. ->select('pid','date')para obter todos os valores únicos para um usuário em um dia


4

Você pode usar a seguinte maneira para obter os dados exclusivos de acordo com sua necessidade, como segue:

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

$count = $data->count();

Espero que isso funcione.


1

Não funcionaria?

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

Veja aqui para discussão ..


3
Esta não é uma boa solução, pois a get()chamada executará a consulta e retornará os resultados do banco de dados e, em seguida, será count()executada na Coleção.
Trevor Gehman

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

Lembre-se de que agrupar por é opcional, isso deve funcionar na maioria dos casos quando você deseja que um grupo de contagem exclua valores de seleção duplicados, o addSelect é um método de instância de querybuilder.


0

Distinct não aceita argumentos, pois adiciona DISTINCT em sua consulta sql, no entanto, você PODE definir o nome da coluna que deseja selecionar distinto com. Portanto, se você tem Flight->select('project_id')->distinct()->get()é igual a SELECT DISTINCT 'project_id' FROM flightse agora pode adicionar outros modificadores como count () ou até mesmo consultas eloquentes brutas.


0

Com base na documentação do Laravel para consultas brutas, consegui obter a contagem de um campo de seleção para trabalhar com esse código no modelo do produto.

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

Esta fachada funcionou para obter o mesmo resultado no controlador:

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

O despejo resultante para ambas as consultas foi o seguinte:

#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

Isso estava funcionando para mim, então tente isto: $ ad-> getcodes () -> distinto ('pid') -> contagem ()


Olá, bem-vindo ao SO. Ao responder a uma pergunta, forneça informações adicionais sobre o código fornecido. Contribuições como esta são bem-vindas, mas outras no futuro podem se beneficiar de uma explicação de tiro
Deepend

-3

tente isso

$ad->getcodes()->groupby('pid')->distinct()->count('pid')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.