按比例正确计算休假时间-mysql

按比例正确计算休假时间-mysql,mysql,sql,datetime,sum,Mysql,Sql,Datetime,Sum,在mysql数据库中,我创建了“leave”表: “工人”表: “订单”表: “订单状态”表(很抱歉,这不符合顺序): 我所做的: 我可以计算其他工人的“订单时间”。我已经正确地从其他工人那里选择了工人(LNAME、FNAME)订单(描述订单和编号订单)和订单上的“总时间”。我在下面编写了mysql命令: SELECT workers.FNAME, workers.LNAME, order_statusAgg.NUMBER_ORDER, order_statusAgg.DESC_ORDER,

在mysql数据库中,我创建了“leave”表:

“工人”表:

“订单”表:

“订单状态”表(很抱歉,这不符合顺序):

我所做的:

我可以计算其他工人的“订单时间”。我已经正确地从其他工人那里选择了工人(LNAME、FNAME)订单(描述订单和编号订单)和订单上的“总时间”。我在下面编写了mysql命令:

SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME'
FROM workers
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;
SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME', 
IFNULL(SEC_TO_TIME(SUM(leaveAgg.ltime)),'00:00:00') AS 'LEAVE TIME'
FROM workers
LEFT JOIN (SELECT leave.ID_WORKER, SUM((datediff(leave.BEGIN_DATE, leave.END_DATE) + 1) * (time_to_sec(time(leave.END_DATE)) - time_to_sec(time(leave.BEGIN_DATE)))) AS ltime FROM leave
LEFT JOIN
(SELECT ID_WORKER, MIN(BEGIN_DATE) AS 'MIN_BEGIN_DATE', MAX(END_DATE) AS 'MAX_END_DATE' 
FROM order_status GROUP BY ID_WORKER) ordstat ON 
leave.ID_WORKER = ordstat.ID_WORKER 
WHERE leave.END_DATE <= MAX_END_DATE AND leave.BEGIN_DATE >= MIN_BEGIN_DATE GROUP BY leave.ID_WORKER) leaveAgg
ON leaveAgg.ID_WORKER = workers.ID_WORKER
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;
然后我得到:

+---------+---------+---------------+------------+------------+
|  FNAME  | LNAME   |  NUMBER_ORDER | DESC_ORDER | ORDER TIME | 
+---------+---------+---------------+------------+------------+
|  DAVID  |  BUCS   | TEST          | TEST       | 22:30:21   |
+---------+---------+---------------+------------+------------+
|  JACK   |  FAR    | TEST          | TEST       | 21:19:18   |
+---------+---------+---------------+------------+------------+
我分析了两天(2019年3月20日和2019年3月21日)。照片如下:

SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME'
FROM workers
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;
SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME', 
IFNULL(SEC_TO_TIME(SUM(leaveAgg.ltime)),'00:00:00') AS 'LEAVE TIME'
FROM workers
LEFT JOIN (SELECT leave.ID_WORKER, SUM((datediff(leave.BEGIN_DATE, leave.END_DATE) + 1) * (time_to_sec(time(leave.END_DATE)) - time_to_sec(time(leave.BEGIN_DATE)))) AS ltime FROM leave
LEFT JOIN
(SELECT ID_WORKER, MIN(BEGIN_DATE) AS 'MIN_BEGIN_DATE', MAX(END_DATE) AS 'MAX_END_DATE' 
FROM order_status GROUP BY ID_WORKER) ordstat ON 
leave.ID_WORKER = ordstat.ID_WORKER 
WHERE leave.END_DATE <= MAX_END_DATE AND leave.BEGIN_DATE >= MIN_BEGIN_DATE GROUP BY leave.ID_WORKER) leaveAgg
ON leaveAgg.ID_WORKER = workers.ID_WORKER
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;

现在,我需要一个mysql查询,它可以根据下面描述的模式正确地、成比例地计算出离开时间:

SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME'
FROM workers
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;
SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME', 
IFNULL(SEC_TO_TIME(SUM(leaveAgg.ltime)),'00:00:00') AS 'LEAVE TIME'
FROM workers
LEFT JOIN (SELECT leave.ID_WORKER, SUM((datediff(leave.BEGIN_DATE, leave.END_DATE) + 1) * (time_to_sec(time(leave.END_DATE)) - time_to_sec(time(leave.BEGIN_DATE)))) AS ltime FROM leave
LEFT JOIN
(SELECT ID_WORKER, MIN(BEGIN_DATE) AS 'MIN_BEGIN_DATE', MAX(END_DATE) AS 'MAX_END_DATE' 
FROM order_status GROUP BY ID_WORKER) ordstat ON 
leave.ID_WORKER = ordstat.ID_WORKER 
WHERE leave.END_DATE <= MAX_END_DATE AND leave.BEGIN_DATE >= MIN_BEGIN_DATE GROUP BY leave.ID_WORKER) leaveAgg
ON leaveAgg.ID_WORKER = workers.ID_WORKER
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;

