Laravel Eloquent - відмінні () і count () не працюють належним чином разом


95

Отже, я намагаюся отримати кількість різних підів у запиті, але повернене значення неправильне.

Це те, що я намагаюся зробити:

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

що повертає значення "2", тоді як значення, яке воно повинно повертати, має бути "1".

Як обхідний шлях я роблю це:

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

що працює нормально і повертає "1"

Чи існує якесь правило, коли підрахунок і різниця не можуть бути за одним запитом? Я вважаю, що обхідний шлях "важкий", я хотів би, щоб оригінальний запит працював :(


Що у вас є у вашій зразковій таблиці в базі даних? А чого ви хочете досягти? Тепер ви, мабуть, повинні отримати кількість різних значень у pidстовпці, тому якщо у вашій таблиці є 2 записи - одна з pid 1, друга з pid 2, кількість повинна повернути 2.
Marcin Nabiałek

ви можете просто замінити get на count таким чином: $count = DB::table('tablename')->count(DB::raw('DISTINCT pid')); також можете зробити: DB::table('tablename')->distinct('pid')->count('pid');
bharat

Відповіді:


123

Наступне повинно працювати

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

2
Була подібна проблема, і, здається, просто groupByне враховуючи цю штуку.
джетеон

8
Виразний не приймає жодних аргументів. Виклик distinct () під час побудови вашого запиту просто встановлює захищений булев значення true, аргумент ігнорується.
Matt McDonald

На L5.1 і це все ще не працює. Використання, count()здається, вимикає або скидає distinct(). Використовуйте, groupBy()як описано у всьому питанні. Редагувати: я вважаю, що навіть groupBy()надає інше count()порівняно з get()наступним підрахунком отриманого масиву.
Джейсон

@ Джейсон, я зробив те саме, що й ти. Дивіться мою відповідь на рішення.
Zoon,

21
distinct()Функція не приймає ніяких аргументів. Ви можете змінити його на $ad->getcodes()->distinct()->count('pid');той самий результат.
Тревор Геман,

26

Більш загальна відповідь, яка заощадила б час і, сподіваюся, інших:

Не працює (повертає кількість усіх рядків):

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

Виправлення:

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

17

Хто-небудь ще стикався з цим повідомленням і не знайшов інших пропозицій для роботи?

Залежно від конкретного запиту може знадобитися інший підхід. У моєму випадку мені потрібно було підрахувати результати a GROUP BY, наприклад

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

або використовувати COUNT(DISTINCT b):

SELECT COUNT(DISTINCT b) FROM a

Трохи спантеличившись, я зрозумів, що жодна з них не має вбудованої функції Laravel. Тож найпростішим рішенням було використання використання DB::rawз countметодом.

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

Пам'ятайте, не використовуйте groupByперед викликом count. Ви можете подати заявку groupByпізніше, якщо це потрібно для отримання рядків.


Звідки взявся $ builder?
Ендрю

1
@Andrew Конструктор запитів Laravel, який ви використовуєте для запиту. Наприклад, красномовний об’єкт$books = Book::where(...)->count(...)
Zoon

->count(DB::raw('DISTINCT b'))генерувати той самий SQL-запит, що і->distinct()->count('b')
Тревор Геман,

5

У мене була подібна проблема, і я знайшов спосіб її обійти.

Проблема полягає в тому, як конструктор запитів Laravel обробляє агрегати. Він приймає перший повернутий результат, а потім повертає "сукупне" значення. Зазвичай це нормально, але коли ви поєднуєте count з groupBy, ви повертаєте count для згрупованого елемента. Отже, сукупність першого рядка - це лише підрахунок першої групи (тому, ймовірно, щось низьке, наприклад 1 або 2).

Отже, підрахунок Laravel закінчився, але я поєднав конструктор запитів Laravel з деяким необробленим SQL, щоб отримати точний підрахунок моїх згрупованих результатів.

Для вашого прикладу, я вважаю, що має працювати наступне (і дозволяти вам уникати отримання):

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

Якщо ви хочете переконатися, що не витрачаєте час на вибір усіх стовпців, ви можете цього уникнути, будуючи свій запит:

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

4

Я натрапив на ту саму проблему.

Якщо ви встановите панель налагодження laravel, ви зможете побачити запити та часто побачити проблему

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

перейти

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

Вам потрібно встановити значення, які повертатимуться як різні. Якщо ви не встановите вибрані поля, він поверне всі стовпці бази даних, і всі будуть унікальними. Тож встановіть запит на різний і виберіть лише ті стовпці, які складають ваше «окреме» значення, яке ви можете додати більше. ->select('pid','date')щоб отримати всі унікальні значення для користувача за день


4

Ви можете використовувати наступний спосіб отримати унікальні дані відповідно до ваших потреб, як показано нижче,

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

$count = $data->count();

Сподіваюся, це спрацює.


1

Чи не спрацювало б це?

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

Дивіться тут для обговорення ..


3
Це не є гарним рішенням, оскільки get()виклик виконує запит і повертає результати з бази даних, а потім count()запускає колекцію.
Тревор Геман,

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

Пам’ятайте, що група by є необов’язковою, це має працювати в більшості випадків, коли ви хочете, щоб група підрахунків виключала повторювані значення вибору, addSelect - це метод екземпляра querybuilder.


0

Виразний не приймайте аргументи, оскільки він додає DISTINCT у ваш запит sql, однак, МОЖЕ вам знадобитися визначити ім'я стовпця, з яким ви хочете виділити окремі. Таким чином, якщо у вас Flight->select('project_id')->distinct()->get()є еквівалент, SELECT DISTINCT 'project_id' FROM flightsі тепер ви можете додати інші модифікатори, такі як count () або навіть необроблені красномовні запити.


0

На основі документів Laravel для необроблених запитів я зміг отримати підрахунок для вибраного поля для роботи з цим кодом у моделі товару.

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

Цей фасад працював, щоб отримати той самий результат у контролері:

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

Отриманий дамп для обох запитів був таким:

#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

Це працювало для мене, тому спробуйте це: $ ad-> getcodes () -> distinct ('pid') -> count ()


Привіт, ласкаво просимо до SO. Відповідаючи на запитання, будь ласка, надайте додаткову інформацію про код, який ви надаєте.
Подібні

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.