Member 10696161 Ответов: 1

Как правильно суммировать как “время отпуска” + “общее время” - mysql


В базе данных mysql я создал таблицу "оставить" :

+--------+---------+---------+-------------+---------+-------------------------------+
|ID_LEAVE|ID_WORKER| FNAME   | LNAME   | BEGIN_DATE          | END_DATE              | 
+--------+---------+---------+---------+------------+--------------------+-----------
| 1      |   1     | DAVID   | BUCS    |2019-03-19 07:00:00  |2019-03-19 15:00:00    | 
+--------+---------+---------+----------------------+--------------------+----------- 
| 2      |   2     | MARK    | GREEN   |2019-03-21 07:00:00  |2019-03-21 15:00:00    |
+--------+---------+---------+----------------------+--------------------------------+


Таблица "рабочие" :

+----------+---------+---------+
|ID_WORKER |  FNAME  | LNAME   |
+----------+---------+----------
| 1        |  DAVID  |  BUCS   |
+----------+---------+----------
| 2        |  MARK   |  GREEN  |
+----------+---------+---------+


"Таблица заказов:

+----------+--------------+---------------+
|ID_ORDER  |  DESC_ORDER  | NUMBER_ORDER  |
+----------+--------------+---------------+
| 20       |  TEST        |  TEST         |
+----------+--------------+---------------+


Таблица "Order_status" :

+----------+---------+---------+---------------------+-------------------+------------+
| Id_status|ID_WORKER| ID_ORDER| BEGIN_DATE          | END_DATE          | ORDER_DONE |
+----------+---------+---------+----------+------------+---------+--------------------+
| 30       |   1     |    20   |2019-03-18 06:50:35  |2019-03-18 15:21:32|  NO        |
+----------+---------+---------+------------+---------+-------------------+-----------+ 
| 31       |   1     |    20   |2019-03-20 06:44:12  |2019-03-20 15:11:23|  NO        |
+----------+---------+---------+------------+---------+-------------------+-----------+ 
| 32       |   1     |    20   |2019-03-22 06:50:20  |2019-03-22 12:22:33|  YES       |
+----------+---------+---------+------------+---------+-------------------+-----------+ 
| 33       |   2     |    20   |2019-03-18 06:45:11  |2019-03-18 15:14:45|  NO        |
+----------+---------+---------+------------+---------+-------------------+-----------+ 
| 34       |   2     |    20   |2019-03-20 06:50:22  |2019-03-20 15:10:32|  NO        |
+----------+---------+---------+------------+---------+-------------------+-----------+ 
| 35       |   2     |    20   |2019-03-22 06:54:11  |2019-03-22 11:23:45|  YES       |
+----------+---------+---------+------------+---------+-------------------+-----------+ 


Что я сделал:

Я могу суммировать "общее время" друг друга работников (в таблице order_status) по порядку, в том числе с суммированием "времени отпуска" из таблицы отпуска. Я также правильно выбрал рабочие (LNAME, FNAME) заказы (DESC_ORDER и NUMBER_ORDER) и "общее время" по заказу друг от друга рабочих. Я написал команду mysql ниже:

SELECT workers.fname, 
       workers.lname, 
       order_statusAgg.number_order,
       workers.id_worker,
       order_statusAgg.desc_order, 
       SEC_TO_TIME(SUM(order_statusAgg.stime)) AS 'TOTAL TIME', 
       SEC_TO_TIME(SUM(leaveAgg.ltime)) AS 'LEAVE TIME' 
FROM   workers 
INNER JOIN (
SELECT leave.id_worker, SUM((Time_to_sec(leave.end_date) - 
                       Time_to_sec(leave.begin_date))) AS ltime
FROM leave
GROUP BY leave.id_worker
) leaveAgg
               ON leaveAgg.id_worker = workers.id_worker
       INNER 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 | TOTAL TIME | LEAVE_TIME   |
 +---------+---------+---------------+------------+------------+--------------+
 |  DAVID  |  BUCS   | TEST          | TEST       | 22:30:21   |   8:00:00    |
 +---------+---------+---------------+------------+------------+--------------+
 |  MARK   |  GREEN  | TEST          | TEST       | 21:19:18   |   8:00:00    |
 +---------+---------+---------------+------------+------------+--------------+


что я хотел бы сделать дальше:

Что я хотел бы сделать дальше: я пытаюсь суммировать их все, я имею в виду: общее время + LEAVE_TIME для каждого работника. Например:

 +---------+---------+---------------+------------+------------+-------------+----------+
|  FNAME  | LNAME   |  NUMBER_ORDER | DESC_ORDER | TOTAL TIME | LEAVE_TIME   | SUM_TIME |
+---------+---------+---------------+------------+------------+--------------+----------+
|  DAVID  |  BUCS   | TEST          | TEST       | 22:30:21   |   8:00:00    | 30:30:21 |
+---------+---------+---------------+------------+------------+--------------+----------+
|  MARK   |  GREEN  | TEST          | TEST       | 21:19:18   |   8:00:00    | 29:19:18 | 
+---------+---------+---------------+------------+------------+--------------+----------+


