douchuoliu4422 2018-05-17 15:20
浏览 651
已采纳

获取groupBy中的最后一项

I have found a few answers on here which I have followed, found it working locally so I pushed up to our test-box where I'm finding this specific DB queries lasts over 1300 seconds by going in to mysql and SHOW PROCESSLIST; and it's hanging on copying to tmp table

It's Laravel 4.2, pretty old legacy code which I'm just trying to stabalise whilst working on a later version. This code below repeats roughly every 30 seconds as per the api_call, which is all well and good except it's not finishing and receiving a 504 Gateway Time-out I feel like I'm doing something recursive or would scouring a really large database be an issue here?

All I’m trying to do is run a groupBy but instead of grouping by the first one I want to group by the last one, just in case of other details being updated.

Any help provided would be highly appreciated.

public function api_prevnames()
{
    if (Auth::user()->repeat_vistor == 'Y') {
        $names = DB::table('visitors')
            ->select(DB::raw('first_name,last_name,email,car_reg,OPTIN,vistor_company'))
            ->where('user_id', Auth::user()->id)
            ->where('hidden', 0)
            ->where('email', '<>', '')
            ->whereRaw('id IN (select MAX(id) FROM visitors GROUP BY first_name, last_name, email)')
            ->get();
    }

    return JSONResponseGenerator::successResponse($names->toArray());

}

Which generates this query

select first_name,last_name,email,car_reg,OPTIN,vistor_company from `visitors` where `user_id` = '439' and `hidden` = '0' and `email` <> '' and id IN (select MAX(id) FROM visitors GROUP BY first_name, last_name, email)

The previous code runs in just under a couple seconds which I've added below:

            $names = DB::table('visitors')
            ->select(DB::raw('first_name,last_name,email,car_reg,OPTIN,vistor_company'))
            ->where('user_id', Auth::user()->id)
            ->where('hidden', 0)
            ->where('email', '<>', '')
            ->groupBy('first_name', 'last_name', 'email')
            ->get();
  • 写回答

1条回答 默认 最新

  • dongqiu3254 2018-05-17 15:59
    关注

    You can try to run the following:

    SELECT
        first_name,
        last_name,
        email,
        car_reg,
        OPTIN,
        vistor_company
    FROM (
        SELECT
            MAX(id) AS id
        FROM `visitors`
        WHERE
            `user_id` = 439
            AND `hidden` = 0
            AND `email` <> ''
        GROUP BY
            first_name,
            last_name,
            email
    ) AS subQ
    NATURAL JOIN `visitors`;
    

    Joins usually are faster than the other way around but I don't think it will help because you apparently are not grouping by indexes. To do that you would have to change the structure and I highly recommend doing so. Try to reduce the maximum length of first_name, last_name and email, so you can create a combined index of these three. If you can change the database structure itself without killing half your system, you should consider to normalize this table like having a table with visitors and another one with visits of those visitors (relation with foreign keys), so you can group by a key instead of grouping by three unindexed strings with a big length.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)
  • ¥20 matlab yalmip kkt 双层优化问题
  • ¥15 如何在3D高斯飞溅的渲染的场景中获得一个可控的旋转物体
  • ¥88 实在没有想法,需要个思路
  • ¥15 MATLAB报错输入参数太多
  • ¥15 python中合并修改日期相同的CSV文件并按照修改日期的名字命名文件
  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入