Solve Data Problems
Solve Data Problems
Solve Data Problems
SQL Server’s date and time functions make it easy to solve various date-
related problems, like finding the start and end dates of a period, finding
anniversaries in a specified period, and identifying weekdays in a period.
In my last article, I explored the various date and use the appropriate DateTimexFromParts() func-
time types in SQL Server and the collection of func- tion for the first of the month and the first and last
tions and operations you can use with them. In this day of the year, and wrap EOMonth() with Cast()
article, I’ll look at some common date problems and or Convert() for the last day of the month.
show how to solve them.
Listing 1. There are simple ways to find the first and last day of
First, a quick review. SQL Server supports six data the month or the year containing a specified date.
types related to dates and times. Four of them are DECLARE @Date Date;
variations on a combined date and time construct.
Three of those (SmallDateTime, DateTime and SET @Date = '1/4/2017';
DateTime2) vary only in precision. The fourth, SELECT DATEFROMPARTS(DATEPART(Year, @Date),
DateTimeOffset, is the same as DateTime2, but also DATEPART(Month, @Date), 1) AS BoM,
includes a timezone offset component. There are EOMONTH(@Date) AS EoM,
also separate Date and Time types. For this article, DATEFROMPARTS(DATEPART(Year, @Date),
1, 1) AS BoY,
I’ll refer to these in the aggregate as date/time. DATEFROMPARTS(DATEPART(Year, @Date),
There are functions for retrieving the current 12, 31) AS EoY;
date/time, computing the difference between date/
time values, calculating new date/time values from
existing ones, taking date/time values apart, and
constructing date/time values from their compo-
nents. I’ll use a number of them in solving the prob- Figure 1. Finding the first and last day of the month or the
year is straightforward.
lems in this article.
The examples use the Adventureworks 2014 But this approach doesn’t work for the first and
sample database. last days of the week or the quarter, because we
don’t know what the appropriate days or months
Find the first and last days of the are. Instead, we need to calculate those, and we can
do months and years the same way, if we wish.
period
Given a date, it’s not unusual to want to find the The DateAdd() function lets us move a date/
first and last day of the containing week, month, time forward or backward by a number of years,
quarter, or year. For some of these periods, it’s easy months, days, hours, etc. The DateDiff() func-
to build the start and end dates by pulling the given tion allows us to compute the difference between
date apart and creating a new one. For other peri- two date/time values in whichever units we want
ods, it’s trickier, but the DateAdd() and DateDiff() (though see my last article to understand exactly
functions provide a generic approach. how that works). We can combine them to figure
out the first or last day of the period containing a
Let’s start with the easy way, which works for particular date, as in Listing 2, where we find the
months and years. First, as noted in my previous first and last day of the week. The code is included
article, the function EOMonth()gives you the last in this month’s downloads as FirstLastOfWeek.
day of the month for a specified date. To find the SQL.
first day of the month, you can extract the month
and year from the specified date and combine them Listing 2. You can combine DateAdd() and DateDiff() to com-
with a day of 1. A similar approach works for the pute dates such as the first and last of the month.
first and last day of the year. Listing 1 shows the DECLARE @Date Date;
code; it’s included in this month’s downloads as SET @Date = '1/4/2017';
FirstLastSimple.SQL. Figure 1 shows the results. If
you want them as one of the other date/time types, SELECT DATEADD(Week,
To see what’s causing the problem, we can add If we run the query as shown, with a specified
the translated birthday to the field list and look for date of January 4, 2017, we get the same results as
only those records with January 4 birthdays, as in in Figure 3. Moving the date into the current year
the query in Listing 7; the results are shown in Fig- lets you find all birthdays in a specified week.. But
ure 5. if we change the specified date to December 29,
Listing 7. By including the computed birthday this year in the
2017, we get the results shown in Figure 6.
results, we can see why this version doesn’t work across the
end of a year.
SELECT FirstName, LastName,
Employee.BusinessEntityID, BirthDate,
DATEADD(YEAR, DATEDIFF(Year,
BirthDate, @Date), BirthDate)
FROM [HumanResources].[Employee]
JOIN [Person].[Person]
ON Employee.BusinessEntityID =
Person.BusinessEntityID Figure 6. With the more complicated date translation, we can
WHERE Month(BirthDate) = 1 find all the birthdays in a specified week, even across the end
AND Day(BirthDate) = 4 of the year.
-- SET DateFirst 7;
DOWNLOAD
Subscribers can download FR201701code.zip in the SourceCode sub directory of the document
portal. It contains the following files:
tamargranor201701_code.zip
Source code for the article “Solve date problems” from Tamar E. Granor, Ph.D.
doughennig201701_code.zip
Source code for the article “Lessons Learned in Version Control, Part 1” from Doug Hennig
whilhentzen201701_code.zip
Source code for the article “Parsing Obnoxious Text Files – Part 2” from Whil Hentzen
ericselje201701_code.zip
Source code for the article “FoxUnit in Depth” from Eric Selje
FoxRockX™(ISSN-1866-4563)
FoxRockX, FoxTalk 2.0, FoxTalk, Visual Extend and Silverswitch are trademarks of ISYS GmbH. All product
names or services identified throughout this journal are trademarks or registered trademarks of their
respective companies.