How can I get T-SQL to include correct data from last month - tsql

In the below query I return data for past 5 months, unfortunately I can not get it to include correct count from current month (June 2021), it ruturns 0 where as it should have returned 2 since I have 2 entries with StartDate 14-06-2021 and 17-06-2021 which should have been in this count.. How can I fix this?.
The output I get (missing 2 in month 6)
year month EmployeeStartet
2021 2 8
2021 3 0
2021 4 0
2021 5 4
2021 6 0
My Query
declare #thismonth1 as Date = DateAdd(
d,
1 - DatePart(d, CURRENT_TIMESTAMP),
CURRENT_TIMESTAMP
);
declare #lastMonth1 as Date = DateAdd(
d,
1 - DatePart(d, CURRENT_TIMESTAMP),
CURRENT_TIMESTAMP
);
declare #firstMonth1 as Date = DateAdd(m, -4, #lastMonth1);
WITH months AS (
SELECT
#firstMonth1 AS thisMonth
UNION ALL
SELECT
DateAdd(m, 1, thisMonth) AS thisMonth
FROM
months
WHERE
thisMonth < #lastMonth1
),
data AS (
SELECT
YEAR(StartDate) year,
MONTH(StartDate) month,
COUNT(StartDate) EmployeeStartet
FROM
EFP_EmploymentUser
WHERE
EmployType = 'fixed'
AND StartDate BETWEEN #firstmonth1
AND #thismonth1
GROUP BY
YEAR(StartDate),
MONTH(StartDate)
)
SELECT
YEAR(m.thisMonth) AS year,
MONTH(m.thisMonth) AS month,
ISNULL(d.EmployeeStartet, 0) AS EmployeeStartet
FROM
months m
LEFT OUTER JOIN data d ON d.year = YEAR(m.thisMonth)
AND d.month = MONTH(m.thisMonth)
ORDER BY
m.thisMonth ASC;

Try
declare #thismonth1 as Date = DateAdd(d, 1 - DatePart(d, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
declare #lastMonth1 as Date = DateAdd(d, 1 - DatePart(d, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
declare #firstMonth1 as Date = DateAdd(m, -4, #lastMonth1);
select #thismonth1, #lastMonth1, #firstMonth1;
This gives you
#thismonth1
#lastMonth1
#firstMonth1
2021-06-01
2021-06-01
2021-02-01
Correct #lastMonth1 and your query will run just fine. You can use EOMONTH for this.

Related

T-SQL Retrieve Last 6 Weeks Data to the Previous Saturday

SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= DATEADD(ww, -6, (Select MAX([TradingDate]) From FactSalesDetail))
ORDER BY TradingDate
Can anyone advise how I can convert the above WHERE Clause from retrieving the last 6 weeks data from Max Date in my Fact Table to the last 6 weeks to the Previous Saturday?
So as of Today that would Saturday 1st Jan and then back 6 weeks from that?
Using the current weekday can get you last Saturday.
And if you bring ##DATEFIRST into the equation then it won't depend on the DATEFIRST setting.
SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())))
AND TradingDate <= CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))
ORDER BY TradingDate
Test snippet for date range
SET DATEFIRST 7;
SELECT
datename(weekday, date_now) AS weekday_now, date_now
, datename(weekday, date1) AS wd1, date1
, datename(weekday, date2) AS wd2, date2
FROM
(
SELECT
CAST(GETDATE() AS DATE) AS date_now
, CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))) AS date1
, CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())) AS date2
) q
weekday_now
date_now
wd1
date1
wd2
date2
Tuesday
2022-01-04
Saturday
2021-11-20
Saturday
2022-01-01
db<>fiddle here

Running Week on Fiscal Calendar

