Unexpected Shorthand Date Implicit Conversions

Published on: 2018-10-23

I do my best work in the mornings.  Evenings are pretty good too once I get a second wind.

Late afternoon are my nemesis for getting any serious technical or creative work done.  Usually I reserve that time for responding to emails, writing documentation, and brewing coffee.

Some afternoons I can’t help myself though and end up getting myself into trouble.

What is THAT!?

It all started when I was troubleshooting an existing query that was having issues.  During the process of trying to understand what the query was doing, I happened to look at the execution plan:

Simplified, but you get the point.

When I hovered over the Table Scan, the Predicate section caught my eye.  Specifically, I wondered “Why is 1900-01-31 showing up? I don’t have that anywhere in my query!

(fun side story: the real query I was working on was dealing with user-defined datatypes, something I don’t have experience with, so I thought those had something to do with the problems I was experiencing.  I latched onto this 1900 date as the potential cause but it ended up being a red herring!)


Like I mentioned, late afternoons are not when I do my best work.  I couldn’t figure out why SQL Server was converting my -30 to January 31, 1900.

Intrigued and having no clue what was going on, I decided to post the question with the #sqlhelp hashtag on Twitter.  Fortunately for me, Aaron Bertrand, Jason Leiser, and Thomas LaRock all came to the rescue with ideas and answers – thanks guys!

Implicit Conversion

In hindsight, the answer is obvious: the -30 implicitly converts to a datetime (the return type of my @Today variable), in this case 30 days after the start of the minimum datetime value, 1900-01-01.

This makes perfect sense: SQL Server needs to do some math and in order to do so it first needs to make sure both datatypes in the equation match.  Since int readily converts to datetime but not the other way around, SQL Server was just doing its job.

Future Problems

As I mentioned earlier, this int to datetime conversion wasn’t the actual issue with my query – in my drowsy state I mistook it as being the source of my problem.

And while it wasn’t a problem this time, it can become a problem in the future.

Aaron has an excellent article on the problems with shorthand date math, but the most relevant future issue with my query is: what if someone in the future decides to update all datetimes to datetime2s (datetime2 being Microsoft’s recommended datatype for new work)?

If we update to a datetime2s and run the query again:

Everything is broken

AHHH!  While SQL Server had no problem converting our previous code between datetime and int, it’s not so happy about converting datetime2.


In the end, the above scenario had nothing to do with the actual problem I had on hand (which had to do with some operator precedence confusion).

To avoid future confusion and problems it’s still better to refactor the code to be explicit with what you want to do by using the DATEADD() function:

Thanks for reading. You might also enjoy following me on Twitter.

Want to learn even more SQL?

Sign up for my newsletter to receive weekly SQL tips!

Conditionally Returning Rows Based On Query Results

Published on: 2018-10-16

While I normally prefer formatting my query results in a downstream app/reporting layer, sometimes I can’t get around adding some business formatting logic to my SQL queries.

Today I want to show you four different ways to conditionally output rows of data based on a SQL query.

Setting Up The Base Query

You’ve probably worked with a query that results in either 0 or 1 rows being returned:

If you put that query into a derived table and add some IIF() logic on top of it, you now have a situation where you your result may contain a row with one of two distinct values or no rows at all:

If you put that query into a derived table and add some IIF() logic on top of it, you now have a situation where you your result may contain a row with one of two distinct values or no rows at all:

(Note: if you ever need to know whether the seconds part of the current time is divisible by 3 and 2, use SELECT IIF(DATEPART(second,GETDATE()) % 6 = 0,1,0) and not this monstrosity of a query  I’m creating to demonstrate a scenario when you dependent derived table logic).

Sometimes we may want to force certain scenarios based on the output of the query above. Here are few common patterns that I find myself doing when needing to meet certain business requirements of queries to return data conditionally.

Always Return 1 Row

Let’s say we are happy with getting a result value of 0 or 1 for AreSecondDivisbleBy3And2, but want to additionally return some other value when our derived table returns no rows. We can accomplish this with a UNION ALL and some sorting:

We can limit our query to return TOP 1 and then add an OrderPrecedence column to determine which query result row to return. If our original query has a row of data, it will be returned because of it’s OrderPrecedence. If our original query returns 0 rows, our fall back UNION ALL default value of -1 will be returned.

Return 1 row when value is 1, 0 rows when value is 0

What about a situation where we want to return a row when AreSecondsDivisbleBy3And2 is equal to 1, but no row when it is equal to 0?

The IIF function and CASE statements work great for conditionally returning a value in a SELECT, but how can we conditionally return a row?  Here’s one approach:

