Laravel Eloquent - разные () и count () неправильно работают вместе


99

Итак, я пытаюсь получить количество различных pid в запросе, но возвращаемое значение неверно.

Вот что я пытаюсь сделать:

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

то, что возвращает значение «2», в то время как значение, которое оно должно вернуть, должно быть «1».

В качестве обходного пути я делаю следующее:

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

что работает нормально и возвращает "1"

Есть ли какое-либо правило, по которому счетчик и отдельный не могут быть в одном запросе? Я считаю обходной путь "тяжелым", я хотел бы, чтобы исходный запрос работал :(


Что у вас есть в образце таблицы в базе данных? А чего вы хотите добиться? Теперь вы, вероятно, должны получить количество различных значений в pidстолбце, поэтому, если у вас есть в вашей таблице 2 записи - одна с pid 1, вторая с pid 2, счетчик должен вернуть 2.
— Марчин Набялек

вы можете просто заменить get на count следующим образом: $count = DB::table('tablename')->count(DB::raw('DISTINCT pid')); также можете: DB::table('tablename')->distinct('pid')->count('pid');
— bharat

Ответы:


128

Следующее должно работать

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

2
Была аналогичная проблема, и кажется, что просто игнорирование groupByделает трюк.
— jeteon

8
Distinct не принимает никаких аргументов. Вызов own () при построении запроса просто устанавливает для параметра protected boolean значение true, аргумент игнорируется.
— Мэтт Макдональд

На L5.1 это все еще не работает. Использование count()кажется , чтобы отключить или опускать distinct(). Используйте, groupBy()как описано в вопросе. Изменить: я нахожу, что даже groupBy()предоставляет другое count()по сравнению с get()последующим подсчетом полученного массива.
— Джейсон

@ Джейсон Я сделал то же наблюдение, что и вы. См. Мой ответ для решения.
— Zoon

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

26

Более общий ответ, который сэкономил бы мне время и, надеюсь, другим:

Не работает (возвращает количество всех строк):

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

Исправление:

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

17

Кто-нибудь еще сталкивался с этим сообщением и не находил других предложений по работе?

В зависимости от конкретного запроса может потребоваться другой подход. В моем случае мне нужно было либо подсчитать результаты 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(...)
— Зун

->count(DB::raw('DISTINCT b'))генерировать тот же SQL-запрос, что и->distinct()->count('b')
— Тревор Геман,

5

У меня была аналогичная проблема, и я нашел способ ее обойти.

Проблема в том, как построитель запросов Laravel обрабатывает агрегаты. Он берет первый возвращенный результат, а затем возвращает «агрегированное» значение. Обычно это нормально, но когда вы комбинируете count с groupBy, вы возвращаете количество для сгруппированного элемента. Таким образом, совокупность первой строки - это просто количество первой группы (поэтому вероятно что-то низкое, например, 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()в коллекции.
— Trevor

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

Помните, что group by является необязательным, это должно работать в большинстве случаев, когда вы хотите, чтобы группа count by исключила повторяющиеся значения выбора, addSelect - это метод экземпляра querybuilder.


0

Distinct не принимает аргументы, поскольку он добавляет 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
]

-2

Это сработало для меня, поэтому попробуйте это: $ ad-> getcodes () -> independent ('pid') -> count ()


Привет, добро пожаловать в SO. Отвечая на вопрос, укажите дополнительную информацию о предоставленном вами коде.
— Подобные

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.