Получение записи SQL

Доброго времени суток сообщество,

Мне нужна помощь, чтобы получить запись из таблицы mysql, как показано ниже. Обратите внимание на мои целевые результаты:

Получение записи SQL

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

public function usersTopRecruits(){
    $tempUID = array();
    $mainAssocArr = array();
    for ($i=0; $i < User::count(); $i++) { 
        if ($i == 0){
            $offset = 0;
        }
        else{           
            $offset = $this->take * $i;
        }

        $users = User::take($this->take)->offset($offset)->get();

        foreach ($users as $value) {
            $refCnts = User::where('referral', $value->aff_id)->count();

            if ($refCnts > 0){
                $tempUID['userAffID'] = $value->aff_id;
                $tempUID['userrecruits'] = $refCnts;
                $mainAssocArr[] = $tempUID;
            }
        }
    }//End of For loop

    //Here, i tried to sort by highest recruits

    foreach ($mainAssocArr as $key => $row) {
        $desc[$key]  = $row['userrecruits'];
        $asc[$key] = $row['userAffID'];
    }

    array_multisort($desc, SORT_DESC, $asc, SORT_ASC, $mainAssocArr);

    return $mainAssocArr;
}

Текущий месяц:

public function userTopRecruitsCurrMonth(){
    $tempUID = array();
    $mainAssocArr = array();
    for ($i=0; $i < User::count(); $i++) { 
        if ($i == 0){
            $offset = 0;
        }
        else{           
            $offset = $this->take * $i;
        }

        $users = User::take($this->take)->offset($offset)->get();

        foreach ($users as $value) {
            $refCnts = User::where('referral', $value->aff_id)->where('signup_date', '>=', 'startDateOfCurrentMonth')->count();

            if ($refCnts > 0){
                $tempUID['userAffID'] = $value->aff_id;
                $tempUID['userRecruits'] = $refCnts;
                $mainAssocArr[] = $tempUID;
            }
        }
    }//End of For loop


    foreach ($mainAssocArr as $key => $row) {
        $volume[$key]  = $row['userRecruits'];
        $edition[$key] = $row['userAffID'];
    }

    array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $mainAssocArr);

    return $mainAssocArr;
}

Любая помощь или предложение будут оценены.

ПРИМЕЧАНИЕ. Я использую модель Eloquent, но НЕ использую «laravel».

Почему тег <sql>? Вам нужен SQL-запрос?

jarlh 10.12.2018 21:27

Да, построители запросов. Извините, я их не фанат. Лично я, вероятно, сделал бы (коррелированный) подзапрос, чтобы подсчитать итоги, а затем присоединиться к нему, чтобы выполнить заказ. Это агрегированный запрос, который должен подсчитывать всю БД, и если вы можете запечь это число и поддерживать его, это будет намного быстрее.

ArtisticPhoenix 10.12.2018 21:33

@ArtisticPhoenix спасибо за комментарий. любой пример запроса или подзапроса, который, по вашему мнению, может решить или помочь в решении проблемы?

Harrison O 10.12.2018 21:40

Да, DbFiddle, если вам нужны пользователи без рефералов, вам, возможно, придется выполнить левое присоединение вместо внутреннего (присоединиться)

ArtisticPhoenix 10.12.2018 21:56

Подзапрос есть, если вы хотите такие вещи, как имя и т. д. Поскольку группировка на referral вместо этого предоставит вам данные одного из тех, на которые ссылаются пользователи, а не фактические данные пользователей. Лучше сделать это как подзапрос, потому что он создает меньшую временную таблицу, а затем выполняет все это на том же уровне, а также выполняет сортировку по меньшей временной таблице. Вы даже можете переместить ORDER BY в подзапрос, и он ничего не изменит. Например По крайней мере, насколько я понимаю, как это оптимизирует.

ArtisticPhoenix 10.12.2018 22:04

@ArtisticPhoenix, это полезно, большое вам спасибо

Harrison O 10.12.2018 22:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
6
44
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Из вашего комментария я понимаю, что предоставление вам SQL-запросов может помочь.

