【问题标题】:Convert Raw SQL 'NOT' IN (too slow) to Laravel Eloquent将原始 SQL 'NOT' IN (太慢) 转换为 Laravel Eloquent
【发布时间】:2019-05-06 00:36:07
【问题描述】:

我在 Laravel 5.3 控制器中有一个使用 Raw SQL 的运行脚本,我发现它速度慢且不安全(作为 Raw )。是否有任何方法可以使其更高效并将其转换为 eloquent 或 Laravel 的查询生成器?

代码如下,谢谢!

SELECT  machine_code, machine_name
FROM    factory_equipment
WHERE  machine_code  NOT IN
    (
        SELECT  distinct(machine_code)
        FROM    echecklist_data
        WHERE   DATE_FORMAT(date, '%Y-%m-%d') = CURDATE() 
    )
  AND type='production' ORDER BY machine_code ASC

【问题讨论】:

    标签: php mysql sql laravel eloquent


    【解决方案1】:

    您可以使用 SQL 提高效率。我会推荐NOT EXISTS

    SELECT fe.machine_code, fe.machine_name
    FROM factory_equipment fe
    WHERE NOT EXISTS (SELECT 1
                      FROM echecklist_data ed
                      WHERE ed.machine_code = fe.machine_code AND
                            ed.date >= CURDATE() AND
                            ed.date < CURDATE() + INTERVAL 1 DAY
                     ) AND
         fe.type = 'production'
    ORDER BY fe.machine_code ASC;
    

    我会进一步推荐以下索引:factory_equipment(type, machine_code, machine_name)echecklist_data(machine_code, date)

    【讨论】:

    • 谢谢!有什么方法可以将它转换为我不擅长的 laravel eloquent 吗?
    • @Wahsei 。 . .我也不是。
    【解决方案2】:

    您可以通过将其变为LEFT JOIN 并仅选择echecklist_data 表中不匹配的行来加快此查询:

    SELECT    fe.machine_code, fe.machine_name
    FROM      factory_equipment fe
    LEFT JOIN echecklist_data ed ON ed.machine_code = fe.machine_code AND DATE_FORMAT(ed.date, '%Y-%m-%d') = CURDATE()
    WHERE     fe.type='production' AND ed.machine_code IS NULL
    ORDER BY  fe.machine_code ASC
    

    请注意,如果您的date 列是DATETIME 类型,那么使用DATE(ed.date) = CURDATE() 也将比DATE_FORMAT(ed.date, '%Y-%m-%d') = CURDATE() 更有效。

    【讨论】:

    • 谢谢!稍后我将比较这两个查询。有什么方法可以将它转换为我不擅长的 laravel eloquent 吗?
    • 恐怕我也不擅长那个......但它在雄辩中不太可能比作为原始查询更有效率。
    • @Wahsei 您还应该注意 GordonLinoff 关于使用索引的说法。而且他检查日期的代码可能比使用DATE(date)
    【解决方案3】:

    我设法使用 laravel 的查询让它工作。希望对其他人有所帮助

    DB::table('factory_equipment')
            ->select('factory_equipment.machine_code', 'factory_equipment.machine_name')
            ->leftjoin('echecklist_data', function ($leftjoin) {
                $leftjoin->on('factory_equipment.machine_code', '=', 'echecklist_data.machine_code')
                ->Where( DB::raw("DATE_FORMAT(echecklist_data.date, '%Y-%m-%d')"), DB::raw("CURDATE()") );
                })
            ->where('factory_equipment.type' , '=', 'production') 
            ->whereNull('echecklist_data.machine_code')         
            ->get();
    

    【讨论】:

    • 我很高兴看到你解决了;抱歉,我无法提供原始 SQL 之外的帮助。你应该接受你自己的答案。
    猜你喜欢
    • 2019-05-31
    • 2019-04-04
    • 2019-04-29
    • 2021-09-11
    • 2016-04-27
    • 2018-10-11
    • 2019-04-24
    • 2021-09-13
    • 1970-01-01
    相关资源
    最近更新 更多