Laravel 运行 不禁用 mysql 严格模式的复杂查询

Laravel run complex query without disabling mysql strict mode

我有一个相当复杂的查询,例如:

SELECT 
  COALESCE (
    SUM (
      CASE WHEN `closed_job_reports`.`job_report_id` IS NOT NULL THEN 1 ELSE 0 END
    ), 
    0
  ) AS `CLOSED`, 
  COALESCE (
    SUM (
      CASE WHEN `job_reports`.`id` IS NULL 
      AND `jobs`.`deadline` <= CURRENT_TIMESTAMP() THEN 1 ELSE 0 END
    ), 
    0
  ) AS `OVERDUE`, 
  COALESCE (
    SUM (
      CASE WHEN (
        `assigned_jobs`.`assigned_job_id` IS NULL 
        AND `pending_jobs`.`id` IS NOT NULL 
        AND `jobs`.`deadline` > NOW ()
      ) 
      OR (
        `assigned_jobs`.`assigned_job_id` IS NOT NULL 
        AND `jobs`.`deadline` > NOW () 
        AND `job_reports`.`id` IS NULL
      ) THEN 1 ELSE 0 END
    ), 
    0
  ) AS `PENDING`, 
  COALESCE (
    SUM (
      CASE WHEN `closed_job_reports`.`job_report_id` IS NULL 
      AND `job_reports`.`id` IS NOT NULL THEN 1 ELSE 0 END
    ), 
    0
  ) AS `AWAITING_CLOSURE`, 
  COALESCE (
    SUM (
      CASE WHEN (
        `job_reports`.`id` IS NULL 
        OR `assigned_jobs`.`assigned_job_id` IS NULL
      ) 
      AND (
        `jobs`.`deadline` > NOW ()
      ) THEN 1 ELSE 0 END
    ), 
    0
  ) AS `OPEN`, 
  COALESCE (
    COUNT (*), 
    0
  ) AS `TOTAL`, 
  COALESCE (
    SUM (
      `job_reports`.`distance_travelled`
    ), 
    0
  ) AS `distance_travelled`, 
  COALESCE (
    ROUND(
      SUM (
        CASE WHEN (
          `job_reports`.`id` IS NOT NULL 
          AND `jobs`.`job_category_id` = 2
        ) THEN ABS (
          TIMESTAMPDIFF (
            SECOND, `job_reports`.`end_time`, 
            `job_reports`.`start_time`
          )
        ) ELSE 0 END
      ) / 3600, 
      2
    ), 
    0
  ) AS `hours_worked`, 
  COALESCE (
    COUNT (`job_reports`.`id`), 
    0
  ) AS `num_reported_sites`, 
  COALESCE (
    SUM (
      CASE WHEN `jobs`.`job_category_id` = 2 
      AND `job_reports`.`id` IS NOT NULL THEN 1 ELSE 0 END
    ), 
    0
  ) AS `pm_num_reported_jobs`, 
  COALESCE (
    SUM (
      CASE WHEN `jobs`.`job_category_id` = 2 THEN 1 ELSE 0 END
    ), 
    0
  ) AS `pm_num_jobs` 
FROM 
  `jobs` 
  INNER JOIN `job_categories` ON `job_categories`.`id` = `jobs`.`job_category_id` 
  LEFT OUTER JOIN `assigned_jobs` ON `jobs`.`id` = `assigned_jobs`.`job_id` 
  LEFT OUTER JOIN `job_reports` ON `assigned_jobs`.`assigned_job_id` = `job_reports`.`assigned_job_id` 
  LEFT OUTER JOIN `closed_job_reports` ON `job_reports`.`id` = `closed_job_reports`.`job_report_id` 
  LEFT OUTER JOIN `pending_jobs` ON `jobs`.`id` = `pending_jobs`.`new_job_id` 
WHERE
  `jobs`.`date_added` BETWEEN '2022-01-01' AND '2022-02-17' 
-- GROUP BY
--   `closed_job_reports`.`job_report_id`, `job_reports`.`id`, `assigned_jobs`.`assigned_job_id`, `pending_jobs`.`id`,  `closed_job_reports`.`job_report_id`, `job_reports`.`id`, `assigned_jobs`.`assigned_job_id`
ORDER BY 
  `jobs`.`id` DESC

我可以很容易地从 PhpMyAdmin 运行 它得到我想要的,如下所示:

但是当使用 DB::select 方法从 laravel 宁 运行 时,我得到一个语法错误:

