SQL Date clause for Reporting Services - sql-server

I am developing a report using SQL and SSRS that gives a day by day breakdown of stats from the 1st of the month to the previous day.
However, on the 1st of the month the report comes up blank when I need it to show the previous months information (e.g. on the 1st of February I want a report that gives me a day by day breakdown of January from the 1st to 31st.
I tried the following case statement in the SQL where clause to see if it would fix the issue but it doesn't seem to work:
(dIntervalStart BETWEEN dbo.DateAndTime(CASE WHEN DAY(GEtDate()) = 1 THEN DATEADD(mm, DATEDIFF(mm, 0, GETDATE() - 1), 0) ELSE DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0) END, '00:00:00')
Is there something else that might work?

declare #StartOfMOnth bit
declare #startDate date
declare #endDate date
select #StartOfMOnth =
case when datepart(dd, getdate()) <> 1 then 0
else 1
end
IF (#StartOfMOnth = 0) --If not start of month
BEGIN
SELECT #startDate = DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0) --First day of current month
SELECT #endDate = DATEADD(DD, -1, GETDATE())--Previous day
END
ELSE --If start of month
BEGIN
SELECT #startDate = DATEADD(MONTH, -1, DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)) --First day of last month
SELECT #endDate = DATEADD(DD, -1, DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0))--Last day of last month
END
--Once you have start and end dates, do what needs to be done in the dataset

Related

SQL Server - Date String

Can you please help me create an sql statement that will get the previous date and concatenate that date in this format:
'2016-05-05 00:00:00'
I already know the sql function to get the previous date but I don't know yet on how to get the time in the expected format. My query is something like this
Select *
from table
where
transaction_date between '2016-05-05 00:00:00' and '2016-05-05 23:59:59'
So I need 00:00:00 and 23:59:59 to be concatenated in the date.
You don't need the times at all. Just don't use BETWEEN and use >= and < for the next day, like this:
SELECT *
FROM table
WHERE transaction_date >= '2016-05-05'
AND transaction_date < '2016-05-06'
Or if you only have the single date value:
DECLARE #date DATETIME = '2016-05-05'
SELECT *
FROM table
WHERE transaction_date >= #date
AND transaction_date < DATEADD(DAY, 1, #date)
The added benefit of doing it this way is that you also don't miss out on times that occur in the last second of the day as your original query does. For example 2016-05-05 23:59:59.001
Edit: From the comments below
To get yesterdays date, get today's date and subtract a day from it:
DECLARE #date DATETIME = DATEADD(DAY, -1, CAST(GETDATE() AS DATE))
Now use the logic as mentioned above.
This function:
DATEADD(dd, DATEDIFF(dd, 0, GetDate()), 0)
...will turn 2016-05-05 18:18:231 into 2016-05-05 00:00:000. From there it is easy to get full date boundaries by adding and subtracting days:
DECLARE #Date DATETIME
,#YesterdayStartDate DATETIME
,#TodayStartDate DATETIME
SET #Date = GetDate()
SET #TodayStartDate = DATEADD(dd, DATEDIFF(dd, 0, #date), 0)
SET #YesterdayStartDate = DATEADD(dd, -1, #TodayStartDate)
SELECT #Date, #YesterdayStartDate, #TodayStartDate
SELECT *
FROM Table
WHERE
transaction_date >= #YesterdayStartDate AND
transaction_date < #TodayStartDate
This will give you the result with transaction_date on yesterday.
SELECT
*
FROM
TABLE
WHERE
transaction_date BETWEEN dateadd(DAY, datediff(DAY, 1, GETDATE()), 0) AND dateadd(DAY, 1, dateadd(DAY, datediff(DAY, 1, GETDATE()), 0))
Compare date with out time part . ie below code.
Select * from table
where CONVERT(VARCHAR(8), transaction_date , 112) = CONVERT(VARCHAR(8), getdate(), 112)

MS Sql Date format?

I'm pretty new to MSSQL and was wondering if someone could help me convert the following where statement from looking at previous week to previous month.
ks.report_date BETWEEN (convert(varchar(113), (DATEADD(day, (-1 * DATEPART(dw, (dateadd(week, -1, getdate())))) + 1, (dateadd(week, -1, getdate())))), 101))
AND (convert(varchar(113), (DATEADD(day, (-1 * DATEPART(dw, (dateadd(week, -1, getdate())))) + 7, (dateadd(week, -1, getdate())))), 101))
SQL Server has a function called EOMonth() that will take a date and give you the end of the month containing that date. You can then use DATEADD to subtract months from that value to get the last day of previous months. Lastly, use DATEADD again to add 1 day to get the first day of the month. Here is an example.
BETWEEN DATEADD(DAY, 1, DATEADD(MONTH, -2, EOMONTH(GETDATE())))
AND DATEADD(MONTH, -1, EOMONTH(GETDATE()))
If you're using an earlier version than SQL Server 2012 then this would work:
BETWEEN DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
AND DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))

Find the First Wednesday after the last Tuesday of last financial month

One of my clients defines (for strange financial reasons) a financial month as a period of time that begins the Wednesday immediately after the last Tuesday of a Month (inclusive) and lasts until the last tuesday of the following month (inclusive).
I need to find the start of the last and the current financial month.
Some examples:
if today is September 23rd 2015 i need to get July 29th and August 26th because the current financial month goes from August 26th to September 29th.
If today is September 30th 2015 I need to get August 26th to September 30th.
I have different clients with different definitions and this means that some of them are using Wednesday and others are using Monday so i need this day to be a parameter, like Monday = 1 and Wednesday = 3. I call it FDOM, FirstDayOfMonth.
My work so far focused on using the formulas i found around with first and last days of current and last month, modified to take into account FDOM. I managed to get last Wednesday of Last Month but this sometimes is not correct because I am considering a day of the month that belongs to a solar month but also to the next financial month, like September 30th belongs to solar September but to Financial October, as financial October begins September 30th.
DECLARE #BASE AS DateTime = '19000101 00:00'
DECLARE #FDOM AS INT = 3 --Wednesday
DECLARE #Datevalue AS DATE = GETDATE()
SET DATEFIRST #FDOM
select DATEADD(D,1-(DATEPART(dw,DATEADD(D,-1,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #Datevalue) , #BASE)))),DATEADD(D,-1,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #Datevalue) , #BASE)))
This gives me the first wednesday after the last tuesday of last month and this would be correct from September 1st to September 29th (it gives August 26th) as "the beginning of the current financial month". But it would be wrong on September 30th as it should give September 30th and also wrong from August 26th till the end of August as it should give August 26th but instead gives July 29th.
I think this answers your requirements. Its quite long but hopefully, by breaking things out and naming things, I'm making it clear how we get to the final answer, and so if it's not quite right, it can be adapted:
declare #FDOM int
set #FDOM = 3 --Wednesday. 0 = Sunday, 6 = Saturday
declare #KnownDay datetime
set #KnownDay = DATEADD(day,#FDOM - 1,'20150301') --Offset from a "known good" Sunday to the day before FDOM
declare #EOLastDec datetime
set #EOLastDec = DATEADD(year,DATEDIFF(year,'20010101',GETDATE()),'20001231')
declare #Today datetime
set #Today = DATEADD(day,DATEDIFF(day,0,GETDATE()),0) --You can change this to test other key dates
;With Numbers(n) as (--If you have a numbers table, you can skip this CTE
select ROW_NUMBER() OVER (ORDER BY so1.object_id) - 1
from sys.objects so1 cross join sys.objects so2
), LastOfMonths as (
select DATEADD(month,n,#EOLastDec) as LOM
from Numbers
where n between 0 and 13
), LastImportant as (
select DATEADD(day,-n,LOM) as EOFMonth
from LastOfMonths cross join Numbers
where n between 0 and 6 and
DATEPART(weekday,DATEADD(day,-n,LOM)) = DATEPART(weekday,#KnownDay)
)
select DATEADD(day,1,li0.EOFMonth) as StartOfMonth,DATEADD(day,1,li1.EOFMonth) as EndOfMonth
from
LastImportant li1
cross join
LastImportant li2
left join
LastImportant li1_anti
on
li1.EOFMonth < li1_anti.EOFMonth and
li1_anti.EOFMonth <= #Today
left join
LastImportant li2_anti
on
li2.EOFMonth > li2_anti.EOFMonth and
li2_anti.EOFMonth >= #Today
inner join
LastImportant li0
on
li0.EOFMonth < li1.EOFMonth
left join
LastImportant li0_anti
on
li0_anti.EOFMonth < li1.EOFMonth and
li0.EOFMonth < li0_anti.EOFMonth
where
li1.EOFMonth <= #Today and
li2.EOFMonth >= #Today and
li1_anti.EOFMonth is null and
li2_anti.EOFMonth is null and
li0_anti.EOFMonth is null
Hopefully, the CTEs are reasonably explanatory. We generate a numbers table, and then we calculate the last day of each month, and from there, we step up to 6 days backwards to locate a day of the right type (i.e. a Tuesday, if #FDOM is 3)
I originally had a simpler final query using just li1 and li2 (and li1_anti and li2_anti), but realised that the query was just finding the current financial month - so I've added another couple of joins (using li0 and li0_anti) to find the start of the previous financial month.
Calculate the start date from previous month and the last day from current month and used a CTE to generate all dates between them. Later, get the MAX weekday from both months.
DECLARE #CurrentDate DATE = '2015-08-23'
DECLARE #StartDate DATE,
#EndDate DATE,
#MonthEnd INT = 3
-- Get the first day from previous month and last day from current month
SELECT #StartDate = DATEADD(MONTH , DATEDIFF(MONTH, 0, #CurrentDate)-1, 0),
#EndDate = DATEADD(SECOND,-1,
DATEADD(MONTH , DATEDIFF(MONTH, 0, #CurrentDate)+1,0))
;WITH Calendar AS
( -- Generate all dates between #StartDate and #EndDate
SELECT #StartDate [Date]
UNION ALL
SELECT DATEADD(D, +1, Calendar.[Date])
FROM Calendar
WHERE Calendar.[Date] < #EndDate
)
SELECT DATEADD(DAY, +1, MAX(StartDate.[Date])) StartDate,
DATEADD(DAY, +1, MAX(EndDate .[Date])) EndDate
FROM Calendar StartDate,
Calendar EndDate
WHERE -- Get the max weekday from previous month
DATEPART(MONTH , StartDate.[Date]) = DATEPART(MONTH, #StartDate) AND
DATEPART(WEEKDAY, StartDate.[Date]) = #MonthEnd AND
-- Get the max weekday from current month
DATEPART(MONTH , EndDate .[Date]) = DATEPART(MONTH, #EndDate) AND
DATEPART(WEEKDAY, EndDate .[Date]) = #MonthEnd
Try this. You can use EOMONTH function to get the end of month on Sql Server 2012 or above.
Click to see the fiddle demo.
DECLARE #date DATETIME = GETDATE()
DECLARE #LastMonthEnd DATETIME = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, #date), 0))
DECLARE #CurrentMonthEnd DATETIME = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, #date) + 1, 0))
SET DATEFIRST 1
;WITH CTE1 AS
(
SELECT 1 number, DATEPART(WEEKDAY, #LastMonthEnd) FirstDay,
DATEPART(WEEKDAY, #CurrentMonthEnd) LastDay
UNION ALL
SELECT 1+number, DATEPART(WEEKDAY, DATEADD(DAY, -number, #LastMonthEnd)),
DATEPART(WEEKDAY, DATEADD(DAY, -number, #CurrentMonthEnd))
FROM CTE1
WHERE number < 7
)
SELECT DATEADD(DAY, -(SELECT Number FROM CTE1 WHERE FirstDay = 3), #LastMonthEnd) StartDate,
DATEADD(DAY, -(SELECT Number FROM CTE1 WHERE LastDay = 3), #CurrentMonthEnd) EndDate
After a lot of effort I managed to find an expression that DOES NOT use CTE as i am not sure i can't use CTE in all the places i will have to employ this.
So basically first i understand with a CASE if the date i am considering is before or after the last Wednesday of the Month it belongs to. Then i return the last wednseday of two and of one month ago OR the last wednesday of one month ago and of this month.
This works also changing FDOM and i tested it for several months of this year. It seems to always work.
Probably the use of EOMonth would shorten it but i have to verify i can use it in my server.
I am sorry i just specified as a requirement that i can't use a CTE only in the comments but thank you for your help
DECLARE #datevalue AS Datetime = getdate()
DECLARE #BASE AS DateTime = '19000101 00:00'
DECLARE #FDOM AS INT = 3 --1 is for Monday
SET DATEFIRST #FDOM
SELECT CASE WHEN (#datevalue < DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE)))
THEN(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 1, #BASE)))
ELSE(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 0, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 0, #BASE)))
END AS [Start of Last Financial Month]
,CASE WHEN (#datevalue < DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE)))
THEN(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 0, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 0, #BASE)))
ELSE(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE)))
END AS [Start of Current Financial Month]

Displaying dates values for current date in SQL Server

I am trying to filter out the values based on the date which should be within today's date. I am using the below query, however the query is not working as expected.
This is what I am using in SQL Server.
select values
from table
where date between DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
and GETDATE()
I am expecting the date to be filtered for values between '2015-03-18 00:00:00' AND '2015-03-18 23:59:59' if I am executing the query on 18th March 2015.
Please guide.
It's much better to use a >= and < than BETWEEN:
SELECT *
FROM Table
WHERE
date >= CAST(CAST(GETDATE() AS DATE) AS DATETIME)
AND date < DATEADD(DAY, 1, CAST(CAST(GETDATE() AS DATE) AS DATETIME))
CAST(CAST(GETDATE() AS DATE) AS DATETIME) will get you the current date without the time part that is 2015-03-18 00:00:00
DATEADD(DAY, 1, CAST(CAST(GETDATE() AS DATE) AS DATETIME)) will get you the next day, again without the time part.
So in turn, your WHERE condition would be:
WHERE
date >= '2015-03-18 00:00:00'
AND date < '2015-03-19 00:00:00'
Alternatively, you can use this:
SELECT *
FROM Table
WHERE
date >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) -- beginning of this day
AND date < DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) + 1, 0) -- beginning of next day
For more date calculations, refer to this article.
As You are Expecting value between '2015-03-18 00:00:00' AND
'2015-03-18 23:59:59. so, you can simply compare only date part.
you can Use Cast()/Convert():
SELECT *
FROM Table
WHERE
cast(date as date) =cast(getdate() as date)
It included 2015-03-18 00:00:00' AND '2015-03-18 23:59:59'

T-SQL statement for selecting all records on a future date

I need to select all records with a billing date 15 days from now.
This gives me nothing because it is trying to compare date and time:
"nextbill = dateadd(d, +15, getdate())"
This works:
"select *
from custrate
where nextbill >= '2014-01-02 00:00:00' and nextbill < '2014-01-02 23:59:59'"
How do I get everything with a date of 15 days from now ignoring the time?
I would use the start of the day with >= and start of the next day with a <...
declare #from datetime, #thru datetime;
set #from = dateadd(d, datediff(d, 0, getdate()) + 15, 0);
set #thru = dateadd(d, 1, #from);
select ...
from custrate
where nextbill >= #from and nextbill < #thru
select *
from custrate
where convert(date,nextbill) = DATEADD(d, 15, convert(date,getdate()))
or older versions of sql:
select *
from custrate
where DATEADD(dd, DATEDIFF(dd, 0, nextbill), 0) = DATEADD(dd, DATEDIFF(dd, 0, getdate()), 15)

Resources