I have a problem on this calendar, the weeks calculations per year are working correctly based on our needs, but now I need to add a iteration variable (#runningWeekSeed) that increments in 1 when the week changes (#WorkWeekSeed).
I'm not sure If i explained correctly.
/*
This Query is built for a 4-4-5 calendar, Mon - Sun week.
Each Fiscal year start on 01/01/YYYY ends on 12/31/YYYY.
*/
DECLARE
#FiscalCalendarStart DATETIME, -- Calendar starts
#EndOfCalendar DATETIME, -- Calendar ends
#CurrentDate DATETIME, -- Calendar date being calculated against
#RunningDaySeed INT, -- Days calculations
#RunningWeekSeed INT, -- Weeks calculations
#FiscalYearSeed INT, -- Years calculations
#RunningPeriodSeed INT, -- Fiscal Month
#WorkWeekSeed INT, -- Fiscal Week
#WorkQuarterSeed INT, -- Fiscal Quarter
#WorkPeriod INT, -- Used to assign where the extra "leap week" goes. Based on the 4-4-5 calendar.
#WeekEnding DATETIME
DECLARE #FiscalTimePeriods AS TABLE (
Sysdate VARCHAR (10), -- Date with format MMDDYYYY
Date_Time_Target DATETIME, -- The date, but with Time duh
MSC_Week INT, -- Running week according MSC Calendar
MSC_Year INT, -- Calendar with corresponding days into the Fiscal year
weekEnding DATETIME,
runningWeekSeed INT
)--Of Table
/* These are user variables, and should be set according every need */
SELECT
#FiscalCalendarStart = '20150101', -- The date of year start. Used as the base date for calculations (This case will be on 12/29/2015 to match 7 days week for week 1 of 2015)
#EndOfCalendar = '20901231' , -- The date on which the calendar query will end. Can be adjusted for each need
#RunningDaySeed = 1, -- This is used to measure the number of days since the calendar began, often used for depreciation (usually 1)
#RunningPeriodSeed = 1, -- The number of fiscal months since the original calendar began (usually 1)
#RunningWeekSeed = 1, -- The number of fiscal weeks since the original calendar began (usually 1)
#FiscalYearSeed = 2015 -- The starting fiscal year (first 3 days of week 1 belongs to 2014 but it's on 2015 fiscal calendar)
/* These are iteration variables, do not mess with these */
SELECT
#WorkPeriod = 1 ,
#WorkWeekSeed = 1 ,
#WorkQuarterSeed = 1
/* The loop is iterated once for each day */
SET #CurrentDate = #FiscalCalendarStart
SELECT #WeekEnding = dateadd ( D , 8 - DATEPART ( DW , #CurrentDate ), #CurrentDate )
WHILE #CurrentDate <= #EndOfCalendar
BEGIN --MAIN BEGIN
INSERT INTO #FiscalTimePeriods
SELECT
CONVERT ( VARCHAR (10), #CurrentDate , 101 ) AS SysDate,
#CurrentDate AS Date_Time_Target,
#WorkWeekSeed AS MSC_Week,
YEAR (#CurrentDate) AS MSC_Year,
#WeekEnding,
#RunningWeekSeed
/* Iterate the date and increment the RunningDay */
SET #CurrentDate = DATEADD ( D , 1 , #CurrentDate )
SELECT #RunningDaySeed = #RunningDaySeed + 1,
#WeekEnding = dateadd ( D , 8 - DATEPART ( DW , #CurrentDate ), #CurrentDate )
/* If #CurrentDate is 01/01/YYYY, reset fiscal counters */
IF (DATEPART (MONTH, #CurrentDate) = 1 AND DATEPART(DAY, #CurrentDate) = 1)
BEGIN
SELECT
#WorkPeriod = 1 ,
#WorkWeekSeed = 1 ,
#WorkQuarterSeed = 1,
#FiscalYearSeed = #FiscalYearSeed + 1
END
ELSE
/*************Check if Monday is between 12/23 to 12/31 *****************/
IF DATEPART ( DW , #CurrentDate ) = 2 -- Check if #CurrentDate is monday
IF DATEPART (MONTH, #CurrentDate) = 12 AND (DATEPART(DAY, #CurrentDate) in (23, 24, 25, 26, 27, 28, 29, 30, 31)) -- If #CurrentDate is Dec 23 to 31
BEGIN
SELECT
#WeekEnding = dateadd ( D , 8 - DATEPART ( DW , #CurrentDate ), #CurrentDate ),
#WorkWeekSeed = 52,
#WorkQuarterSeed = 4,
#WorkPeriod = 12
END
ELSE
IF DATEPART ( DW , #CurrentDate ) = 2
BEGIN
SELECT
#WeekEnding = dateadd ( D , 8 - DATEPART ( DW , #CurrentDate ), #CurrentDate ),
#WorkWeekSeed = CASE
WHEN #WorkWeekSeed = 53 THEN 52
ELSE #WorkWeekSeed + 1
END
END
/* Compare if current date acomplish ISO_WEEK standard ISO 8601*/
IF DATEPART ( ISO_WEEK , #CurrentDate ) = 1
SELECT
#WorkPeriod = 1,
#WorkWeekSeed = 1,
#WorkQuarterSeed = 1
------------------------HERE IS WHERE START TO DO THE CALCULATION OF THE runningWeekSeed-------------------------
IF #WorkWeekSeed = 52
SELECT #WeekEnding = dateadd ( D , 8 - DATEPART ( DW , #CurrentDate ), #CurrentDate ),
#RunningWeekSeed = #RunningWeekSeed
ELSE
IF DATEPART(DW, #CurrentDate) = 2
SELECT #RunningWeekSeed = #RunningWeekSeed + 1
ELSE
IF (DATEPART (MONTH, #CurrentDate) = 1 AND DATEPART(DAY, #CurrentDate) = 1)
SELECT #RunningWeekSeed = #RunningWeekSeed + 1
END -- MAIN BEGIN
SELECT
*
FROM #FiscalTimePeriods
ORDER BY Date_Time_Target ASC
The needed results need to be like this

Group Records By Time Period

I'm trying to take a time frame the user selects and then group the selection into time periods - in this case: 2 weeks.
For instance, today is 5/4/2018 and if I set that as my start date and 5/31/2018 as my end date, I get the following:
DECLARE #StartDate DATE ,
#EndDate DATE ,
#ToDate DATE;
SET #StartDate = GETDATE ();
SET #EndDate = '20180531';
SET #ToDate = DATEADD ( DAY, 1, #EndDate );
SELECT dd.Date ,
ROW_NUMBER () OVER ( ORDER BY DATEPART ( WEEK, dd.Date )) AS [rownumb]
FROM dbo.DateDimension AS [dd]
WHERE dd.Date >= #StartDate
AND dd.Date < #ToDate;
And the results look like:
Date rownumb
2018-05-04 1
2018-05-05 2
2018-05-06 3
2018-05-07 4
2018-05-08 5
2018-05-09 6
2018-05-10 7
2018-05-11 8
2018-05-12 9
2018-05-13 10
2018-05-14 11
2018-05-15 12
2018-05-16 13
2018-05-17 14
2018-05-18 15
2018-05-19 16
2018-05-20 17
2018-05-21 18
2018-05-22 19
2018-05-23 20
2018-05-24 21
2018-05-25 22
2018-05-26 23
2018-05-27 24
2018-05-28 25
2018-05-29 26
2018-05-30 27
2018-05-31 28
I was playing around with ROW_NUMBER ( along with RANK and DENSE_RANK ) but I have not been able to get these functions to accomplish what I am looking for but what I am hoping to do is have an additional column called "TimePeriod" where the dates are grouped together in 2-week increments ( or 14 days ) so that 5/4/18 through 5/17/18 have a value of 1 for the "TimePeriod" column and 5/18/18 through 5/31/18 would have a value of 2 for the "TimePeriod" column. And this should be dynamic so that wider date ranges are grouped in periods of two weeks with each period increasing by 1.
Suggestions?
If there's no requirement to use the ordering and ranking functions in sql, you can easily implement as below.
get the total number of days between the start and end date
for each date you subtract the days difference of the current date from the total days difference, then divide this by 14
so this basically will give you the interval (2 weeks) to which the current date belongs, it's zero based so you might want to add a 1 to it
DECLARE #StartDate DATE ,
#EndDate DATE ,
#ToDate DATE;
DECLARE #DaysDiff INT;
SET #StartDate = GETDATE ();
SET #EndDate = '20180531';
SET #ToDate = DATEADD ( DAY, 1, #EndDate );
--GET the difference in days between the start and end date
SET #DaysDiff = DATEDIFF( Day, #StartDate,#ToDate )
SELECT dd.Date ,
( #DaysDiff - DATEDIFF(Day,dd.Date,#ToDate) )/14
FROM dbo.DateDimension AS [dd]
WHERE dd.Date >= #StartDate
AND dd.Date < #ToDate;

postgresql daysdiff between two dates grouped by month

I have a table with the date columns (start_date, end_date) and I want to calculate the difference between these dates and grouped by the month.
I am able to get the datediff in days, but I do not know how to group this in month, any suggestions?
Table:
id Start_date End_date days
1234 2014-06-03 2014-07-05 32
12345 2014-02-02 2014-05-10 97
Expected results:
month diff_days
2 26
3 30
4 31
5 10
6 27
7 5
I think your expected output numbers are off a little. You might want to double-check.
I use a calendar table myself, but this query uses a CTE and date arithmetic. Avoiding the hard-coded date '2014-01-01' and the interval for 365 days is straightforward, but it makes the query harder to read, so I just used those values directly.
with your_data as (
select date '2014-06-03' as start_date, date '2014-07-05' as end_date union all
select '2014-02-02', '2014-05-10'
), calendar as (
select date '2014-01-01' + (n || ' days')::interval calendar_date
from generate_series(0, 365) n
)
select extract (month from calendar_date) calendar_month, count(*) from calendar
inner join your_data on calendar.calendar_date between start_date and end_date
group by calendar_month
order by calendar_month;
calendar_month count
--
2 27
3 31
4 30
5 10
6 28
7 5
As a rule of thumb, you should never group by the month alone--doing that risks grouping data from different years. This is a safer version that includes the year, and which also restricts output to a single calendar year.
with your_data as (
select date '2014-06-03' as start_date, date '2014-07-05' as end_date union all
select '2014-02-02', '2014-05-10'
), calendar as (
select date '2014-01-01' + (n || ' days')::interval calendar_date
from generate_series(0, 700) n
)
select extract (year from calendar_date) calendar_year, extract (month from calendar_date) calendar_month, count(*) from calendar
inner join your_data on calendar.calendar_date between start_date and end_date
where calendar_date between '2014-01-01' and '2014-12-31'
group by calendar_year, calendar_month
order by calendar_year, calendar_month;
SQL Fiddle
with min_max as (
select min(start_date) as start_date, max(end_date) as end_date
from t
), g as (
select daterange(d::date, (d + interval '1 month')::date, '[)') as r
from generate_series(
(select date_trunc('month', start_date) from min_max),
(select end_date from min_max),
'1 month'
) g(d)
)
select *
from (
select
to_char(lower(r), 'YYYY Mon') as "Month",
sum(upper(r) - lower(r)) as days
from (
select t.r * g.r as r
from
(
select daterange(start_date, end_date, '[]') as r
from t
) t
inner join
g on t.r && g.r
) s
group by 1
) s
order by to_timestamp("Month", 'YYYY Mon')
;
Month | days
----------+------
2014 Feb | 27
2014 Mar | 31
2014 Apr | 30
2014 May | 10
2014 Jun | 28
2014 Jul | 5
Range data types
Range functions and operators

Understanding TSQL Coalesce function

I am trying to select all 12 months / year. And I thought following TSQL code would do this. However, this does not include all months like I want. What is the cause of this? This is modified code:
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
)
select yt.DateClosed 'r2', m.m 'r3',
month(coalesce(yt.DateClosed, m.m)) as 'MonthClosed',
year(coalesce(yt.DateClosed, m.m)) as 'YearClosed'
from months m
left join yourTable yt
on
( datepart(year, yt.DateClosed) = DATEPART(year, m.m)
and datepart(month, yt.DateClosed) = DATEPART(month, m.m)
or
datepart(year, yt.DateOpened) = DATEPART(year, m.m)
and datepart(month, yt.DateOpened) = DATEPART(month, m.m)
)
AND year(coalesce(yt.DateClosed, m.m)) = 2010
order by yt.DateClosed
So above query does not return all months. But if I change above WHERE lines to:
FROM [PROC].ALL_AUDIT
WHERE
BTK_CLOSED_DATE < #TheMonthLastDate
then this query does return all 12 months. How can this be?
Output that I want and that I see when WHERE is BTK_CLOSED_DATE < #TheMonthLastDate:
r2 r3 MonthClosed YearClosed
NULL 2010-06-01 00:00:00.000 6 2010
NULL 2009-11-01 00:00:00.000 11 2009
2010-01-06 20:02:19.127 2010-01-01 00:00:00.000 1 2010
2010-01-27 23:13:45.570 2010-01-01 00:00:00.000 1 2010
2010-02-15 14:49:14.427 2010-02-01 00:00:00.000 2 2010
2010-02-15 14:49:14.427 2009-12-01 00:00:00.000 2 2010
But if I instead use WHERE:
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
then I see:
r2 r3 MonthClosed YearClosed
NULL 2010-10-01 00:00:00.000 10 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-08-01 00:00:00.000 8 2010
NULL 2010-08-01 00:00:00.000 8 2010
...
So notice that in first result I see NULL for June 2010, which is what I want.
I think the problem has something to do with the fact that my data contains 2009-2011 data, but I only compare months and not years. How would I add in this additional logic?
The only place where you are reducing the data is with the WHERE clause you have already identified. Therefore, the reason you are not getting all the months you expect is down to the column TSK_START_DATE not being less than #TheMonthLastDate for all months.
To prove this hypothesis, run the following section of your query (I have commented out part of the where clause and removed everything under 'yourTable' cte). The results should show you what is being returned in the TSK_Start_Date column for your missing months and help you identify why the rows are missing when applying the < #TheMonthLastDate clause.
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
--TSK_START_DATE < #TheMonthLastDate
)
)
select * , #TheMonthLastDate TheMonthLastDate from yourTable