SQL SERVER – Puzzle with MONTH Function – Win USD 50 Amazon Gift Card

It has been a while since we ran the contest. I reached out to kind team of Embarcadero and they agreed to support the next contest. The contest has two steps and they are very simple. It took me a while to build contest, but it is a really fun one. I am very confident that once you try out the contest, you will love it.

Two Giveaways:

SQL SERVER - Puzzle with MONTH Function - Win USD 50 Amazon Gift Card amazon-gift-cards

(Global) USD 50 Amazon Gift Card to 1 Individual

(India) INR 2500 Flipkart Gift Card to 1 Individual

Contest 1: T-SQL

Run following T-SQL script and observe the answer:

SELECT MONTH(18/200), MONTH(200/18)

SQL SERVER - Puzzle with MONTH Function - Win USD 50 Amazon Gift Card monthcontest

When we look at the answer, it displays 1 as a answer to both of the expression. The question is why does above script return values as 1 instead of throwing an error or displaying any error?

Contest 2: Download and Install DBArtisan

This is the easy part of the contest. You just have to download and install DBArtisan. You can download DBArtisan from here.

How to Participate?

  • Leave an answer for contest 1 in the comment section of the blog.
  • Leave a comment with the same email address which you have used to download DBArtisan.
  • The contest is open till June 2nd, 2015 Midnight PST.
  • The winner will be announced on June 4nd, 2015.
  • There will be two winners 1) Global 2) India.
  • All the correct answer to the contest will be hidden till the winner is announced.

