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.