Database Migration, Comparision and Synchronization Tools
Got a SQL Server or .NET question? Discuss it in the forums. (SQL Server Forums | Dot NET Forums)
First Time? You can support us by signing up. It takes only 5 seconds. Click here to sign up. If you already have an account, click here to login.

Solution for Challenge #4

The goal for this challenge was to write the shortest possible code.

I know that the shortest code is not necessarily better performing code.

But nobody will argue that this challenge was a good exercise.

Here is my original solution for the Challenge #4.

select * from @t where ssn
like'[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]'and
not(ssn like'000%'or ssn like'%-00-%'or ssn like'%0000'or
ssn
like'666%'or ssn>'772'or(ssn>'734'and ssn<'750'))

This is reformatted version to make the code more readable:

SELECT *

FROM @t

WHERE

    ssn LIKE '[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]'   --#1

    AND NOT (    ssn LIKE '000%'                           --not #5

                OR ssn LIKE '%-00-%'                       --not #5

                OR ssn LIKE '%0000'                        --not #5

                OR ssn LIKE '666%'                         --not #4

                OR ssn > '772'                             --not #3

                OR ( ssn > '734' AND ssn < '750'        --not #2

           )

I'm going to reference the validation rules by their numbers in the Challenge #4 description.

The key to this solution was to use not numerical but textual comparisons.

It allowed shortening the code because for numerical comparisons we would need some logic to tokenize SSN into 3 digital groups.

For rule #1 I use the expression

    ssn like'[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]'

that excludes all ssn values that aren't in the format of XXX-XX-XXXX where each X represents a digit.

The wild card [0-9] corresponds to any digit in a range from 0 to 9.

This validation can be expressed even a bit shorter using the approach from Antoine Gémis's solution to this challenge:

    ssn like replace('XXX-XX-XXXX','X','[0-9]')

For #2 I relied on a fact that in a textual comparison any string that is lengthier than 3 characters and starts with group of 3 digits between 734 and 749 is greater than string '734' and less than string '750'

#3 I translated as ssn shouldn't start with a string greater than '772'

#4 I translated as ssn shouldn't start with the string '666'

After format check of XXX-XX-XXXX is applied we can validate rule #5 using % wild card:

   ssn LIKE '000%'        -- excludes ssn that starts with 000  

OR ssn LIKE '%-00-%'      -- excludes ssn that contains -00-                      

OR ssn LIKE '%0000'       -- excludes ssn that ends with 0000              

Validation rule #3 is more restrictive than the rule #6, so if we validate #3 we can omit the check on #6.

Instead of using expression pattern "not like exp1 and not like exp2 and not like..." I used "not (like exp1 or like exp2 or like...)".

It allowed to avoid repetitive "and not"s and as a result make the code shorter.

We can make it a bit shorter removing parenthesis around (ssn>'734' AND ssn<'750') as Pinal Dave did in his solution to this challenge.

Combining all 3 winning solutions I would rewrite the code as the following:

select * from @t where ssn like REPLACE('XXX-XX-XXXX','X','[0-9]')and not(ssn like'000%'or ssn like'%-00-%'or ssn like'%0000'or ssn like'666%'or ssn>'772'or ssn>'734'and ssn<'750')

 

If you like this article,  Subscribe in a reader or Subscribe by Email. Show your support by sharing this article with your friends through the services given below.

Share

Comments

# re: Solution for Challenge #4

Monday, May 11, 2009 11:23 PM by Cleber

Hi Leonid, I saw about this site on Pinal's blog (thanks Pinal, as I said, lot of good stuff on yours...) Well, this is my first comment but you will see me around, back to business, two extra bytes to save on the shortest solution you got, the "*" doesn't need spaces around it. Thanks for spending time helping us, the cusious amateurs, to understand it better.

-Cleber

# re: Solution for Challenge #4

Thursday, May 14, 2009 2:00 PM by Leonid Koyfman

Hi Cleber,

Thank you for the tip about "*".

I didn't know it would work.

Thanks to this site we all can learn something new.

Using "*" reminded me about other, more practical trick I'd like to share.

Instead of "count(*)" in queries I use "count(9)".

It doesn't have to be "9", just any digit.

But it's easier to type "9" because "(" and "9" are on the same key.

It works in ORACLE as well.

-LK-

Copyright © Beyondrelational.com