DATEDIFF in HH:MM:SS format










11















I need to calculate the total length in terms of Hours, Minutes, Seconds, and the average length, given some data with start time and end time.



For example the result must be something like 45:15:10 which means 45 hours 15 min 10 sec, or 30:07 for 30 min 07 sec.



We're using SQL Server 2008 R2 and the conversion failed when time is more than 24:59:59. Any idea of how I could do this?



For information, the columns in the table are Id, StartDateTime, EndDateTime, etc. I need to make a monthly report which contains the recordings count of the month, the total length of these records, and the average length. I'd like to know if there is an easy way to perform all of this.










share|improve this question



















  • 2





    Convert everything to seconds, sum it and then convert to readable format manually.

    – Kermit
    Jan 21 '13 at 19:15
















11















I need to calculate the total length in terms of Hours, Minutes, Seconds, and the average length, given some data with start time and end time.



For example the result must be something like 45:15:10 which means 45 hours 15 min 10 sec, or 30:07 for 30 min 07 sec.



We're using SQL Server 2008 R2 and the conversion failed when time is more than 24:59:59. Any idea of how I could do this?



For information, the columns in the table are Id, StartDateTime, EndDateTime, etc. I need to make a monthly report which contains the recordings count of the month, the total length of these records, and the average length. I'd like to know if there is an easy way to perform all of this.










share|improve this question



















  • 2





    Convert everything to seconds, sum it and then convert to readable format manually.

    – Kermit
    Jan 21 '13 at 19:15














11












11








11








I need to calculate the total length in terms of Hours, Minutes, Seconds, and the average length, given some data with start time and end time.



For example the result must be something like 45:15:10 which means 45 hours 15 min 10 sec, or 30:07 for 30 min 07 sec.



We're using SQL Server 2008 R2 and the conversion failed when time is more than 24:59:59. Any idea of how I could do this?



For information, the columns in the table are Id, StartDateTime, EndDateTime, etc. I need to make a monthly report which contains the recordings count of the month, the total length of these records, and the average length. I'd like to know if there is an easy way to perform all of this.










share|improve this question
















I need to calculate the total length in terms of Hours, Minutes, Seconds, and the average length, given some data with start time and end time.



For example the result must be something like 45:15:10 which means 45 hours 15 min 10 sec, or 30:07 for 30 min 07 sec.



We're using SQL Server 2008 R2 and the conversion failed when time is more than 24:59:59. Any idea of how I could do this?



For information, the columns in the table are Id, StartDateTime, EndDateTime, etc. I need to make a monthly report which contains the recordings count of the month, the total length of these records, and the average length. I'd like to know if there is an easy way to perform all of this.







sql sql-server sql-server-2008 date datetime






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 11 '16 at 14:37









Rafael

3,18032334




3,18032334










asked Jan 21 '13 at 19:13









user1671731user1671731

92119




92119







  • 2





    Convert everything to seconds, sum it and then convert to readable format manually.

    – Kermit
    Jan 21 '13 at 19:15













  • 2





    Convert everything to seconds, sum it and then convert to readable format manually.

    – Kermit
    Jan 21 '13 at 19:15








2




2





Convert everything to seconds, sum it and then convert to readable format manually.

– Kermit
Jan 21 '13 at 19:15






Convert everything to seconds, sum it and then convert to readable format manually.

– Kermit
Jan 21 '13 at 19:15













5 Answers
5






active

oldest

votes


















9














You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).



DECLARE @d TABLE
(
id INT IDENTITY(1,1),
StartDateTime DATETIME,
EndDateTime DATETIME
);

