0

I have a requirement from my customer. Data pattern is below for Note Column

:TT:  12:32,12:35  :TT:

:TT:  05:17,05:30  :TT:

:TT:  01:56,02:00  :TT:

:TT:  01:00,01:12  :TT:

I need to remove :TT: tag and subtract first value from last. for example 12:35-12:32=00:03.

I have applied below code

WITH CTE1 AS
(
    SELECT (LTRIM(RTRIM(REPLACE(CAST(Note as NVarchar(4000)),':tt:','')))) AS Note 
    FROM UD_Notes 
    WHERE Note like ':t%'
)
SELECT Note FROM CTE1

Now getting below result-

  01:00,01:12  
  01:56,02:00  
  05:17,05:30  
  12:32,12:35 

Can anyone help me out for solve this?

Muqo
  • 414
  • 7
  • 15
Nishant
  • 74
  • 2
  • 10

9 Answers9

2

i have a solution that will give you something like this:
3
13
4
12

Note: Updated it with DATEDIFF

    WITH CTE1 AS
    (
        SELECT (LTRIM(RTRIM(REPLACE(CAST(Note as NVarchar(4000)),':tt:','')))) AS Note 

        FROM UD_Notes  
        WHERE Note like ':t%'
    )
    SELECT  Note INTO #RESULT FROM CTE1


    SELECT        
    DATEDIFF(MINUTE, CONVERT(datetime, left(CONVERT(varchar(50), LEFT(Note, CHARINDEX(',', Note) - 1)), 19)), CONVERT(datetime, left(CONVERT(varchar(50), RIGHT(Note, CHARINDEX(',', Note) - 1)), 19)))
    FROM #RESULT

I have tested it like this:

        CREATE TABLE #PRERESULT(
        Note text)

        INSERT INTO #PRERESULT (note)
        VALUES
        (':TT: 12:32,12:35 :TT:'),
        (':TT: 05:17,05:30 :TT:'),
        (':TT: 01:56,02:00 :TT:'),
        (':TT: 01:00,01:12 :TT:');


           WITH CTE1 AS
            (
                SELECT (LTRIM(RTRIM(REPLACE(CAST(Note as NVarchar(4000)),':tt:','')))) AS Note 

                FROM #PRERESULT  
                WHERE Note like ':t%'
            )
            SELECT  Note INTO #RESULT FROM CTE1


            SELECT 
            DATEDIFF(MINUTE, CONVERT(datetime, left(CONVERT(varchar(50), LEFT(Note, CHARINDEX(',', Note) - 1)), 19)), CONVERT(datetime, left(CONVERT(varchar(50), RIGHT(Note, CHARINDEX(',', Note) - 1)), 19)))
            FROM #RESULT

        DROP TABLE #PRERESULT
        DROP TABLE #RESULT

Have a nice day

Etienne

Tienou
  • 700
  • 6
  • 17
  • Msg 241, Level 16, State 1, Line 1 Conversion failed when converting date and/or time from character string. – Nishant Jun 02 '14 at 11:13
  • CONVERT(datetime,Convert(nvarchar(50),RIGHT(Note, CHARINDEX(',', Note) - 1))) -CONVERT(datetime,Convert(nvarchar(50),LEFT(Note, CHARINDEX(',', Note) - 1))) Try this – Tienou Jun 02 '14 at 11:15
  • Getting same Same Error GOB – Nishant Jun 02 '14 at 11:19
  • See above how I tested it, it works like that. I can't tell the difference – Tienou Jun 02 '14 at 11:28
  • Conversion from Text to Datetime: CONVERT(datetime, left (CONVERT(varchar(50), @Field), 19)) – Tienou Jun 02 '14 at 11:36
  • Try: DATEDIFF(MINUTE, CONVERT(datetime, left(CONVERT(varchar(50), LEFT(Note, CHARINDEX(',', Note) - 1)), 19)), CONVERT(datetime, left(CONVERT(varchar(50), RIGHT(Note, CHARINDEX(',', Note) - 1)), 19))) – Tienou Jun 02 '14 at 11:39
  • My Note Field is TEXT that might be problem GOB – Nishant Jun 02 '14 at 11:44
  • Try out my code where it says: "I have tested it like this:" It works there with Text-datatype – Tienou Jun 02 '14 at 11:56
