2009-09-30 4 views
0

У меня есть таблица с двумя столбцами: DATETIME (. Времена в формате HH:MM:SS)Как построить сумму столбцов DATETIME?

Column1    Column2 
1/1/1900 12:20:45 1/1/1900 23:22:25 
1/1/1900 09:00:00 1/1/1900 18:10:30 
…     … 

Я хочу взять в общей сложности колонны 1 и общей колонке 2. Если таблица была только две строки, показанные выше, ожидаемый результат будет:

Column1    Column2 
1/1/1900 21:20:45 1/1/1900 41:32:55 

Обратите внимание, что часы, минуты и секунды не превышала 60.

Как суммировать эти столбцы в SQL Server 2000?

+3

Что означает «сумма», когда вы добавляете две даты? Какие результаты можно ожидать от добавления столбцов 1 и 2 в вашем примере? – Welbog

+0

Разве вы не спросили об этом? –

+1

А, нашел (ссылка видна только для пользователей 10K): http://stackoverflow.com/questions/1497856/how-to-get-a-sum-of-varchar-value/1497937#1497937 Почему вы удалили Старый? –

ответ

0

это даст вам то, что вы после:

CREATE TABLE #Times 
(
    Column1 datetime 
    ,Column2 datetime 
) 

INSERT INTO #Times VALUES ('1/1/1900 12:20:45', '1/1/1900 23:22:25') 
INSERT INTO #Times VALUES ('1/1/1900 09:00:00', '1/1/1900 18:10:30') 

SELECT 
    CONVERT(varchar(10),dateadd(day,datediff(day,0,dt2.MinColumn1),0),101) 
     +' ' 
     +CASE WHEN TotalSecondsColumn1/3600>60 then '60' ELSE CONVERT(varchar(2),TotalSecondsColumn1/3600) END 
     +':' 
     +CASE WHEN (TotalSecondsColumn1-(TotalSecondsColumn1/3600*3600))/60 >60 then '60' ELSE CONVERT(varchar(2),(TotalSecondsColumn1-(TotalSecondsColumn1/3600*3600))/60) END 
     +':' 
     +CASE WHEN TotalSecondsColumn1-((TotalSecondsColumn1/3600*3600)+(((TotalSecondsColumn1-(TotalSecondsColumn1/3600*3600))/60)*60)) >60 then '60' ELSE CONVERT(varchar(2),TotalSecondsColumn1-((TotalSecondsColumn1/3600*3600)+(((TotalSecondsColumn1-(TotalSecondsColumn1/3600*3600))/60)*60))) END 
    AS Column1 
    ,CONVERT(varchar(10),dateadd(day,datediff(day,0,dt2.MinColumn2),0),101) 
     +' ' 
     +CASE WHEN TotalSecondsColumn2/3600>60 then '60' ELSE CONVERT(varchar(2),TotalSecondsColumn2/3600) END 
     +':' 
     +CASE WHEN (TotalSecondsColumn2-(TotalSecondsColumn2/3600*3600))/60 >60 then '60' ELSE CONVERT(varchar(2),(TotalSecondsColumn2-(TotalSecondsColumn2/3600*3600))/60) END 
     +':' 
     +CASE WHEN TotalSecondsColumn2-((TotalSecondsColumn2/3600*3600)+(((TotalSecondsColumn2-(TotalSecondsColumn2/3600*3600))/60)*60)) >60 then '60' ELSE CONVERT(varchar(2),TotalSecondsColumn2-((TotalSecondsColumn2/3600*3600)+(((TotalSecondsColumn2-(TotalSecondsColumn2/3600*3600))/60)*60))) END 
    AS Column1 
    FROM #Times t 
     INNER JOIN (SELECT 
         SUM(DATEDIFF(second,CONVERT(datetime,LEFT(CONVERT(char(23),Column1,121),10)),Column1)) AS TotalSecondsColumn1 
         ,SUM(DATEDIFF(second,CONVERT(datetime,LEFT(CONVERT(char(23),Column2,121),10)),Column2)) AS TotalSecondsColumn2 
         FROM #Times 
        ) dt ON 1=1 
     INNER JOIN (SELECT 
         MIN(Column1) AS MinColumn1 
         ,MIN(Column2) AS MinColumn2 
         FROM #Times 
        ) dt2 ON 1=1 
    WHERE t.Column1=dt2.MinColumn1 

ВЫВОД:

Column1    Column1 
------------------- ------------------- 
01/01/1900 21:20:45 01/01/1900 41:32:55 

(1 row(s) affected) 

Однако, это точно просуммировать раз, увеличивающиеся день, месяц и год, как скважина:

SELECT 
    DATEADD(second,dt.TotalSecondsColumn1,dateadd(day,datediff(day,0,dt2.MinColumn1),0)) AS Column1 
    ,DATEADD(second,dt.TotalSecondsColumn2,dateadd(day,datediff(day,0,dt2.MinColumn2),0)) AS Column2 
    FROM #Times t 
     INNER JOIN (SELECT 
         SUM(DATEDIFF(second,CONVERT(datetime,LEFT(CONVERT(char(23),Column1,121),10)),Column1)) AS TotalSecondsColumn1 
         ,SUM(DATEDIFF(second,CONVERT(datetime,LEFT(CONVERT(char(23),Column2,121),10)),Column2)) AS TotalSecondsColumn2 
         FROM #Times 
        ) dt ON 1=1 
     INNER JOIN (SELECT 
         MIN(Column1) AS MinColumn1 
         ,MIN(Column2) AS MinColumn2 
         FROM #Times 
        ) dt2 ON 1=1 
    WHERE t.Column1=dt2.MinColumn1 

