SQL记录检索

时间:2018-12-10 20:25:56

标签: php mysql sql optimization eloquent

晚安社区,

我需要帮助来从mysql表中检索记录,如下所示。请注意我的目标结果:

Table and result

下面是我目前的方法,该方法在行数少的情况下效果很好,但是速度非常慢,或者在成千上万甚至数百行上花费时间。

resolver: lts-9.20

extra-deps: [
repa-3.4.1.4,
]

当月:

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;
}

任何帮助或建议,将不胜感激。

注意:我使用的是Eloquent模型,但未使用“ laravel”

2 个答案:

答案 0 :(得分:2)

根据您的评论,我了解为您提供SQL查询可能会有所帮助。

此简单的综合查询将返回(所有时间)发生次数最多(最高)的REFERRAL s。

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

答案 1 :(得分:1)

我会使用这样的查询:

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之类的信息。如果您不再次加入,您将不会得到这些东西。

它还会建立一个较小的临时表(在内存中),然后如果您在同一级别上进行操作(可能,我将不得不对其进行深入解释,并进行详细说明)。

Try it yourself

如果您只想使用一个月,我们可以修改子查询以仅计算该月添加的用户:

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

最后,如果您想要未推荐任何人的用户,则可能/将不得不使用LEFT JOIN。

For Example

如果您添加

WHERE
  u2.agg IS NULL

在外部查询的末尾,您可以找到所有没有引荐的用户。

For Example

除了进行任何优化之外,(对我来说)将其作为子查询阅读起来更好。

最后一个,如果您不喜欢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甚至无法使用它进行修改之间可能是有区别的。

干杯!