Add varchar columns with colon in between to show time

  • Hi,

    I have a requirement to add columns (varchar) where data is separated with a colon (:). For e.g.

    115:32 and 34:28

    160:00 (hrs and minutes).

    Thanks,

    Paul

  • Well you have stated your requirement, as strange as it seems, but what is your question ? What assistance are you seeking ?

    Looking for a better method to store datetime values? It seems as what you have been requested, is not the best method to store time, but then again you may not have any alternative.

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • bitbucket-25253 (3/23/2012)


    Well you have stated your requirement, as strange as it seems, but what is your question ? What assistance are you seeking ?

    Looking for a better method to store datetime values? It seems as what you have been requested, is not the best method to store time, but then again you may not have any alternative.

    I'll try to explain my requirement in detail:

    There is a column(varchar) in a table which stores values in the format 00:00. I need to sum these values in such a way that it is stored in a HH:MM format. Say for e.g. there are these 2 values-

    161:37 and 129:33. It should show the output as:

    291:10 (converted in the format as HH:MM).

    The problem is the column has a varchar datatype. I hope I have made it more clear.

    Thanks.

  • Here is one way of doing what you want, but I must say it is not very efficient, but for the life of me I can not come up with another suggestion.

    DECLARE @H1 VARCHAR(10)

    DECLARE @H2 VARCHAR(10)

    DECLARE @min-2 AS INT

    DECLARE @Hrs AS INT

    SET @H1 = '161:37'

    SET @H2 = '129:33'

    SET @min-2 = CAST(SUBSTRING(@H1,CHARINDEX(':',@H1)+1,DATALENGTH(@H1))AS INT)+CAST(SUBSTRING(@H2,CHARINDEX(':',@H2)+1,DATALENGTH(@H2))AS INT)

    SELECT CAST(CAST(SUBSTRING(@H1,1,CHARINDEX(':',@H1)-1) AS INT)

    +CAST(SUBSTRING(@H2,1,CHARINDEX(':',@H2)-1)AS INT)

    +(@Min - (@Min%60))/60 AS VARCHAR(10))+':'+ CAST(@Min%60 AS VARCHAR(2))

    Result:

    291:10

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • What would make it clearer is if you took the time to provide us with the DDL (CREATE TABLE statement(s)) for the table(s) involved, sample data for the table(s) (as INSERT INTO statements), the expected results based on the sample data, and what you have done so far to solve your problem so that we know where you are having problems and can help.

    Please read the first article I reference below in my signature block regarding "Asking for help". It will show you what you need to provide and how to post it to get the best possible answers to your questions.

    Remember, we can't see what you see unless you show us.

  • pwalter83 (3/23/2012)


    Hi,

    I have a requirement to add columns (varchar) where data is separated with a colon (:). For e.g.

    115:32 and 34:28

    160:00 (hrs and minutes).

    Thanks,

    Paul

    I would suggest to store your time in minutes in column of INT datatype. In this case you can easily use this time in any calculations. Formatting to HH:MM can be done when you output data to UI or other consumer.

    At the end, you can have computed column which will "store" this in formatted way.

    You will find, that storing it as formatted string (varchar), gives no much benefits, but guaranteed nightmare for any calculation...

    _____________________________________________
    "The only true wisdom is in knowing you know nothing"
    "O skol'ko nam otkrytiy chudnyh prevnosit microsofta duh!":-D
    (So many miracle inventions provided by MS to us...)

    How to post your question to get the best and quick help[/url]

  • bitbucket-25253 (3/23/2012)


    Here is one way of doing what you want, but I must say it is not very efficient, but for the life of me I can not come up with another suggestion.

    DECLARE @H1 VARCHAR(10)

    DECLARE @H2 VARCHAR(10)

    DECLARE @min-2 AS INT

    DECLARE @Hrs AS INT

    SET @H1 = '161:37'

    SET @H2 = '129:33'

    SET @min-2 = CAST(SUBSTRING(@H1,CHARINDEX(':',@H1)+1,DATALENGTH(@H1))AS INT)+CAST(SUBSTRING(@H2,CHARINDEX(':',@H2)+1,DATALENGTH(@H2))AS INT)

    SELECT CAST(CAST(SUBSTRING(@H1,1,CHARINDEX(':',@H1)-1) AS INT)

    +CAST(SUBSTRING(@H2,1,CHARINDEX(':',@H2)-1)AS INT)

    +(@Min - (@Min%60))/60 AS VARCHAR(10))+':'+ CAST(@Min%60 AS VARCHAR(2))

    Result:

    291:10

    Thanks for your reply....However, I have to create a new column based on this calculation and use that in a report. Your code is correct but I just want to know how do I replace @min-2 ?

    Something like this-

    CAST(SUBSTRING(WeekHours,CHARINDEX(':',WeekHours)+1,DATALENGTH(WeekHours))AS INT)+CAST(SUBSTRING(WeekHours,CHARINDEX(':',WeekHours)+1,DATALENGTH(WeekHours))AS INT)

    SELECT CAST(CAST(SUBSTRING(WeekHours,1,CHARINDEX(':',WeekHours)-1) AS INT)

    +CAST(SUBSTRING(WeekHours,1,CHARINDEX(':',WeekHours)-1)AS INT)

    +(WeekHours - (WeekHours%60))/60 AS VARCHAR(10))+':'+ CAST(WeekHours%60 AS VARCHAR(2)) as StandardHours

  • @min-2 is simply functioning as a "place holder" or intermediate value. You could alter the previous code to

    SET @min-2 = CAST(SUBSTRING(@H1,CHARINDEX(':',@H1)+1,DATALENGTH(@H1))AS INT)+CAST(SUBSTRING(@H2,CHARINDEX(':',@H2)+1,DATALENGTH(@H2))AS INT)

    INSERT INTO NewColumn -- Inserted new statement

    SELECT CAST(CAST(SUBSTRING(@H1,1,CHARINDEX(':',@H1)-1) AS INT)

    +CAST(SUBSTRING(@H2,1,CHARINDEX(':',@H2)-1)AS INT)

    +(@Min - (@Min%60))/60 AS VARCHAR(10))+':'+ CAST(@Min%60 AS VARCHAR(2))

    ]

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • bitbucket-25253 (3/23/2012)


    @Min is simply functioning as a "place holder" or intermediate value. You could alter the previous code to

    SET @min-2 = CAST(SUBSTRING(@H1,CHARINDEX(':',@H1)+1,DATALENGTH(@H1))AS INT)+CAST(SUBSTRING(@H2,CHARINDEX(':',@H2)+1,DATALENGTH(@H2))AS INT)

    INSERT INTO NewColumn -- Inserted new statement

    SELECT CAST(CAST(SUBSTRING(@H1,1,CHARINDEX(':',@H1)-1) AS INT)

    +CAST(SUBSTRING(@H2,1,CHARINDEX(':',@H2)-1)AS INT)

    +(@Min - (@Min%60))/60 AS VARCHAR(10))+':'+ CAST(@Min%60 AS VARCHAR(2))

    ]

    Thanks for your reply....however, this is not working for me, I get errors when I run your code...I will explain it more clearly....I have a column 'WeekHours' which has a datatype varchar and which stores values in the format '00:00'. I need to Sum all these values in the time format 'HH:MM'. For e.g. the values in the rows are-

    35:00

    35:30

    34:50

    32:25

    38:27

    I need to Sum all these values and store them so that the result for the above example shows as- 176:12 (HH:MM). Is the explanation more clear now ?

    I am really stuck with this and don't know how to proceed.

    Thanks.

  • Not sure if this example is any more efficient than the one provided by bitbucket but it is an alternate:

    DECLARE @times TABLE ([hh:mm]VARCHAR(12))

    INSERT INTO @times

    SELECT '115:32'

    UNION ALL SELECT '34:28'

    ;WITH Times AS (

    SELECT SUM(CAST(SUBSTRING([hh:mm], 1, CHARINDEX(':',[hh:mm])-1) AS INT)) as hh

    ,SUM(CAST(SUBSTRING([hh:mm], CHARINDEX(':',[hh:mm])+1, LEN([hh:mm])) AS INT)) as mm

    FROM @times

    )

    SELECT CAST(hh + mm/60 AS VARCHAR)+ ':' + RIGHT('00'+CAST(mm%60 AS VARCHAR),2)

    FROM Times


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • Could someone please have a look at my query, I am stuck with this one for a long time now...

    I have a column 'WeekHours' which has a datatype varchar and which stores values in the format '00:00'. I need to Sum all these values in the time format 'HH:MM'. For e.g. the values in the rows are-

    35:00

    35:30

    34:50

    32:25

    38:27

    I need to Sum all these values and store them so that the result for the above example shows as- 176:12 (HH:MM). Is the explanation more clear now ?

    I am really stuck with this and don't know how to proceed.

    Thanks.

  • You did say previously:

    Thanks for your reply....However, I have to create a new column based on this calculation and use that in a report. Your code is correct but I just want to know how do I replace @min-2 ?

    I explained that @min-2 was a "place holder" i.e. a variable to hold intermediate data.

    Now:

    Did you test the code posted by dwain.c?

    If yes what result(s) did you obtain ?

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • bitbucket-25253 (3/26/2012)


    You did say previously:

    Thanks for your reply....However, I have to create a new column based on this calculation and use that in a report. Your code is correct but I just want to know how do I replace @min-2 ?

    I explained that @min-2 was a "place holder" i.e. a variable to hold intermediate data.

    Now:

    Did you test the code posted by dwain.c?

    If yes what result(s) did you obtain ?

    Thanks Ron !

    actually I have created a query and this piece of code needs to be included within that. I don't know how to convert your code to include it within the query. The query is as below (your code is in bold):

    Select

    max(datepart(yyyy,s.[Date])) as [Year],

    /*

    CAST(SUBSTRING(WeekHours,CHARINDEX(':',WeekHours)+1,DATALENGTH(WeekHours))AS INT)+CAST(SUBSTRING(WeekHours,CHARINDEX(':',WeekHours)+1,DATALENGTH(WeekHours))AS INT)

    SELECT CAST(CAST(SUBSTRING(WeekHours,1,CHARINDEX(':',WeekHours)-1) AS INT)

    +CAST(SUBSTRING(WeekHours,1,CHARINDEX(':',WeekHours)-1)AS INT)

    +(WeekHours - (WeekHours%60))/60 AS VARCHAR(10))+':'+ CAST(WeekHours%60 AS VARCHAR(2)) as tt,

    */

    CONVERT(varchar(6), (sum((datepart(hour,Timenetin) * 3600)) + sum(datepart(minute,Timenetin) * 60) + sum(datepart(second,Timenetin))) / 3600) + ':' + RIGHT('0' + CONVERT(varchar(2),

    (sum((datepart(hour,Timenetin) * 3600)) + sum(datepart(minute,Timenetin) * 60) + sum(datepart(second,Timenetin))) % 3600 / 60), 2) + ':' + RIGHT('0' + CONVERT(varchar(2), (sum((datepart(hour,Timenetin) * 3600)) + sum(datepart(minute,Timenetin) * 60) +

    sum(datepart(second,Timenetin))) % 60), 2) as [Actual Hours],

    convert(varchar(10),((sum(datepart(hour,Timenetin) * 3600) + sum(datepart(minute,Timenetin) * 60) + sum(datepart(second,Timenetin) * 1)) - (25200* count(case when s.Dayname IN ('Mon', 'Tue','Wed', 'Thu', 'Fri') then 1 else 0 end)))/(3600)) As Hrs_Diff,

    convert(varchar(10),((sum(datepart(hour,Timenetin) * 3600) + sum(datepart(minute,Timenetin) * 60) + sum(datepart(second,Timenetin) * 1)) - (25200* count(case when s.Dayname IN ('Mon', 'Tue','Wed', 'Thu', 'Fri') then 1 else 0 end))) %(3600)/60) As Min_Diff,

    convert(varchar(10),((sum(datepart(hour,Timenetin) * 3600) + sum(datepart(minute,Timenetin) * 60) + sum(datepart(second,Timenetin) * 1)) - (25200* count(case when s.Dayname IN ('Mon', 'Tue','Wed', 'Thu', 'Fri') then 1 else 0 end))) %60) as Sec_Diff

    from StaffDay s

    inner join Staff st

    on s.Staff_id = st.Staff_id

    where s.Dayname NOT IN ('Sun','Sat')

    and s.Bank_holiday_flg = 'N'

    and datepart(mm,s.[Date]) IN ('01','02', '03','04','05','06','07','08','09','10','11','12')

    and datepart(yyyy,s.[Date]) = '2012' --IN (@Year)

    and st.active = 'Y'

    group by datepart(mm,s.[Date]) ,s.Cardholder_name

    order by datepart(mm,s.[Date]) asc

  • I have to ask... Why are you doing all of this conversion? Did you develop this app or dis someone else? Can you change the way data is stored? This is just plain poor design... So, if you can change it, so it. Else, I would use some type of ETL to copy this data to another table with a format that will work for you.

    Jared
    CE - Microsoft

  • pwalter83 (3/23/2012)


    Hi,

    I have a requirement to add columns (varchar) where data is separated with a colon (:). For e.g.

    115:32 and 34:28

    160:00 (hrs and minutes).

    Thanks,

    Paul

    Paul,

    For future posts, please see the article at the first link in my signature line below. It'll help us help you more quickly.

    First, we need some test data. I figure 1,000 different times will do. This is just test data and is not a part of the solution.

    --===== Conditionally drop the test table to make reruns in SSMS easier

    IF OBJECT_ID('TempDB..#YourTable','U') IS NOT NULL

    DROP TABLE #YourTable

    ;

    GO

    --===== Create a table with a column of VARCHAR times

    WITH

    cteGenHHHMM AS

    (

    SELECT TOP (1000)

    SomeDateTime = RAND(CHECKSUM(NEWID())) * 10 + CAST(0 AS DATETIME)

    FROM sys.all_columns ac1,

    sys.all_columns ac2

    )

    SELECT WeekHours = CAST(DATEDIFF(hh,0,SomeDateTime) AS VARCHAR(10)) + ':'

    + RIGHT(CONVERT(CHAR(8),SomeDateTime,108),2)

    INTO #YourTable

    FROM cteGenHHHMM

    ;

    --===== Show what we've created as a test table

    SELECT * FROM #YourTable

    ;

    Here's some relatively simple code to solve the problem.

    --===== Now show one way to sum all those Varchar times

    WITH

    cteToDateTime(DT) AS

    (

    SELECT DATEADD(mi,SUM(LEFT(WeekHours,CHARINDEX(':',WeekHours)-1)*60 + RIGHT(WeekHours,2)),0)

    FROM #YourTable

    )

    SELECT CAST(DATEDIFF(hh,0,DT) AS VARCHAR(10))

    + SUBSTRING(CONVERT(CHAR(8),DT,108),3,3)

    FROM cteToDateTime

    ;

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

Viewing 15 posts - 1 through 15 (of 52 total)

You must be logged in to reply to this topic. Login to reply