OUTPUT:

Column1     Column2 
----------------------- ----------------------- 
1900-01-01 21:20:45.000 1900-01-02 17:32:55.000 

(1 row(s) affected) 
0
select Column1+Column2 from table 
+2

Пожалуйста, проверьте мой вопрос – Gopal

0
SELECT Column1 + Column2 AS MyResult FROM YOURTABLE 
0

Этот пример должен проиллюстрировать то, что вам нужно сделать:

declare @Base datetime set @base = '1900-01-01' 
declare @first datetime set @first = '1900-01-01 12:15:00' 
declare @other datetime set @other = '1900-01-01 01:00:00' 

select DATEADD(s, SUM(DATEDIFF(s, @base, dt)),@base) 
from 
(
    select @first as dt 
    union select @other 
) t 

выход из QA на моем Sql Server 2000 является коробка:

1900-01-01 13 : 15: 00.000

0

Ожидаемый результат column1 column2 1/1/1900 21:20:45 1/1/1900 41:32:55

Это не будет работать, так как DATETIME в SQL Server 2000 ограничено 24 часами.

Так что для того, чтобы подвести ваши часы, я думаю, вам придется разбить его на несколько часов, минут, секунд, как INT столбцов, а затем сделать что-то вроде

UPDATE dbo.YourTable 
SET SumHours = DATEPART(HOUR, CONVERT(DATETIME, Column1, 100)), 
    SumMinutes = DATEPART(MINUTE, CONVERT(DATETIME, Column1, 100)), 
    SumSeconds = DATEPART(SECOND, CONVERT(DATETIME, Column1, 100)) 
WHERE........ 

(и то же самое для column2, также).

Я действительно не вижу другого способа. Кроме того, вам нужно преобразовать минуты> 60 в часы + минуты и секунды> 60 в минуты + секунды.

Марк

+0

Если вы собираетесь это сделать, вы можете преобразовать его в ровное число секунд и вернуться к компонентам в конце. –

+0

@ Крис: правда, это другой способ сделать это. –

0

Мое предположение: ваши DateTimes отслеживают истекшее время. Например, ваше первое значение «1/1/1900 12:20:45» означает, что прошло 12 часов, 20 минут и 45 секунд во время (независимо). Учитывая это, вы хотите суммировать все эти прошедшие времена, создавая «общее истекшее время».

Вот один из способов сделать это. (Могут быть и другие - там всегда, кажется, лучший способ реализовать математику времени.) Я запрашиваю только один столбец, чтобы сделать пример более понятным и быть правильно параноидальным. Кроме того, я предполагаю, что : часть (а) абсолютно неактуальна и (b) может быть установлена ​​на что угодно. [И, конечно, если вы используете SQL 2008, вы хотите установить столбец с типом данных времени.] Последний столбец [5] - тот, который вы хотите; другие объясняют, как я туда попал.

select 
    MyColumn -- [1] 
    ,dateadd(dd, -datediff(dd, 0, MyColumn), MyColumn) -- [2] 
    ,datediff(ss, 0, dateadd(dd, -datediff(dd, 0, MyColumn), MyColumn)) -- [3] 
from MyTable 

select 
    sum(datediff(ss, 0, dateadd(dd, -datediff(dd, 0, MyColumn), MyColumn))) -- [4] 
    ,dateadd(ss, sum(datediff(ss, 0, dateadd(dd, -datediff(dd, 0, MyColumn), MyColumn))), 0) -- [5] 
from MyTable 

[1] показывает начальное значение для каждой строки.
[2] конвертирует дату каждого столбца в «1 января 1900 года». Если вы мертвы, убедитесь, что ваши даты будут всегда быть одинаковыми, вам не нужно учитывать это.
[3] Это вычисляет количество секунд, прошедших между полуночью и записанным временем.
[4] Это сумма секунд.
[5] Это добавляет истекшее время (в секундах) к «1 января 1900 года».

Оттуда используйте любую стандартную технологию форматирования, которую вы используете для отображения результатов в течение прошедшего времени (не забудьте указать даты, так как прошедшее время может превышать 24 часа). Этот метод будет точным для любой единицы времени (здесь, как вы хотели, я использовал секунды), но обратите внимание, что если общее количество единиц прошедшего времени превышает (2^31 - 1), как и для миллисекунд, вы может потребоваться бросить на bigints.

Хм, просто подумал: что, если одно истекшее время больше 24 часов? В этом случае дата вашего дата и времени значительна и должна представлять «дату начала». Хуже того, мы не можем предположить, что самая ранняя дата из пула образцов - это базовая дата, так как все ваши прошедшие времена могут составлять 24 часа и более. Для этого вам нужно каким-то образом определить «базовую дату» для расчета. Поскольку в вашем вопросе о том, какова может быть базовая дата, нет никаких указаний, я в качестве окончательного предположения предполагаю, что это не проблема, - что все ваши прошедшие времена будут находиться в пределах 24 часов.

0
SELECT DATEADD(s, 0, SUM(DATEDIFF(s, 0, Column1))) AS SUMColumn1 
    ,DATEADD(s, 0, SUM(DATEDIFF(s, 0, Column2))) AS SUMColumn2 
FROM tbl 
Смежные вопросы