Вы преобразование из десятичной системы счисления (4, 0) на время:
DATEADD(MINUTE, (FLOOR([Time]/100) * 60) + ([Time] % 100), '00:00')
Что только добавляют ваши общие минуты 00:00
, чтобы получить время, когда ваши общие минуты рассчитываются как (hours * 60) + minutes
где
Hours = FLOOR([Time]/100)
Minutes = ([Time] % 100)
ОДНАКО, если это не слишком поздно, вы должны отказаться этот подход полностью.
В SQL Server редко приходится создавать столбцы даты и времени отдельно, лучший подход состоит в том, чтобы иметь один столбец DATETIME2
, и если по какой-либо причине вам нужны отдельные столбцы (например, индексирование), используйте вычисленные столбцы, например.
ALTER TABLE T ADD StartDate AS CAST(StartDateTime AS DATE);
Если вы должны иметь две колонки, хранящиеся отдельно, по крайней мере, вы должны использовать тип TIME
данных для хранения времени, не DECIMAL(4, 0)
. Лучший подход к вашей ситуации - это исправить актуальную проблему, которая является неправильным типом данных, а не вопрос, который вы задали. Если вы должны были сделать это, вы бы данные, такие как:
Job Op JobDateTime
----------------------------------
1 10 06/01/2015 02:54
1 20 06/01/2015 02:54
1 20 06/01/2015 05:42
1 20 06/01/2015 13:47
1 20 07/01/2015 13:40
1 30 07/01/2015 14:08
1 30 07/01/2015 13:40
1 30 08/01/2015 10:37
1 40 06/01/2015 05:43
и т.д.
Тогда ваш запрос так прост, как
SELECT JOb, Op, FirstJob = MIN(JobDateTime), LastJob = MAX(JobDateTime)
FROM T
GROUP BY JOb, Op;
код, чтобы сделать это исправление будет:
ALTER TABLE [YourTable] ADD JobDateTime DATETIME2 NOT NULL;
UPDATE [YourTable]
SET JobDateTime = DATEADD(MINUTE, (FLOOR([Time]/100) * 60) + ([Time] % 100), CAST([Date] AS DATETIME)));
ALTER TABLE [YourTable] DROP COLUMN [Date];
ALTER TABLE [YourTable] DROP COLUMN [Time];
Если у вас уже есть много существующего кода, который использует эти столбцы, вы можете использовать вычисленный столбец для вычисления для вас:
ALTER TABLE YourTable
ADD JobDateTime AS DATEADD(MINUTE, (FLOOR([Time]/100) * 60) + ([Time] % 100), CAST([Date] AS DATETIME));
e.g.
CREATE TABLE #T (Job INT, Op INT, [Date] DATE, [Time] DECIMAL(4, 0));
INSERT #T (Job, Op, [Date], [Time])
VALUES
(1, 10, '2015-06-01', 254),
(1, 20, '2015-06-01', 254),
(1, 20, '2015-06-01', 542),
(1, 20, '2015-06-01', 1347),
(1, 20, '2015-07-01', 1340),
(1, 30, '2015-07-01', 1408),
(1, 30, '2015-07-01', 1340),
(1, 30, '2015-08-01', 1037),
(1, 40, '2015-06-01', 543),
(1, 40, '2015-06-01', 1348),
(1, 40, '2015-08-01', 1038),
(1, 50, '2015-07-01', 1219),
(1, 50, '2015-08-01', 1039),
(1, 60, '2015-07-01', 1220),
(1, 60, '2015-10-01', 1054),
(1, 60, '2015-12-01', 859);
ALTER TABLE #T
ADD JobDateTime AS DATEADD(MINUTE, (FLOOR([Time]/100) * 60) + ([Time] % 100), CAST([Date] AS DATETIME));
SELECT Job,
Op,
FirstJob = MIN(JobDateTime),
LastJob = MAX(JobDateTime)
FROM #T
GROUP BY Job, Op;
Как выше следует, я бы рекомендовал только вернув дату и время в качестве одного столбца, но если вы хотите их как отдельные столбцы, то вы должны по крайней мере использовать тип TIME
:
В любом случае я бы рекомендовал вернуть полное время или, по крайней мере, использовать столбцы даты и времени, например
SELECT Job,
Op,
[Start] = CAST(MIN(JobDateTime) AS DATE),
[End] = CAST(MAX(JobDateTime) AS DATE),
StartTime = CAST(MIN(JobDateTime) AS TIME),
EndTime = CAST(MAX(JobDateTime) AS TIME)
FROM #T
GROUP BY Job, Op;
Если вы не можете делать какие-либо изменения схемы вы можете просто включать формулу в Вашем запросе (после того, как вы были пробивать свой дБА для использования десятичной для хранения времени):
SELECT Job,
Op,
FirstJob = MIN(DATEADD(MINUTE, (FLOOR([Time]/100) * 60) + ([Time] % 100), CAST([Date] AS DATETIME))),
LastJob = MAX(DATEADD(MINUTE, (FLOOR([Time]/100) * 60) + ([Time] % 100), CAST([Date] AS DATETIME)))
FROM #T
GROUP BY Job, Op;
Что вы используете? Пожалуйста, отметьте вопрос соответствующим образом. –