Этот простой расширенный запрос вернет REFERRAL с наибольшим количеством вхождений (за все время), с наибольшим наверху.

SELECT referral, COUNT(*) 
FROM table
GROUP BY referral
ORDER BY COUNT(*) DESC

Если вы ищете такие же результаты за текущий месяц, просто добавьте предложение WHERE:

SELECT referral, COUNT(*) 
FROM table
WHERE YEAR(sigmup_date) = YEAR(NOW()) AND MONTH(sigmup_date) = MONTH(NOW()) 
GROUP BY referral
ORDER BY COUNT(*) DESC

ваш ответ выглядит великолепно, но часть текущего месяца, похоже, не работает из условия <where>

Harrison O 10.12.2018 22:18

@HarrisonOziegbe: правильно, я неправильно расставил пункты WHERE и GROUP BY. Отредактировал мой ответ, теперь он должен работать нормально.

GMB 10.12.2018 22:22

Добро пожаловать, @HarrisonOziegbe, рад, что помог!

GMB 10.12.2018 22:27

Я бы использовал такой запрос:

SELECT
    *
FROM
    users AS u0 
JOIN
(
    SELECT
        u1.REFERRAL AS agg,
        COUNT(u1.REFERRAL) AS total
    FROM 
        users AS u1
    GROUP BY
        u1.REFERRAL
    ORDER BY total DESC
) AS u2
ON
    u2.agg = u0.AFF_ID

Подзапрос позволяет вам, снова присоединившись к таблице, извлечь данные о фактических пользователях, по которым сгруппирован AFF_ID. Это даст вам такие вещи, как их FIRST_NAME и т. д. Если вы не присоединитесь снова, вы не получите этого.

Он также создает меньшую временную таблицу (в памяти), тогда, если бы вы сделали это на том же уровне (возможно, мне пришлось бы вникнуть в нее, чтобы объяснить больше).

Попробуй сам

Если вы хотите сделать это всего за один месяц, мы можем изменить подзапрос, чтобы подсчитывать только пользователей, добавленных в этом месяце:

SELECT
    *
FROM
    users AS u0 
JOIN
(
    SELECT
        u1.REFERRAL AS agg,
        COUNT(u1.REFERRAL) AS total
    FROM 
        users AS u1
    WHERE 
        YEAR(u1.sigmup_date) = YEAR(NOW())
      AND
        MONTH(u1.sigmup_date) = MONTH(NOW())
    GROUP BY
        u1.REFERRAL
    ORDER BY total DESC
) AS u2
ON
    u2.agg = u0.AFF_ID

Наконец, вам может / придется использовать ЛЕВОЕ СОЕДИНЕНИЕ, если вам нужны пользователи, которые никого не рекомендовали.

Например

А если добавить что-то вроде

WHERE
  u2.agg IS NULL

В конце внешнего запроса вы можете найти всех пользователей без рефералов.

Например

Помимо любой оптимизации, лучше (для меня) делать это как подзапрос.

И последнее, если вам не нравится NULL в целом, вы можете использовать COALESCE(), чтобы исправить это следующим образом:

SELECT
  u0.*, COALESCE(u2.total,0) AS total
FROM
  users AS u0 
LEFT JOIN
(
  SELECT
      u1.REFERRAL AS agg,
      COUNT(u1.REFERRAL) AS total
  FROM 
      users AS u1
  GROUP BY
      u1.REFERRAL
  ORDER BY total DESC
) AS u2
ON
  u2.agg = u0.AFF_ID

DBFiddle

А теперь это 0

Я считаю, что COALESCE очень полезен, и чем меньше работы придется выполнять в коде, тем легче будет. Если вы можете отформатировать данные из БД так, как вы хотите, это, как правило, лучше, чем манипулировать ими позже. Это может быть разница между использованием чего-то вроде fetchAll и необходимостью его зацикливать и изменять в PHP, прежде чем вы сможете его использовать.

Ваше здоровье!

Другие вопросы по теме