INSERT @d(StartDateTime, EndDateTime) VALUES
(DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
(GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
(DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
(DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));

;WITH x AS (SELECT id, StartDateTime, EndDateTime,
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM @d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;


Results:



id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
-- ------------------- ------------------- -------------- ------------
1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33


This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:



;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM @d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;


This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.






share|improve this answer
































    3














    SELECT CONVERT(time, 
    DATEADD(mcs,
    DATEDIFF(mcs,
    '2007-05-07 09:53:00.0273335',
    '2007-05-07 09:53:01.0376635'),
    CAST('1900-01-01 00:00:00.0000000' as datetime2)
    )
    )





    share|improve this answer
































      1














      If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:



      select avg(cast(endtime - starttime) as float)
      from t


      You can convert it back to a datetime using the reverse cast:



      select cast(avg(cast(endtime - starttime as float) as datetime)
      from t


      The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:



      select right(convert(varchar(255), <val>, 120), 10)


      To get the hours exceeding 24, here is another approach:



      select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)


      It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.






      share|improve this answer






























        1














        I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:



        SELECT CONVERT(time, 
        DATEADD(s,
        DATEDIFF(s,
        '2018-01-07 09:53:00',
        '2018-01-07 11:53:01'),
        CAST('1900-01-01 00:00:00.0000000' as datetime2)
        )
        )





        share|improve this answer






























          0














          A way that avoids overflows and can include days and go all the way to milliseconds in the output:



          DECLARE @startDate AS DATETIME = '2018-06-01 14:20:02.100'
          DECLARE @endDate AS DATETIME = '2018-06-02 15:23:09.000'
          SELECT CAST(DATEDIFF(day,'1900-01-01', @endDate - @startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), @endDate - @startDate, 114)


          The above will return




          1d 01:03:06:900




          And, off course, you can use the formatting of your choice



          SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.






          share|improve this answer






















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f14445600%2fdatediff-in-hhmmss-format%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            5 Answers
            5






            active

            oldest

            votes








            5 Answers
            5






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            9














            You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).



            DECLARE @d TABLE
            (
            id INT IDENTITY(1,1),
            StartDateTime DATETIME,
            EndDateTime DATETIME
            );

            INSERT @d(StartDateTime, EndDateTime) VALUES
            (DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
            (GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
            (DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
            (DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));

            ;WITH x AS (SELECT id, StartDateTime, EndDateTime,
            d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
            a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
            FROM @d
            )
            SELECT id, StartDateTime, EndDateTime,
            [delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
            + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
            + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
            [avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
            + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
            + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
            FROM x;


            Results:



            id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
            -- ------------------- ------------------- -------------- ------------
            1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
            2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
            3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
            4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33


            This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:



            ;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
            d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
            a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
            FROM @d
            )
            SELECT id, StartDateTime, EndDateTime,
            [delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
            CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
            + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
            + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
            [avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
            CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
            + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
            + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
            FROM x;


            This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.






            share|improve this answer





























              9














              You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).



              DECLARE @d TABLE
              (
              id INT IDENTITY(1,1),
              StartDateTime DATETIME,
              EndDateTime DATETIME
              );

              INSERT @d(StartDateTime, EndDateTime) VALUES
              (DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
              (GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
              (DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
              (DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));

              ;WITH x AS (SELECT id, StartDateTime, EndDateTime,
              d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
              a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
              FROM @d
              )
              SELECT id, StartDateTime, EndDateTime,
              [delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
              + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
              + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
              [avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
              + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
              + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
              FROM x;


              Results:



              id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
              -- ------------------- ------------------- -------------- ------------
              1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
              2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
              3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
              4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33


              This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:



              ;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
              d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
              a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
              FROM @d
              )
              SELECT id, StartDateTime, EndDateTime,
              [delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
              CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
              + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
              + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
              [avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
              CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
              + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
              + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
              FROM x;


              This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.






              share|improve this answer



























                9












                9








                9







                You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).



                DECLARE @d TABLE
                (
                id INT IDENTITY(1,1),
                StartDateTime DATETIME,
                EndDateTime DATETIME
                );

                INSERT @d(StartDateTime, EndDateTime) VALUES
                (DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
                (GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
                (DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
                (DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));

                ;WITH x AS (SELECT id, StartDateTime, EndDateTime,
                d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
                a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
                FROM @d
                )
                SELECT id, StartDateTime, EndDateTime,
                [delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
                [avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
                FROM x;


                Results:



                id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
                -- ------------------- ------------------- -------------- ------------
                1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
                2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
                3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
                4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33


                This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:



                ;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
                d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
                a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
                FROM @d
                )
                SELECT id, StartDateTime, EndDateTime,
                [delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
                CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
                + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
                [avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
                CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
                + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
                FROM x;


                This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.






                share|improve this answer















                You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).



                DECLARE @d TABLE
                (
                id INT IDENTITY(1,1),
                StartDateTime DATETIME,
                EndDateTime DATETIME
                );

                INSERT @d(StartDateTime, EndDateTime) VALUES
                (DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
                (GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
                (DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
                (DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));

                ;WITH x AS (SELECT id, StartDateTime, EndDateTime,
                d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
                a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
                FROM @d
                )
                SELECT id, StartDateTime, EndDateTime,
                [delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
                [avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
                FROM x;


                Results:



                id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
                -- ------------------- ------------------- -------------- ------------
                1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
                2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
                3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
                4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33


                This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:



                ;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
                d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
                a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
                FROM @d
                )
                SELECT id, StartDateTime, EndDateTime,
                [delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
                CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
                + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
                [avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
                CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
                + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
                + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
                FROM x;


                This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 21 '13 at 19:38

























                answered Jan 21 '13 at 19:25









                Aaron BertrandAaron Bertrand

                212k27370408




                212k27370408























                    3














                    SELECT CONVERT(time, 
                    DATEADD(mcs,
                    DATEDIFF(mcs,
                    '2007-05-07 09:53:00.0273335',
                    '2007-05-07 09:53:01.0376635'),
                    CAST('1900-01-01 00:00:00.0000000' as datetime2)
                    )
                    )





                    share|improve this answer





























                      3














                      SELECT CONVERT(time, 
                      DATEADD(mcs,
                      DATEDIFF(mcs,
                      '2007-05-07 09:53:00.0273335',
                      '2007-05-07 09:53:01.0376635'),
                      CAST('1900-01-01 00:00:00.0000000' as datetime2)
                      )
                      )





                      share|improve this answer



























                        3












                        3








                        3







                        SELECT CONVERT(time, 
                        DATEADD(mcs,
                        DATEDIFF(mcs,
                        '2007-05-07 09:53:00.0273335',
                        '2007-05-07 09:53:01.0376635'),
                        CAST('1900-01-01 00:00:00.0000000' as datetime2)
                        )
                        )





                        share|improve this answer















                        SELECT CONVERT(time, 
                        DATEADD(mcs,
                        DATEDIFF(mcs,
                        '2007-05-07 09:53:00.0273335',
                        '2007-05-07 09:53:01.0376635'),
                        CAST('1900-01-01 00:00:00.0000000' as datetime2)
                        )
                        )






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Apr 30 '15 at 3:54









                        bit

                        3,59711932




                        3,59711932










                        answered Apr 30 '15 at 3:07









                        Avinash ReddyAvinash Reddy

                        311




                        311





















                            1














                            If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:



                            select avg(cast(endtime - starttime) as float)
                            from t


                            You can convert it back to a datetime using the reverse cast:



                            select cast(avg(cast(endtime - starttime as float) as datetime)
                            from t


                            The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:



                            select right(convert(varchar(255), <val>, 120), 10)


                            To get the hours exceeding 24, here is another approach:



                            select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)


                            It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.






                            share|improve this answer



























                              1














                              If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:



                              select avg(cast(endtime - starttime) as float)
                              from t


                              You can convert it back to a datetime using the reverse cast:



                              select cast(avg(cast(endtime - starttime as float) as datetime)
                              from t


                              The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:



                              select right(convert(varchar(255), <val>, 120), 10)


                              To get the hours exceeding 24, here is another approach:



                              select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)


                              It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.






                              share|improve this answer

























                                1












                                1








                                1







                                If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:



                                select avg(cast(endtime - starttime) as float)
                                from t


                                You can convert it back to a datetime using the reverse cast:



                                select cast(avg(cast(endtime - starttime as float) as datetime)
                                from t


                                The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:



                                select right(convert(varchar(255), <val>, 120), 10)


                                To get the hours exceeding 24, here is another approach:



                                select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)


                                It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.






                                share|improve this answer













                                If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:



                                select avg(cast(endtime - starttime) as float)
                                from t


                                You can convert it back to a datetime using the reverse cast:



                                select cast(avg(cast(endtime - starttime as float) as datetime)
                                from t


                                The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:



                                select right(convert(varchar(255), <val>, 120), 10)


                                To get the hours exceeding 24, here is another approach:



                                select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)


                                It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.







                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Jan 21 '13 at 19:26









                                Gordon LinoffGordon Linoff

                                789k35314418




                                789k35314418





















                                    1














                                    I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:



                                    SELECT CONVERT(time, 
                                    DATEADD(s,
                                    DATEDIFF(s,
                                    '2018-01-07 09:53:00',
                                    '2018-01-07 11:53:01'),
                                    CAST('1900-01-01 00:00:00.0000000' as datetime2)
                                    )
                                    )





                                    share|improve this answer



























                                      1














                                      I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:



                                      SELECT CONVERT(time, 
                                      DATEADD(s,
                                      DATEDIFF(s,
                                      '2018-01-07 09:53:00',
                                      '2018-01-07 11:53:01'),
                                      CAST('1900-01-01 00:00:00.0000000' as datetime2)
                                      )
                                      )





                                      share|improve this answer

























                                        1












                                        1








                                        1







                                        I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:



                                        SELECT CONVERT(time, 
                                        DATEADD(s,
                                        DATEDIFF(s,
                                        '2018-01-07 09:53:00',
                                        '2018-01-07 11:53:01'),
                                        CAST('1900-01-01 00:00:00.0000000' as datetime2)
                                        )
                                        )





                                        share|improve this answer













                                        I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:



                                        SELECT CONVERT(time, 
                                        DATEADD(s,
                                        DATEDIFF(s,
                                        '2018-01-07 09:53:00',
                                        '2018-01-07 11:53:01'),
                                        CAST('1900-01-01 00:00:00.0000000' as datetime2)
                                        )
                                        )






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Jan 18 '18 at 6:46









                                        jabko87jabko87

                                        1,61711323




                                        1,61711323





















                                            0














                                            A way that avoids overflows and can include days and go all the way to milliseconds in the output:



                                            DECLARE @startDate AS DATETIME = '2018-06-01 14:20:02.100'
                                            DECLARE @endDate AS DATETIME = '2018-06-02 15:23:09.000'
                                            SELECT CAST(DATEDIFF(day,'1900-01-01', @endDate - @startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), @endDate - @startDate, 114)


                                            The above will return




                                            1d 01:03:06:900




                                            And, off course, you can use the formatting of your choice



                                            SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.






                                            share|improve this answer



























                                              0














                                              A way that avoids overflows and can include days and go all the way to milliseconds in the output:



                                              DECLARE @startDate AS DATETIME = '2018-06-01 14:20:02.100'
                                              DECLARE @endDate AS DATETIME = '2018-06-02 15:23:09.000'
                                              SELECT CAST(DATEDIFF(day,'1900-01-01', @endDate - @startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), @endDate - @startDate, 114)


                                              The above will return




                                              1d 01:03:06:900




                                              And, off course, you can use the formatting of your choice



                                              SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.






                                              share|improve this answer

























                                                0












                                                0








                                                0







                                                A way that avoids overflows and can include days and go all the way to milliseconds in the output:



                                                DECLARE @startDate AS DATETIME = '2018-06-01 14:20:02.100'
                                                DECLARE @endDate AS DATETIME = '2018-06-02 15:23:09.000'
                                                SELECT CAST(DATEDIFF(day,'1900-01-01', @endDate - @startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), @endDate - @startDate, 114)


                                                The above will return




                                                1d 01:03:06:900




                                                And, off course, you can use the formatting of your choice



                                                SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.






                                                share|improve this answer













                                                A way that avoids overflows and can include days and go all the way to milliseconds in the output:



                                                DECLARE @startDate AS DATETIME = '2018-06-01 14:20:02.100'
                                                DECLARE @endDate AS DATETIME = '2018-06-02 15:23:09.000'
                                                SELECT CAST(DATEDIFF(day,'1900-01-01', @endDate - @startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), @endDate - @startDate, 114)


                                                The above will return




                                                1d 01:03:06:900




                                                And, off course, you can use the formatting of your choice



                                                SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.







                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Jun 11 '18 at 18:08









                                                Eugenio AndruskiewitschEugenio Andruskiewitsch

                                                1




                                                1



























                                                    draft saved

                                                    draft discarded
















































                                                    Thanks for contributing an answer to Stack Overflow!


                                                    • Please be sure to answer the question. Provide details and share your research!

                                                    But avoid


                                                    • Asking for help, clarification, or responding to other answers.

                                                    • Making statements based on opinion; back them up with references or personal experience.

                                                    To learn more, see our tips on writing great answers.




                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function ()
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f14445600%2fdatediff-in-hhmmss-format%23new-answer', 'question_page');

                                                    );

                                                    Post as a guest















                                                    Required, but never shown





















































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown

































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown







                                                    Popular posts from this blog

                                                    𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                                                    Edmonton

                                                    Crossroads (UK TV series)