У меня есть таблица, которая содержит строки для разных событий в течение дня.
+------------+---------------------+---------------------+-----------+
| Logdate | Firstart | Laststop | Drivetime |
+------------+---------------------+---------------------+-----------+
| 2018-04-01 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 | 00:36:25 |
| 2018-04-01 | 2018-04-01 07:43:12 | 2018-04-01 09:43:12 | 00:21:23 |
| 2018-04-01 | 2018-04-01 09:53:27 | 2018-04-01 14:45:11 | 00:54:11 |
+------------+---------------------+---------------------+-----------+
Мне приходится группироваться днем и получать минимальное значение Firststart, где оно присутствует.
Если Firststart отсутствует для этого события, значение равно 0000-00-00 00:00:00.
Теперь я должен запросить:
MIN (Firststart) со значением> '0000-00-00 00:00:00' (если присутствует, в противном случае - 0000-00-00 00:00:00 ') и SUM (Drivetime) для каждого регистратора.
Используя этот запрос ниже, я всегда получаю '0000-00-00 00:00:00' как MIN (firstart), но я хочу получить '2018-04-01 07:43:12' за это значение,
SELECT
Logdate,
MIN(Firststart) AS Firststart,
MAX(Laststop) AS Laststop,
SEC_TO_TIME(SUM(TIME_TO_SEC(Drivetime))) AS Drivetime
FROM Logevents
WHERE Logdate >= "2018-04-01"
GROUP BY Logdate
Возможно ли это, и если да, то какой правильный синтаксис?
Хитрость заключается в том, чтобы использовать NULLIF
для переключения до NULL всех строк '0000-00-00 00:00:00'
до функции MIN/MAX
aggreagate, поскольку она будет исключать их.
После агрегации, если есть нули, мы можем использовать ISNULL
чтобы преобразовать их в строку '0000-00-00 00:00:00'
.
select
Logdate,
isnull(MIN(nullif(Firststart, '0000-00-00 00:00:00')), '0000-00-00 00:00:00') Firststart,
isnull(MAX(nullif(Laststop, '0000-00-00 00:00:00')), '0000-00-00 00:00:00') Laststop,
cast(dateadd(ss, SUM(datediff(ss, 0, Drivetime)), 0) as time(0)) Drivetime
from x
group by Logdate
Попробуй это:
SELECT Logdate, MAX(Firststart) AS Firststart, MAX(Laststop) AS Laststop,
SEC_TO_TIME(SUM(TIME_TO_SEC(A.Drivetime))) AS Drivetime
FROM
(SELECT
Logdate, MIN(Firststart) AS Firststart, MAX(Laststop) AS Laststop,
SEC_TO_TIME(SUM(TIME_TO_SEC(Drivetime))) AS Drivetime
FROM Logevents
WHERE Firststart>'0000-00-00 00:00:00'
GROUP BY Logdate
UNION
SELECT
Logdate, MIN(Firststart) AS Firststart, MAX(Laststop) AS Laststop,
SEC_TO_TIME(SUM(TIME_TO_SEC(Drivetime))) AS Drivetime
FROM Logevents
WHERE Firststart='0000-00-00 00:00:00'
GROUP BY Logdate) A
GROUP BY A.Logdate;
Посмотрите, как это работает на SQL Fiddle.