Я понятия не имею, как ее решить. Есть ли у кого-нибудь идея, как ее решить? Любая идея. Спасибо большое за любую помощь!

Что я уже пробовал:

я пробовал добавить в верхний запрос:

SEC_TO_TIME(SUM(SEC_TO_TIME(SUM(order_statusAgg.ttime) + SUM(leaveAgg.stime)) AS 'SUM_TIME';


Но я знаю, что это плохая идея.

1 Ответов

Рейтинг:
5

CHill60

1. Использование SEC_TO_TIME, TIME_TO_SEC кажется излишним. Почему бы просто не использовать TIMESTAMPDIFF[^]

2. у вас плохой дизайн БД - нет необходимости повторять имя и фамилию работников в БД. leave таблица - у вас есть эта информация на workers таблица и у вас есть ссылка на эту таблицу в leave.ID_WORKER

3. я не вижу никакой причины для всех этих подзапросов (и он не будет компилироваться для меня), что-то вроде следующего гораздо проще и легче следовать

select W.fname, W.lname, NUMBER_ORDER, DESC_ORDER
   ,SUM(TIMESTAMPDIFF(HOUR, os.begin_date, os.end_date)) as hoursWorkedOnOrders
   ,SUM(TIMESTAMPDIFF(HOUR, l.BEGIN_DATE, L.END_DATE)) as leavetime
   ,SUM(TIMESTAMPDIFF(HOUR, os.begin_date, os.end_date)) + SUM(TIMESTAMPDIFF(HOUR, l.BEGIN_DATE, L.END_DATE)) as totaltime
from #workers W
INNER JOIN #order_status OS ON W.id_worker = OS.id_worker
INNER JOIN #orders O ON OS.id_order = O.id_order
LEFT OUTER JOIN #leave L ON L.id_worker = W.id_worker
GROUP BY W.fname, W.lname, NUMBER_ORDER, DESC_ORDER



Edit - в качестве отступления я благодарю вас за предоставление ваших схем таблиц, образцов данных, предпринятого кода и ожидаемых результатов, поэтому я поддерживаю ваш вопрос. Если вы хотите, чтобы нам было еще проще помочь вам, избегайте рисования таблиц с вашими данными и просто дайте нам несколько простых ddl для воспроизведения проблемы. Чтобы объяснить, что я имею в виду, вот примеры данных, которые я использовал для получения вышеприведенного решения:
create table #leave(ID_LEAVE int identity(1,1),ID_WORKER int, FNAME varchar(30), LNAME varchar(30), BEGIN_DATE datetime, END_DATE datetime)
insert into #leave(ID_WORKER, FNAME, LNAME, BEGIN_DATE, END_DATE) values
(1, 'DAVID', 'BUCS','2019-03-19 07:00:00','2019-03-19 15:00:00'), 
(2, 'MARK', 'GREEN','2019-03-21 07:00:00','2019-03-21 15:00:00')
select * from 

create table #workers(ID_WORKER int identity(1,1),  FNAME varchar(30)  , LNAME varchar(30))
insert into #workers (FNAME  , LNAME) values
('DAVID',  'BUCS'),
('MARK',  'GREEN')

create table #orders (ID_ORDER int,  DESC_ORDER varchar(30), NUMBER_ORDER varchar(30))
insert into #orders (ID_ORDER  ,  DESC_ORDER  , NUMBER_ORDER) values
(20,  'TEST',  'TEST')

create table #order_status(Id_status int identity(30,1),ID_WORKER int, ID_ORDER int, BEGIN_DATE datetime, END_DATE datetime, ORDER_DONE varchar(3))
insert into #order_status (ID_WORKER, ID_ORDER, BEGIN_DATE, END_DATE, ORDER_DONE) values
(1,    20   ,'2019-03-18 06:50:35'  ,'2019-03-18 15:21:32',  'NO' )       ,
(1,    20   ,'2019-03-20 06:44:12'  ,'2019-03-20 15:11:23',  'NO' )       ,
(1,    20   ,'2019-03-22 06:50:20'  ,'2019-03-22 12:22:33',  'YES' )      ,
(2,    20   ,'2019-03-18 06:45:11'  ,'2019-03-18 15:14:45',  'NO'  )      ,
(2,    20   ,'2019-03-20 06:50:22'  ,'2019-03-20 15:10:32',  'NO'  )      ,
(2,    20   ,'2019-03-22 06:54:11'  ,'2019-03-22 11:23:45',  'YES' )


Maciej Los

5ed!

Member 10696161

Спасибо за ответ но я проверил этот код и у меня есть ошибка

#1582 - неверное количество параметров в вызове собственной функции 'TIMEDIFF'

Для некоторой помощи у меня есть версия 10.1.37-MariaDB

CHill60

Мои извинения, я использовал SQL Server, чтобы проверить решение, и забыл изменить TIMEDIFF на TIMEПЕЧАТЬDIFF (согласно ссылке в решении). Я обновил свое решение