例如,ID_WORKER=26的休假时间(他有订单“测试”)

我的尝试:我在下面的mysql查询中尝试了总休假时间:

SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME'
FROM workers
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;
SELECT workers.FNAME, 
workers.LNAME, 
order_statusAgg.NUMBER_ORDER,
order_statusAgg.DESC_ORDER, 
SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'ORDER TIME', 
IFNULL(SEC_TO_TIME(SUM(leaveAgg.ltime)),'00:00:00') AS 'LEAVE TIME'
FROM workers
LEFT JOIN (SELECT leave.ID_WORKER, SUM((datediff(leave.BEGIN_DATE, leave.END_DATE) + 1) * (time_to_sec(time(leave.END_DATE)) - time_to_sec(time(leave.BEGIN_DATE)))) AS ltime FROM leave
LEFT JOIN
(SELECT ID_WORKER, MIN(BEGIN_DATE) AS 'MIN_BEGIN_DATE', MAX(END_DATE) AS 'MAX_END_DATE' 
FROM order_status GROUP BY ID_WORKER) ordstat ON 
leave.ID_WORKER = ordstat.ID_WORKER 
WHERE leave.END_DATE <= MAX_END_DATE AND leave.BEGIN_DATE >= MIN_BEGIN_DATE GROUP BY leave.ID_WORKER) leaveAgg
ON leaveAgg.ID_WORKER = workers.ID_WORKER
LEFT JOIN (
SELECT order_status.ID_WORKER, orders.NUMBER_ORDER, orders.DESC_ORDER, 
SUM((TIME_TO_SEC(order_status.END_DATE) - TIME_TO_SEC(order_status.BEGIN_DATE))) AS stime 
FROM order_status INNER JOIN orders
ON orders.ID_ORDER = order_status.ID_ORDER
GROUP BY order_status.ID_WORKER) order_statusAgg
ON workers.ID_WORKER = order_statusAgg.ID_WORKER
WHERE order_statusAgg.NUMBER_ORDER LIKE 'TEST'
GROUP BY workers.ID_WORKER;
我想得到这个结果:

22:30:21 + 2:00:16 = 24:30:37
小心!如果有人休假2天或以上,我不能这样做:

                    '08:31:40'                                      
(-------------------------------------------------) * 16:00:00 
 '08:31:40' + '08:37:00' + '08:53:03' + '08:29:01'   
我每天都要像我解释的那个例子那样分析


我知道这是一个更难的问题,我找不到任何线索来解决它。有人能告诉我应该更改或添加什么吗。提前感谢您的帮助或建议。

您的订单状态表中似乎有一些额外的数据,因为我有一些额外的行。但是过滤掉这些并运行一天,我得到了一个结果。我在电子表格中仔细检查了结果,结果似乎是正确的:

(08:31:40/34:30:44)*08:00:00=01:58:36.3194

不管怎样,这是您要解决的问题:

SELECT *,
SEC_TO_TIME((d.ORDER_TIME / d.DAILY_TOTAL) * 28800) as 'LEAVE TIME'
FROM
(
SELECT  os.*,
        o.NUMBER_ORDER,
        ((TIME_TO_SEC(os.END_DATE) - TIME_TO_SEC(os.BEGIN_DATE))) AS 'ORDER_TIME',
        (SUM(TIME_TO_SEC(os.END_DATE) - TIME_TO_SEC(os.BEGIN_DATE)) OVER (PARTITION BY CAST(os.END_DATE AS DATE) ORDER BY o.ID_ORDER ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) as 'DAILY_TOTAL'
FROM order_status os
    INNER JOIN orders o ON o.ID_ORDER = os.ID_ORDER
WHERE   (
        CAST(os.BEGIN_DATE AS DATE) = '2019-03-20' OR
        CAST(os.END_DATE AS DATE) = '2019-03-20'
        )
        AND NOT (
                    os.ID_STATUS = 32 AND
                    os.ID_ORDER = 19 AND
                    os.ID_WORKER = 26)
) d

你还在寻找解决办法吗?@JimJimson是的。我仍在寻找解决方案。很好,请参阅下面的答案。