1

Try this:

select 
right('00'+cast(cast(substring(ltrim(rtrim(replace(cast(Note as nvarchar(100)),':TT:',''))),7,2) as int) - cast(substring(ltrim(rtrim(replace(cast(Note as nvarchar(100)),':TT:',''))),1,2) as int) as varchar),2) 
+ ':' 
+ right('00'+cast(cast(substring(ltrim(rtrim(replace(cast(Note as nvarchar(100)),':TT:',''))),10,2) as int) -  cast(substring(ltrim(rtrim(replace(cast(Note as nvarchar(100)),':TT:',''))),4,2) as int) as varchar),2)
from ud_notes where note like ':t%'

Breakdown:

  1. Replace ':TT:' with blanks.
  2. Trim the string to remove unnecessary spaces.
  3. Since the strings represent time as HH:MM, we can safely assume that the resulting substring will always be of the form xx:xx,xx:xx and of length 11. So, we can hardcode the indices where we get the substrings representing hours and minutes for start and end times.
  4. Cast the strings to integers and perform the subtraction.
  5. Pad with the necessary amount of zeros.
  6. Concatenate with a separator to return the expected output as varchar.
shree.pat18
  • 21,449
  • 3
  • 43
  • 63
1

You can use an scalar user defined function that receives the string (even the whole string including the ':TT:'), and process it to give you back the desired result.

In this way you can reuse it and test it easyly.

Somethign like this:

CREATE FUNCTION dbo.TimeDiff(@value AS nvarchar(4000))
RETURNS NVARCHAR(5)
AS
BEGIN
    DECLARE @cleaned NVARCHAR(11)
    SET @cleaned = LTRIM(RTRIM(REPLACE(@value,':TT:','')))
    DECLARE @h1 int
    DECLARE @m1 int
    DECLARE @h2 int
    DECLARE @m2 INT
    DECLARE @t1 INT
    DECLARE @t2 int  
    SET @h1 = CAST(SUBSTRING(@cleaned,1,2) AS int)
    SET @m1 = CAST(SUBSTRING(@cleaned,4,2) AS int)
    SET @h2 = CAST(SUBSTRING(@cleaned,7,2) AS int)
    SET @m2 = CAST(SUBSTRING(@cleaned,10,2) AS int)
    SET @t1 = @h1 * 60 + @m1
    SET @t2 = @h2 * 60 + @m2
    DECLARE @diff INT
    DECLARE @diffh NVARCHAR(2)
    DECLARE @diffm NVARCHAR(2)
    SET  @diff = @t1 - @t2
    SET @diffh = RIGHT('0' + CAST(@diff / 60 AS NVARCHAR(2)),2)
    SET @diffm = RIGHT('0' + CAST(@diff % 60 AS NVARCHAR(2)), 2)
    RETURN @diffh + ':' + @diffm
END

And you can test it like this:

 SELECT dbo.TimeDiff(':TT: 12:23,11:54 :TT:')

Then you can easily use this function in your select sentences. Of course, you can modify the implementation to make it more efficient, or modify the details of the calculation.

JotaBe
  • 38,030
  • 8
  • 98
  • 117
1

Test Data

DECLARE @TABLE TABLE (Note TEXT)
INSERT INTO @TABLE VALUES 
(':TT:  12:32,12:35  :TT:'),
(':TT:  05:17,05:30  :TT:'),
(':TT:  01:56,02:00  :TT:'),
(':TT:  01:00,01:12  :TT:')

Query

