Laravel Eloquent - odrębne () i count () nie działają poprawnie razem

102

Więc próbuję uzyskać liczbę różnych pidów w zapytaniu, ale zwrócona wartość jest nieprawidłowa.

Oto, co staram się zrobić:

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

co zwraca wartość „2”, podczas gdy wartością, którą powinien zwrócić, powinno być „1”.

Aby obejść ten problem, robię to:

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

co działa dobrze i zwraca „1”

Czy jest jakaś reguła, w której liczba i odrębne nie mogą znajdować się w tym samym zapytaniu? Uważam, że obejście jest „ciężkie”, chciałbym, aby oryginalne zapytanie działało :(

Inigo EC
źródło
Co masz w swojej przykładowej tabeli w bazie danych? A co chcesz osiągnąć? Teraz powinieneś dostać liczbę różnych wartości w pidkolumnie, więc jeśli masz w tabeli 2 rekordy - jeden z PID 1, drugi z PID 2, liczba powinna powrócić 2.
Marcin Nabiałek
możesz po prostu zamienić get na count w ten sposób: $count = DB::table('tablename')->count(DB::raw('DISTINCT pid')); możesz też zrobić: DB::table('tablename')->distinct('pid')->count('pid');
bharat

Odpowiedzi:

131

Poniższe powinny działać

$ad->getcodes()->distinct('pid')->count('pid');
Suresh Bala
źródło
2
Miałem podobny problem i wydaje się, że po prostu pominięcie załatwia sprawę groupBy.
jeteon
8
Distinct nie przyjmuje żadnych argumentów. Wywołanie różnicy () podczas budowania zapytania po prostu ustawia chronioną wartość logiczną na wartość true, argument jest ignorowany.
Matt McDonald,
Na L5.1 i to nadal nie działa. Używanie count()wydaje się wyłączać lub upuszczać distinct(). Używaj groupBy()zgodnie z opisem w całym pytaniu. Edycja: stwierdzam, że nawet groupBy()zapewnia inny w count()porównaniu do, get()a następnie zliczanie wynikowej tablicy.
Jason
@Jason Zrobiłem taką samą obserwację jak ty. Zobacz moją odpowiedź na rozwiązanie.
Zoon
21
distinct()Funkcja przyjmuje żadnych argumentów. Możesz go zmienić na $ad->getcodes()->distinct()->count('pid');z tym samym wynikiem.
Trevor Gehman
26

Bardziej ogólna odpowiedź, która zaoszczędziłaby mi czas i, miejmy nadzieję, innych:

Nie działa (zwraca liczbę wszystkich wierszy):

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

Poprawka:

DB::table('users')
            ->distinct()
            ->count('first_name');
Andrzej
źródło
17

Czy ktoś jeszcze natknął się na ten post i nie znalazł innych sugestii do pracy?

W zależności od konkretnego zapytania może być potrzebne inne podejście. W moim przypadku potrzebowałem albo policzyć wyniki GROUP BYnp

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

lub użyj COUNT(DISTINCT b):

SELECT COUNT(DISTINCT b) FROM a

Po chwili zastanowienia zdałem sobie sprawę, że nie ma wbudowanej funkcji Laravel dla żadnego z nich. Więc najprostszym rozwiązaniem było użycie DB::rawz countmetodą.

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

Pamiętaj, nie używaj groupByprzed telefonem count. Możesz złożyć wniosek groupBypóźniej, jeśli potrzebujesz go do uzyskania rzędów.

Zoon
źródło
Skąd się wziął $ builder?
Andrew
1
@Andrew Kreator zapytań Laravel, którego używasz do zapytania. Na przykład elokwentny obiekt$books = Book::where(...)->count(...)
Zoon
->count(DB::raw('DISTINCT b'))generuje to samo zapytanie SQL co->distinct()->count('b')
Trevor Gehman
5

Miałem podobny problem i znalazłem sposób, aby go obejść.

Problem polega na sposobie, w jaki kreator zapytań Laravel obsługuje agregacje. Pobiera pierwszy zwrócony wynik, a następnie zwraca wartość „zagregowaną”. Zwykle jest to w porządku, ale gdy łączysz count z groupBy, zwracasz liczbę na zgrupowany element. Tak więc agregat w pierwszym wierszu to po prostu liczba z pierwszej grupy (więc prawdopodobnie coś niskiego, na przykład 1 lub 2).

Tak więc liczba Laravel się skończyła, ale połączyłem narzędzie do tworzenia zapytań Laravel z surowym kodem SQL, aby uzyskać dokładną liczbę zgrupowanych wyników.

Na przykład, spodziewam się, że zadziała (i pozwoli ci uniknąć get):

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

Jeśli chcesz mieć pewność, że nie marnujesz czasu na wybieranie wszystkich kolumn, możesz tego uniknąć podczas tworzenia zapytania:

 $query = $ad->select(DB::raw(1))->getcodes()->groupby('pid')->distinct();
Matt McDonald
źródło
4

Natknąłem się na ten sam problem.

Jeśli zainstalujesz pasek debugowania laravel, możesz zobaczyć zapytania i często zobaczyć problem

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

zmień na

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

Musisz ustawić wartości, które mają być zwracane jako odrębne. Jeśli nie ustawisz wybranych pól, zwróci to wszystkie kolumny w bazie danych i wszystkie będą unikalne. Dlatego ustaw zapytanie na odrębne i wybierz tylko kolumny, które składają się na twoją „odrębną” wartość, którą możesz chcieć dodać więcej. ->select('pid','date')aby uzyskać wszystkie unikalne wartości dla użytkownika w ciągu jednego dnia

Brett
źródło
4

Możesz użyć następującego sposobu, aby uzyskać unikalne dane zgodnie ze swoimi potrzebami w następujący sposób:

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

$count = $data->count();

Mam nadzieję, że to zadziała.

Shahrukh Anwar
źródło
1

Czy to nie zadziała?

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

Zobacz tutaj do dyskusji ..

JonnyFoley
źródło
3
Nie jest to dobre rozwiązanie, ponieważ get()wywołanie wykona zapytanie i zwróci wyniki z bazy danych, a następnie count()uruchomi się na Collection.
Trevor Gehman
1
$solution = $query->distinct()
            ->groupBy
            (
                [
                    'array',
                    'of',
                    'columns',
                ]
            )
            ->addSelect(
                [
                    'columns',
                    'from',
                    'the',
                    'groupby',
                ]
            )
            ->get();

Pamiętaj, że grupowanie według jest opcjonalne, powinno to działać w większości przypadków, gdy chcesz, aby grupa zliczania według wykluczała zduplikowane wybrane wartości, addSelect jest metodą instancji programu budującego zapytania.

Daniel Santos
źródło
0

Distinct nie przyjmuje argumentów, ponieważ dodaje DISTINCT w zapytaniu sql, jednak MOŻE być konieczne zdefiniowanie nazwy kolumny, którą chcesz wybrać jako odrębną. Tak więc, jeśli masz Flight->select('project_id')->distinct()->get()jest równe SELECT DISTINCT 'project_id' FROM flightsi możesz teraz dodać inne modyfikatory, takie jak count () lub nawet surowe zapytania elokwentne.

Karl Anthony Baluyot
źródło
0

Na podstawie dokumentacji Laravel dla surowych zapytań udało mi się uzyskać liczbę dla wybranego pola do pracy z tym kodem w modelu produktu.

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

Ta fasada działała, aby uzyskać ten sam wynik w kontrolerze:

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

Wynikowy zrzut dla obu zapytań był następujący:

#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
źródło
-2

To działało dla mnie, więc spróbuj tego: $ ad-> getcodes () -> wyraźny ('pid') -> count ()

Sushant Yadav
źródło
Witam w SO. Odpowiadając na pytanie prosimy o podanie dodatkowych informacji o podanym kodzie. Takie wkłady są mile widziane, ale inni mogą w przyszłości skorzystać z wyjaśnienia dotyczącego strzału
Deepend
-3

Spróbuj tego

$ad->getcodes()->groupby('pid')->distinct()->count('pid')
xiaoxiao
źródło