检索尚未分配到工作的车辆驾驶员的数据

Cam*_*Cam 6 mysql performance subquery select query-performance

过去 24 小时都在为某事挣扎。需要一些天才来发光。我正在尝试为驱动程序显示每周工作循环/日志,它将显示:

  • 尚未分配给司机的工作
  • 已分配给司机的工作
  • 如果作业已分配给驱动程序,则显示当天可用的驱动程序
  • 如果当天没有工作,则显示所有可用驱动程序的列表

最后2点是我真正挣扎的地方。

我有以下表格:

drivers ('driver_id', 'driver_name')

vehicles ('vehicle_id', 'vehicle_make', 'vehicle_model')

jobs ('job_id', 'collection_address', 'collection_datetime', 'delivery_address', 'deliver_datetime', 'driver_id', 'vehicle_id') 
Run Code Online (Sandbox Code Playgroud)

我附上了下面的输出屏幕:

在此处输入图片说明

例如,如果您查看 23/09/2016,司机 Keith 正在工作,但 Nick 有空。但是,如果我执行子查询,它会显示两个驱动程序,这不是正确的结果。我的 SQL 语句如下,如果有人可以提供帮助,我将不胜感激。

    SELECT listofdays.job_date, j.job_id, IF( j.driver_id > 0 AND j.job_id > 0, (SELECT driver_name FROM t_drivers WHERE driver_id = j.driver_id LIMIT 1), '') as job_driver, IF( j.vehicle_id > 0, (SELECT vehicle_reg FROM t_vehicles WHERE vehicle_id = j.vehicle_id LIMIT 1), 'no') as job_vehicle, j.collection_town, j.collection_postcode, j.delivery_town, j.delivery_postcode, j.job_status
 FROM (
  SELECT '2016-09-19' + INTERVAL seq.seq DAY AS job_date
  FROM seq_0_to_999999 AS seq
  WHERE seq.seq <= TIMESTAMPDIFF(DAY , '2016-09-19', '2016-09-25' )
 ) AS listofdays
LEFT JOIN t_jobs j ON listofdays.job_date = DATE(j.collection_datetime)
ORDER BY DATE(listofdays.job_date), j.job_order ASC
Run Code Online (Sandbox Code Playgroud)

我也很高兴在速度和性能方面对上述查询进行任何改进。它将用于内部系统。

修订后的查询如下:

    SELECT
  sub.job_date,
  j.job_id,
  IFNULL(d.driver_name, '') as job_driver,
  IFNULL(v.vehicle_reg, 'no') as job_vehicle,
  j.collection_town,
  j.collection_postcode,
  j.delivery_town,
  j.delivery_postcode,
  j.job_status,
  IF(j.job_id IS NULL, sub.available_drivers, 'no availability') AS available_drivers
FROM
  (
    SELECT
      listofdays.job_date,
      GROUP_CONCAT(d.driver_name) AS available_drivers
    FROM
      (
        SELECT
          '2016-09-19' + INTERVAL seq.seq DAY AS job_date
        FROM
          seq_0_to_999999 AS seq
        WHERE
          seq.seq <= TIMESTAMPDIFF(DAY, '2016-09-19', '2016-09-25')
      ) AS listofdays
      CROSS JOIN t_drivers AS d
      LEFT JOIN t_jobs AS j ON listofdays.job_date = DATE(j.collection_datetime)
      AND d.driver_id = j.driver_id                   
GROUP BY listofdays.job_date
  ) AS sub
  LEFT JOIN t_jobs AS j ON sub.job_date = DATE(j.collection_datetime)
  LEFT JOIN t_drivers AS d ON j.driver_id = d.driver_id
  LEFT JOIN t_vehicles AS v ON j.vehicle_id = v.vehicle_id
ORDER BY
  job_date ASC,
  job_order ASC
Run Code Online (Sandbox Code Playgroud)

输出如下:

在此处输入图片说明

如果您在 23 日查看上图,则有 2 个空缺职位,其中应该有可用驱动程序的列表,但它说没有可用的驱动程序。在我们的例子中,Nick 那天没有工作,但它说没有空。

And*_*y M 3

我将从可用驱动程序列表开始。由于您似乎希望将它们作为 CSV 字符串,因此使用分组并使用 GROUP_CONCAT() 连接名称是有意义的。使用作业的外连接来计算日期和驱动程序的叉积,然后,要获取每天可用的驱动程序,仅当驱动程序名称没有匹配的作业时才对驱动程序名称进行分组连接:

\n\n
SELECT\n  listofdays.job_date,\n  GROUP_CONCAT(IF(j.job_id IS NULL, d.driver_name, NULL)) AS available_drivers\nFROM\n  (\n    SELECT\n      '2016-09-19' + INTERVAL seq.seq DAY AS job_date\n    FROM\n      seq_0_to_999999 AS seq\n    WHERE\n      seq.seq <= TIMESTAMPDIFF(DAY, '2016-09-19', '2016-09-25')\n  ) AS listofdays\n  CROSS JOIN t_drivers AS d\n  LEFT JOIN t_jobs AS j ON listofdays.job_date = DATE(j.collection_datetime)\n                     AND d.driver_id = j.driver_id\nGROUP BY\n  listofdays.job_date\n;\n
Run Code Online (Sandbox Code Playgroud)\n\n

下一步也是最后一步是使用上面的作为派生表并再次外连接到它\ t_jobsxe2\x80\x93 这次以获得作业详细信息(并且您还需要外连接t_driverst_vehicle也可以从这些表中获取详细信息):

\n\n
SELECT\n  sub.job_date,\n  j.job_id,\n  IFNULL(d.driver_name, '') as job_driver,\n  IFNULL(v.vehicle_reg, 'no') as job_vehicle,\n  j.collection_town,\n  j.collection_postcode,\n  j.delivery_town,\n  j.delivery_postcode,\n  j.job_status,\n  sub.available_drivers\nFROM\n  (\n    SELECT\n      listofdays.job_date,\n      GROUP_CONCAT(IF(j.job_id IS NULL, d.driver_name, NULL)) AS available_drivers\n    FROM\n      (\n        SELECT\n          '2016-09-19' + INTERVAL seq.seq DAY AS job_date\n        FROM\n          seq_0_to_999999 AS seq\n        WHERE\n          seq.seq <= TIMESTAMPDIFF(DAY, '2016-09-19', '2016-09-25')\n      ) AS listofdays\n      CROSS JOIN t_drivers AS d\n      LEFT JOIN t_jobs AS j ON listofdays.job_date = DATE(j.collection_datetime)\n                         AND d.driver_id = j.driver_id\n    GROUP BY\n      listofdays.job_date\n  ) AS sub\n  LEFT JOIN t_jobs AS j ON sub.job_date = DATE(j.collection_datetime)\n  LEFT JOIN t_drivers AS d ON j.driver_id = d.driver_id\n  LEFT JOIN t_vehicles AS v ON j.vehicle_id = v.vehicle_id\nORDER BY\n  job_date ASC,\n  job_order ASC\n;\n
Run Code Online (Sandbox Code Playgroud)\n