;WITH CTE1 AS
(
    SELECT  CAST(REPLACE(LEFT(Note, CHARINDEX(',', Note) -1),':tt:','') AS TIME) AS StartTime
           ,CAST(SUBSTRING(Note, CHARINDEX(',', Note)+ 1, 5) AS TIME)     AS  EndTime
    FROM (SELECT CAST(Note AS VARCHAR(1000)) AS Note FROM @TABLE) A
    WHERE Note like ':t%'
)
SELECT CAST(StartTime AS NVARCHAR(5)) AS StartTime
      ,CAST(EndTime AS NVARCHAR(5))   AS EndTime
      ,DATEDIFF(MINUTE, StartTime,EndTime) TimeDifference
FROM CTE1

Result Set

╔═══════════╦═════════╦════════════════╗
║ StartTime ║ EndTime ║ TimeDifference ║
╠═══════════╬═════════╬════════════════╣
║ 12:32     ║ 12:35   ║              3 ║
║ 05:17     ║ 05:30   ║             13 ║
║ 01:56     ║ 02:00   ║              4 ║
║ 01:00     ║ 01:12   ║             12 ║
╚═══════════╩═════════╩════════════════╝

Working SQL FIDDLE

M.Ali
  • 67,945
  • 13
  • 101
  • 127
  • Argument data type text is invalid for argument 1 of left function. – Nishant Jun 02 '14 at 11:22
  • @Nishant Have a look now you should have provided this information in your question. Anyway all you need to do is to convert it to varchar/nvarchar data type is it should work as it is. See my update. – M.Ali Jun 02 '14 at 11:57
1

Hi Nishant try this one:

select DATEDIFF(MI,SUBSTRING(REPLACE(Note,':TT:',''),  
    charindex('',REPLACE(Note,':TT:','')),  
    charindex(',',REPLACE(Note,':TT:',''))),  
    SUBSTRING(REPLACE(Note,':TT:',''),  
    charindex(',',REPLACE(Note,':TT:',''))+1,  
    len(REPLACE(colval,':TT:',''))-charindex(',',REPLACE(Note,':TT:',''))))  

from UD_Notes

enter image description here

Bjarke Freund-Hansen
  • 28,728
  • 25
  • 92
  • 135
knkarthick24
  • 3,106
  • 15
  • 21
1

If you want to get results in hh:mi format:

SELECT
    CONVERT(VARCHAR(5), DATEADD(minute, DATEDIFF(minute, LEFT(LTRIM(REPLACE(CONVERT(VARCHAR(8000), Note), ':TT:', '')), 5), RIGHT(RTRIM(REPLACE(CONVERT(VARCHAR(8000), Note), ':TT:', '')), 5)), 0), 14)
FROM
    UD_Notes
WHERE
    PATINDEX(':T%', Note) > 0

Explanation: Extract the left and right time strings. Implicitly convert the strings to time data while getting the integer difference in minutes. Convert the resulting integer to hh:mi.

Muqo
  • 414
  • 7
  • 15
1
select cast(dateadd(minute, 
                    datediff(minute, 
                            substring(Note, 7, 5), 
                            substring(Note, 13, 5)
                           ),
                    0) as time(0))

Result:

00:03:00
00:13:00
00:04:00
00:12:00

SQL Fiddle

Mikael Eriksson
  • 136,425
  • 22
  • 210
  • 281
1

It's taken me a while, and I'll be this isn't the most efficient way of doing it (too many conversions), but I have an XML solution working which someone might be able to improve on. Note that since you are dealing with times I have used Date functions - but make sure you read the caveat at the end. Basically, in your CTE you convert the data to simple XML form like

<Note>
    <T1>00:00</T1>
    <T2>00:00</T2>
</Note>

This takes away the need to do string splitting functions. Now you can get your result by using a combination of DATEDIFF, DATEADD, CAST and LEFT

 WITH CTE1 AS
(
    SELECT CAST('<Note><T1>' + REPLACE((LTRIM(RTRIM(REPLACE(CAST(Note AS NVARCHAR(4000)),
         ':tt:','')))), ',', '</T1><T2>') + '</T2></Note>' AS XML) AS Note 
    FROM UD_Notes 
    WHERE Note like ':t%'
)


