Finding Max Value from a 4-character Date String

  • Hi all,

    Somewhat of an odd question maybe, but it makes sense given my context

    I have a table which contains dates that are stored as an MMYY string, for example, "0812" would be "2012-08-01".

    I need to find the max date from a collection of records that contain these strings.

    So here's the sample data and such:

    CREATE TABLE #TestValues

    (

    ID INT IDENTITY PRIMARY KEY,

    SomeValue INT,

    FourCharDate CHAR(4)

    )

    INSERT INTO #TestValues (SomeValue, FourCharDate)

    SELECT 1, '0812'

    UNION ALL

    SELECT 1, '0912'

    UNION ALL

    SELECT 1, '1012'

    UNION ALL

    SELECT 1, '0915'

    UNION ALL

    SELECT 1, '1012'

    UNION ALL

    SELECT 2, '0711'

    UNION ALL

    SELECT 2, '0501'

    UNION ALL

    SELECT 2, '0586'

    UNION ALL

    SELECT 2, '0512'

    UNION ALL

    SELECT 3, '0752'

    UNION ALL

    SELECT 3, '0812'

    UNION ALL

    SELECT 3, '0812'

    SELECT * FROM #TestValues

    IDSomeValueFourCharDate

    110812

    210912

    311012

    410915

    511012

    620711

    720501

    820586

    920512

    1030752

    1130812

    1230812

    And here's my solution. Just wondering if anyone has a better solution, since mine looks kinda ugly:

    SELECT

    SomeValue,

    RIGHT(MAX(CAST(RIGHT(FourCharDate, 2) AS INT) * 100 + CAST(LEFT(FourCharDate, 2) AS INT)), 2) + RIGHT('0' + LEFT(MAX(CAST(RIGHT(FourCharDate, 2) AS INT) * 100 + CAST(LEFT(FourCharDate, 2) AS INT)), 2), 2) AS FourCharDate

    FROM #TestValues

    GROUP BY SomeValue

    SomeValueFourCharDate

    10915

    20586

    30752

  • Since your working with what is essentially just text anyway, just continue treating it as text and do the following:

    SELECT MAX(RIGHT(FourCharDate,2) + LEFT(FourCharDate,2)) FROM #TestValues

    Result (from your sample data) is 8605, which is correct, (unless that was supposed to be May of 1986?). As long as your data is consistently in the MMYY format, this should work. If you need to add the century, it is only slightly more complicated: determine your cutoff year and prepend either '19' or '20' based on the value of the the rightmost two characters.

    Rob Schripsema
    Propack, Inc.

  • Hm. So you're using the max of a string value. That works in all cases? Hadn't thought about trying that, 'cause I wasn't sure how SQL Server handles taking the max value from strings.

    I guess it would do a character-by-character comparison, using ASCII values? So, ASCII('9') is greater than ASCII('8'), etc..., then compare each character.

    How does it do for performance though?

  • kramaswamy (8/29/2011)


    Hm. So you're using the max of a string value. That works in all cases? Hadn't thought about trying that, 'cause I wasn't sure how SQL Server handles taking the max value from strings.

    I guess it would do a character-by-character comparison, using ASCII values? So, ASCII('9') is greater than ASCII('8'), etc..., then compare each character.

    How does it do for performance though?

    Yes, it will work in all cases -- as long as you can confirm that you'll always have the four character MMYY format in your source data.

    I can't vouch for exactly how SQL does a compare on strings, but I've always found speed to be no problem. I'm pretty certain that CASTing the string value to an integer is a more expensive operation than a string compare, in any case.

    Rob Schripsema
    Propack, Inc.

  • How about this?

    ; WITH CharsConvertedToDate AS

    (

    SELECT ID , SomeValue , FourCharDate ,

    RN = ROW_NUMBER() OVER ( PARTITION BY SomeValue ORDER BY CAST ( '01-'+STUFF(FourCharDate , 3, 0,'-' ) AS DATETIME) DESC)

    FROM #TestValues

    )

    SELECT SomeValue , FourCharDate

    FROM CharsConvertedToDate

    WHERE RN = 1

  • ColdCoffee (8/29/2011)


    How about this?

    ; WITH CharsConvertedToDate AS

    (

    SELECT ID , SomeValue , FourCharDate ,

    RN = ROW_NUMBER() OVER ( PARTITION BY SomeValue ORDER BY CAST ( '01-'+STUFF(FourCharDate , 3, 0,'-' ) AS DATETIME) DESC)

    FROM #TestValues

    )

    SELECT SomeValue , FourCharDate

    FROM CharsConvertedToDate

    WHERE RN = 1

    This depends on the localization settings of the computer. If you're going to go that route, you should use CONVERT rather than CAST so that you can specify the date format. You can also simplify it--since you need to specify the date format anyhow--by using one of the US formats.

    CONVERT(datetime, Stuff(FourCharDate, 3, 0, '/01/'), 101)

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • I'd considered CONVERTing to a date, but I figured that doing a date conversion and then comparison would be more expensive than leaving it as an INT.

    Thanks for the input though, all - comparing the INT version I had with the string version posted by Rob yielded roughly the same amount of time for calculation, so I've left it as INT to avoid changing code

Viewing 7 posts - 1 through 6 (of 6 total)

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