Reference: Pinal Dave (https://blog.sqlauthority.com)

Embarcadero
Previous Post
SQL SERVER – Antivirus Exclusions Best Practices With SQL Server
Next Post
SQL SERVER – Adding Reference Data to Master Data Services – Notes from the Field #081

Related Posts

309 Comments. Leave new

  • Jaydeep Galiya
    May 21, 2015 5:04 pm

    Select month(18,200),month(200/18) giving 1 value because first of all it did 200/18 that results 11.11 so from that SQL server taking integer value that is 11. So till now it shows 11 days in month function. Now Query becomes select month(11) so in that 11 days must be divide by 30 for evaluate month. So after that 11/30 outputs 0.so at last the month will show 1 because in that function it output upper limit of that month.So finally output comes 1 and it does not throw any exception.

    Reply
  • Shivakumar Durg
    May 21, 2015 6:32 pm

    SELECT MONTH((18/200)%365), MONTH((200/18)%365)

    Reply
  • ritesh meehr
    May 21, 2015 6:53 pm

    SELECT MONTH(18/200), 18/200 evaluates to 0 as date parameter which is base month. hence the result 1.
    SELECT MONTH(200/18), 200/18 evaluates to 1 as date parameter which is the first month of the base year.
    [email address]

    Reply
  • Hi Pinal,

    After thinking on it i have found the logic behind it.

    By default SQL Server has Date : 01/01/1900

    So now if I pass 0 as argument in above function it will return 1 value. Logic i Found for month is below.

    Declare @a int=200
    Declare @b int=18
    Declare @C int=@a/@b
    Declare @SupposeDate date

    set @SupposeDate= Dateadd(day,@c,’01/01/1900′)

    Select Month(@SupposeDate),Month(@c)

    SQL Server add that number of days in ’01/01/1900′ that we have passed and than check the month of that date and it will return as an output.

    That is what I am thinking. Please let me know your feedback.

    Thanks & Regards,
    Rikhil

    Reply
    • Hi Pinal ,
      I am seeing my comment status is under waiting for moderation? I posted it yesterday. Why it is taking too long time to update?

      Reply
  • rogge heflin
    May 21, 2015 9:43 pm

    18/200 = 11; 200/18 = 0; when one execute MONTH(typeof(int)), then the “date” used is the number of days date from 1900-01-01, where Jan. 1 = 0 and Jan. 31 = 30, and Feb. 1 = 32.
    rogge

    Reply
  • rogge heflin
    May 21, 2015 9:46 pm

    addendum… and oops Feb 1= 31… so MONTH(31) = 2.

    Reply
  • We need to look at the number of days added to 1900-01-01 after performing the division operation for the numbers provided in braces i.e 18/200 = 0 and 200/18 = 11and the way it works is as follows.
    Select MONTH(18/200) = Select MONTH(0)= Select MONTH(dateadd(dd,0,0)) = Select MONTH(dateadd(dd,0,’1900-01-01′))
    Select MONTH(200/18) = select MONTH(11) = Select month(dateadd(dd,11,0))= Select MONTH(dateadd(dd,11,’1900-01-01′))

    Reply
  • Arun Gopinath
    May 21, 2015 11:25 pm

    Is it because dayofyear (200/18)=11 is updated to 12 as day 1-1-1900 starts with zero index,so it month(12th jan 1900). similarly 18/200 is 1 month(1st jan 1900) both returns jan whose integer value is 1

    Reply
  • Hi Pinal,

    Answer for T-SQL contest is as below.
    SELECT MONTH(18/200), MONTH(200/18)

    MONTH(18/200)
    —————————
    First it evaluates 18/200 which is 0, so query becomes MONTH(0)
    In SQL Server argument 0 in MONTH(0) is considered to January 1 1990.
    So answer is 1 because it is first month.

    MONTH(200/18)
    ———————————–
    First 200/18 is evaluated as 11.
    argument in MONTH(11) is same as above considered to be the date of first month, so answer is 1

    Reply
  • pampushet S. Awasare
    May 22, 2015 10:09 am

    if we trying to convert any integer value into date time SQL server always consider date “01/01/1900 00:00:00” .. SELECT CONVERT(DATETIME, 2)

    Reply
  • what it do is trying to convert (200/18) to datetime value like this:
    select CONVERT (datetime,(18/200)) —>>>1900-01-01 00:00:00.000
    select CONVERT (datetime,(200/18)) —>>>1900-01-12 00:00:00.000

    then it Extract the month from that date ,,,which is January in both cases

    Reply
  • Manjunath Chowdary
    May 22, 2015 12:18 pm

    Hi Pinal,

    The 18/200 or 200/18 results an integer value. this resultant in turn is treated as time part by the month function and hence the default is returned as 1. If date contains only a time part, the return value is 1, the base month.

    Reply
  • Hello Pinal,

    Following is my response:

    CASE OF: ‘SELECT MONTH(18/200)’
    The argument in Month function represents ‘Date’ in ‘int’ format. 18/200 gives zero as integer value, thus the expression becomes Month(0) & SQL Server interprets 0 as January 1, 1900. Therefore, it returns 1 which is January.

    Further, it is interesting to note that any date/datetime in SQL Server can be represented in integer format. Have a look at the following:
    select cast(0 as datetime) — returns ‘1900-01-01 00:00:00.000’
    select cast(cast(0 as datetime) as datetime) — returns ‘1900-01-01 00:00:00.000’
    select month(cast(0 as datetime)) — returns 1
    select month(cast(cast(0 as datetime) as datetime)) –returns 1

    So, effectively integer 0 represents ‘1900-01-01 00:00:00.000’, hence MONTH(18/200)==MONTH(0)==MONTH(‘1900-01-01 00:00:00.000’) returns 1 which is January.

    CASE OF: ‘SELECT MONTH(200/18)’
    Similarly, MONTH(200/18)=MONTH(11)==MONTH(‘1900-01-12 00:00:00.000’) returns 1 which is January again.
    select cast(11 as datetime) — returns ‘1900-01-12 00:00:00.000’
    select cast(cast(11 as datetime) as datetime) — returns ‘1900-01-12 00:00:00.000’
    select month(cast(11 as datetime)) — returns 1
    select month(cast(cast(11 as datetime) as datetime)) –returns 1

    @Pinal: Your posts are always a delight to read before starting my day. They are short, spot-on & serve as a new learning everyday. Your recent posts of ‘PowerShell script’ and ‘net helpmsg’ were also very helpful, they come handy during production issues.

    The above question was equally interesting to solve.

    Thanks for sharing your knowledge!

    Regards!

    Reply
  • RAM KRIPAL SINGH
    May 22, 2015 2:19 pm

    In SQL Server, The Month() method takes date as input parameter and returns month of the entered date. However when an integer value is passed to this function, it counts the number of days starting from 1900-01-01 00:00:00.000 and returns the month of it.

    Hence when 18/200 is passed it returned one ie it converted it to value1900-01-01 00:00:00.000 and returned 1. Similarly when 200/18 is passed, the same is converted to 1900-01-12 00:00:00.000 and the method again returns one.

    PS: run select cast(18/200 as datetime) for an example.

    Kind regards,
    Ram Kripal Singh.

    Reply
  • In SQL Server, The Month() method takes date as input parameter and returns month of the entered date. However when an integer value is passed to this function, it counts the number of days starting from 1900-01-01 00:00:00.000 and returns the month of it.

    Hence when 18/200 is passed it returned one ie it converted it to value1900-01-01 00:00:00.000 and returned 1. Similarly when 200/18 is passed, the same is converted to 1900-01-12 00:00:00.000 and the method again returns one.

    Reply
  • select 18/200, 200/18 will return 0 and 1.

    Month functions takes input a date and it implicitly converts 0 and 1 as datetime
    and deafault starting value as 1900-01-1 00:00:00.000 and 1900-01-12 00:00:00.000
    respectively.

    SELECT Month(0), Month(1) —
    After applying month function will return month part as 1, 1

    Reply
  • If date contains only a time part, the return value is 1, the base month.
    It assumes that results of the division – integer- as time part.

    Reply
  • Sanjay Kumar
    May 22, 2015 6:34 pm

    The result of the expression 18/200 and 200/18 results to 0 & 11 respectively. The integer value gets added to 1900-01-01 when applied with a date related function i.e. Month. Basis the above results it’ll result into 1900-01-01 and 1900-01-12 respectively. Since the month value for both the dates is 1 hence Month functions returns the result as 1 for both the expressions.
    Hope the answer clarifies the fact behind this…

    Reply
  • Mauricio Jarquin
    May 22, 2015 7:56 pm

    —–The Question ? –Why returns 1, 1
    SELECT MONTH(200/18),MONTH(18/200)
    –Declaring a date variable and a Character Variable
    DECLARE @TodayDate DATETIME, @StringDate VARCHAR(20)
    –Getting date
    SET @TodayDate=GETDATE()
    — converting @TodayDate to get time time part
    SET @StringDate=CONVERT(VARCHAR(10),@TodayDate,108)
    –Printing today variable
    SELECT @TodayDate
    –printing the conversion
    SELECT @StringDate

    –printing the return of MONTH() from a complete date variable
    SELECT MONTH(@TodayDate)
    –printint the return of MONTH() from time part variable
    –SQL interprets the time portion. If the date contains only a time part, the return value is 1, the base month.
    SELECT MONTH(convert(DATETIME, @StringDate,103))
    –regards,
    —-Mauricio Jarquin (Nicaragua) [email removed]

    Reply
  • Mohammed khan
    May 22, 2015 9:17 pm

    Month function get date as a value, in this case it assuming it is a time part only thus it returning base month.

    Reply

Leave a Reply