SELECT LEFT(CAST(DATEADD(mi, DATEDIFF(mi, CAST(y.T1 AS TIME), CAST(y.T2 AS TIME)), CAST('00:00' AS TIME)) AS VARCHAR(20)), 5)
FROM (
  SELECT c.value('(T1/text())[1]', 'varchar(50)') AS T1, 
        c.value('(T2/text())[1]', 'varchar(50)') AS T2
FROM  (SELECT Note FROM CTE1) x
CROSS APPLY Note.nodes('/Note') AS T(c)) y

What's happening is that first we get the CTE to give us an XML data type which we can then query to give us two 'columns' (T1 and T2). The SELECT is doing a lot of jobs at once so I'll break it down. Lets assume the example you gave which was 12:35 - 12:32 = 00:03.

DATEDIFF(mi, CAST(y.T1 AS TIME), CAST(y.T2 AS TIME))

Here we get the two columns T1 and T2 and we CAST those to the TIME type and get the difference (i.e. T2 - T1). This gives us an INT difference of 3 so in the next bit I'll simply substitute 3 into the relevant part.

So, now we get

DATEADD(mi, 3, CAST('00:00' AS TIME))

What we're doing here is creating a notional TIME of 00:00 and adding our difference to it in minutes (mi) so this gives us 00:03. Once again, we'll substitute it in.

CAST(00:03 AS VARCHAR(20))

Pretty simple here, we're just getting a VARCHAR representation of our time. Because TIME has a pretty good accuracy, we get the seconds and nanoseconds which would look like this 00:03:00.0000000. We want rid of the seconds and nanoseconds since we're dealing with hours and minutes here.

LEFT('00:03:00.0000000', 5)

That leaves us with '00:03' as a string.

I won't bother going through the body of the query because although I can write it I don't think I could explain it quite clearly enough but there's plenty of pages that will explain XML querying far better than I can such as this blog post from MSDN and this blog post which looks at querying XML fields in t-sql.

I have no doubt there's a better way to do this and someone on here can also give a good explanation of the query - please feel free anyone to add to this and explain what I struggle to.

CAVEAT

If T1 was 01:00 and T2 was 12:57 then you would get an answer of 11:57 because they are indeed 11 hours and 57 minutes apart in the forward direction. To be honest I haven't got time now to work out how to make this give you a result of 3 for those two times, but someone else probably can spot how to, I hope.

Steve Pettifer
  • 1,975
  • 1
  • 19
  • 34
  • Thanks for providing detailed approach steve.but I am getting below error -Conversion failed when converting date and/or time from character string. – Nishant Jun 02 '14 at 13:13
  • No worries. There's lots of options being presented but I felt it might be worth adding this for completeness as it is another possible avenue. Good luck! – Steve Pettifer Jun 02 '14 at 13:14
  • i am using SQL server 2008R2 – Nishant Jun 02 '14 at 13:16
  • Well it will work on that for sure - that's what I used. Just might not necessarily be the best solution for you - you have a few to choose from! – Steve Pettifer Jun 02 '14 at 13:21
0

Well all answers were quite correct and I have to choose in one of them. Unfortunately i was getting blanks spaces in result set because of those blank spaces I was getting error of conversion (varchar to time). I have overcome problem by below query and it is working for me right now. Thanks all senior members and experts to providing me their valuable inputs. I got right approach to get my desired result.

{    
SELECT 
CONVERT(VARCHAR,DATEDIFF(mi,
CAST(SUBSTRING(REPLACE(CAST(Note AS VARCHAR(1000)),':TT:',''),CHARINDEX(':',REPLACE(CAST(Note AS VARCHAR(1000)),':TT:',''))-2,CHARINDEX(':',REPLACE(CAST(Note AS VARCHAR(1000)),':TT:',''))) AS TIME)
,CAST(SUBSTRING(REPLACE(CAST(Note AS VARCHAR(1000)),':TT:',''),CHARINDEX(',',REPLACE(CAST(Note AS VARCHAR(1000)),':TT:',''))+1,5) AS Time))) + ' mins' As 'TimeDiff'
 FROM UD_Notes where Note like '%:TT:%'    }
Nishant
  • 74
  • 2
  • 10