In this scenario, we return a row when our value is 1, but do not return a row when the value is 0 or our derived table doesn’t return any rows.

We use an INNER JOIN to filter out the row value that we want to return 0 rows.

Return 1 row when null, and 0 rows when the value is 1 or 0

In this scenario we want to return no rows when AreSecondsDivisibleBy3And2=1 and a row when its not.

I’ve never had a real-world use for this one, but it’s essentially a combination of the first two solutions.

This one is by far the most difficult one to logic through, but it’s a pure reversal of return no rows when rows are present and return a row when no rows are present.

Always return 0 rows

I’m not exactly sure what the business case for never returning any rows would be, but this one is pretty simple: just add a condition that will always evaluate to false:

Since 1=0 will never be true, your query will never return any results regardless of what kind of logic is happening in your SELECT or derived table.

Thanks for reading. You might also enjoy following me on Twitter.

Want to learn even more SQL?

Sign up for my newsletter to receive weekly SQL tips!

The Project Graveyard

Published on: 2018-10-09

This post is a response to this month’s T-SQL Tuesday #107 prompt by Jeff Mlakar.  T-SQL Tuesday is a way for the SQL Server community to share ideas about different database and professional topics every month.

This month’s Halloween themed topic asks to “…
share a story about a project you worked on or were impacted by that went horribly wrong.”

I’ve been fortunate enough to never have been part of a large disastrous project at work.  My projects always have a “fail fast” mentality, so they never build up to a point where they come crashing down in a death spiral.

But that’s not to say I haven’t experienced my own project horror story in my personal work.

A while back I made a goal to produce a quality SQL Server focused blog post and video every week.  Essentially this means I am starting a new small-scale project each week where I play the part of project manager, developer, analyst, etc… with a delivery deadline of every Tuesday morning.  While I’ve gotten better at this process over time, I have also failed to meet my personal goals numerous for a variety of reasons.

Scope Creep-y

In order to meet my weekly deadline, I need to stay laser focused on the topic I choose for that particular week.  If I get additional ideas while writing and start trying to incorporate them into my post (ie. scope creep), I inevitably miss midweek milestones and have to try to make up time elsewhere to make my deadline.

One instance of scope-creep I experienced earlier this year was when I was trying to write a post on how to build a table-driven validation system.

I’ve built many table-driven processes in the past so this seemed like it would be an easy topic to write about.  I started that week’s blogging process by building the demo templates that would include table structures, execution scripts, etc…

Instead of wrapping up my basic demos so I could move on to writing the actual post, I kept building out demos for more features: logging functions, parameterization, SQL injection protection, common performance problems, etc…

It was exciting to be building all of this out, but instead of creating one-week’s content, I realized I had started working on enough demos for several weeks of posts.  This wouldn’t have necessarily been a bad thing on its own; after all it’s nice to be a few weeks ahead on content creation.

However, I didn’t quite finish enough demos for any one post in particular, and due to some other life events I didn’t get back to working on my demos until Sunday afternoon.  Normally at that point I’d already have my demos done, a blog post written, a video filmed, and either a finished video edit that I’m uploading or getting really close to uploading to YouTube.  What I had instead was a bunch of half-finished SQL demos saved in a very rough outlined blog post.

The Project Graveyard

This isn’t the first time poor time management and scope creep has gotten me in trouble:

Some projects sent prematurely to the grave

I have several posts that I’ve invested a good amount of time into but never released because they are incomplete.  In almost all of these cases my problems stemmed from poor planning and scope creep.

In the case of my table-driven post, by late-Sunday afternoon I realized I was going to miss my weekly deadline goal if I continued with that post, so I scrapped the idea for now and quickly wrote and shot a different post on an SSMS trick instead.  It was discouraging to have to do that, but at the end of the day I was able to meet my weekly deadline even if it was with a different result than I initially expected.

You might be thinking, “Why not ignore deadlines and release the post later in the week/month?”  For me, I like my weekly deadlines because I like the creative challenges that come from having time constraints.  It forces me to limit my scope and work on different projects on a regular basis.  My goal from blogging and video making is to learn how to present information in a succinct manner so that my communication skills, both written and verbal, improve.  So while I can (and probably will) complete these posts at some point in the future, I treat them as failures for that particular week’s project.

And while failures aren’t particularly fun, they can wind up being great learning opportunities: after all, I haven’t gotten so off track due to scope creep ever since.

Thanks for reading. You might also enjoy following me on Twitter.

Want to learn even more SQL?

Sign up for my newsletter to receive weekly SQL tips!