SQLSTATE[42000]: Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause (SQL: SELECT
...

我有很多这样的疑问,我会 运行宁。我检查了这个 post: Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)

但我的似乎有点复杂,因为我必须从几个相关表中进行查询。我看到其他人建议禁用mysql严格模式,但我不想那样做。

我知道你们中的一些人可能遇到过复杂查询的这个问题。请问您在解决其中一些问题时使用了哪些步骤或技术?谢谢。

好的。所以你有一个像我一样非常复杂的查询?好吧,我发现我不需要数据库中的视图,因为在我的情况下它是不必要的。

首先,我必须将查询分解为更小的部分,一次一个。这是在我被指向 Laravel 文档 https://laravel.com/docs/9.x/queries#raw-expressions

之后

我从原始查询的主要 table - 工作开始,然后继续将联接添加到查询中。

数据分组是最复杂的部分。那就是我遇到的问题。因此,在分解查询之后,我不得不更改我用于原始数据分组的内容。将数据分组到工作类别名称(或工作类别 ID)中使其更简单。

最后,我得到的显示结果看起来好多了。

这里用一段代码来说明。 我对原始查询进行了一些修改,但仍保留我需要的连接

$users = DB::table('jobs')
                    ->select(DB::raw(
                        
                        'job_categories.category_name, COUNT(jobs.id) as jobs_count, COUNT(assigned_jobs.assigned_job_id) AS assigned_jobs_count, 

                        COUNT(recurring_jobs.job_id) AS recurring_jobs_count,

                        COALESCE(SUM(
                            CASE WHEN 
                            assigned_jobs.assigned_job_id IS NULL 
                            THEN 1 ELSE 0
                            END
                        ), 0) AS unassigned_jobs_count,

                        COUNT(job_reports.id) AS reported_jobs_count,

                        COALESCE(SUM(
                            CASE WHEN job_reports.id IS NULL
                            THEN 1 ELSE 0
                            END
                        ), 0) AS unreported_jobs_count,
                        
                        COALESCE(SUM(
                            CASE WHEN closed_job_reports.job_report_id IS NOT NULL THEN 1 ELSE 0
                            END
                        ), 0) AS closed_jobs_count,

                        COALESCE(SUM(
                            CASE WHEN job_reports.id IS NOT NULL AND closed_job_reports.job_report_id IS NULL THEN 1 ELSE 0 
                            END
                        ), 0) AS reported_unclosed_jobs_count,

                        COALESCE(SUM(
                            CASE WHEN 
                                (job_reports.id IS NULL AND jobs.deadline > NOW() AND assigned_jobs.assigned_job_id IS NULL)
                            THEN 1 ELSE 0
                            END
                        ), 0) AS opened_only_jobs_count,

                        COALESCE(SUM(
                            CASE WHEN 
                                job_reports.id IS NULL AND jobs.deadline > NOW() AND assigned_jobs.assigned_job_id IS NOT NULL OR 

                                (job_reports.id IS NULL AND jobs.deadline > NOW() AND pending_jobs.id IS NOT NULL)

                            THEN 1 ELSE 0
                            END
                        ),0) AS pending_jobs_count,
                        
                        COALESCE(SUM(
                            CASE WHEN job_reports.id IS NULL AND jobs.deadline <= NOW() THEN 1 ELSE 0
                            END
                        ), 0) AS overdue_jobs_count
                        
                        '                    
                    ))
                    ->groupBy('job_categories.category_name')
                    ->join('job_categories', 'job_categories.id', '=', 'jobs.job_category_id')
                    ->leftJoin('assigned_jobs', 'jobs.id', '=', 'assigned_jobs.job_id')
                    ->leftJoin('pending_jobs', 'jobs.id', '=', 'pending_jobs.new_job_id')
                    ->leftJoin('job_reports', 'job_reports.assigned_job_id', '=', 'assigned_jobs.assigned_job_id')
                    ->leftJoin('closed_job_reports', 'closed_job_reports.job_report_id', '=', 'job_reports.id')
                    ->leftJoin('recurring_jobs', 'recurring_jobs.job_id', '=', 'jobs.id')
                    ->get();

我希望这可以帮助人们解决他们的错误问题

SQLSTATE[42000]:语法错误或访问冲突:1140 如果没有 GROUP BY,则混合使用没有 GROUP 列的 GROUP 列(MIN()、MAX()、COUNT(),...)是非法的子句

当使用 laravel 或其他类似框架时...