SQL - count dates that are between same dates every year - sql

I have a table with the following rows:
date
2018-09-01
2018-10-01
2019-01-01
2019-09-01
2020-03-01
2020-08-01
Let's say fiscal year starts in October of the previous year and ends in September of that year. So fiscal year 2020 would be from 2019-10-01 to 2020-09-30. I am trying to count the dates that fall within each fiscal year so create the following table:
date_count fiscal_year
1 FY18
3 FY19
2 FY20
I've tried the following to get a single year:
SELECT count(*) as date_count, 'FY18' as fiscal_year
FROM table_name
WHERE date between '2017-10-01' and '2018-09-30'
and I get
date_count fiscal_year
1 FY18
But I need to do this for every fiscal year. I've seen similar answers online but none that has the date counts. Would I need to use a recursive query?

Just add 3 months and extract the year:
select t.*,
year(dateadd(month, 3, date)) as fiscal_year
from t;

Related

How can I create a week group column in my Date Dimension Table based on this specific logic?

I am using SQL Server 2014 and I have a table in my Database called Date Dimension.
It has a column called "Date" which contains daily dates from 01 January 2013 to 31 December 2025 (extract of the column given below):
Date
2022-01-01
2022-01-02
2022-01-03
2022-01-04
2022-01-05
2022-01-06
2022-01-07
2022-01-09
...
2022-01-30
2022-01-31
...
I need to create a new column in the Date Dimension Table called "HR_WeekGroup" based on the following logic:
A WeekGroup will start on a Monday and end on a Sunday. WeekGroups will be calculated for EACH Month separately. That is, if the 1st Day of a Month is a Saturday, the WeekGroup for that week will consist of only 2 days (Saturday and Sunday) and if the last Day of that Month is a Monday, the weekGroup will consist of only 1 Day (Monday).
Here is what I'm after (based on the Month of January 2022):
Date HR_WeekGroup
2022-01-01 Wk 01Jan2022-02Jan2022
2022-01-02 Wk 01Jan2022-02Jan2022
2022-01-03 Wk 03Jan2022-09Jan2022
2022-01-04 Wk 03Jan2022-09Jan2022
2022-01-05 Wk 03Jan2022-09Jan2022
2022-01-06 Wk 03Jan2022-09Jan2022
2022-01-07 Wk 03Jan2022-09Jan2022
2022-01-09 Wk 03Jan2022-09Jan2022
... ...
2022-01-30 Wk 24Jan2022-30Jan2022
2022-01-31 Wk 31Jan2022
...
What would be the T-SQL Code that would allow me to create this column?
I had a look at the following pages but I can't figure out how to apply the examples to my specific problem.
What is the SQL syntax to create a column in my Date Dimension Table that will group the dates into this specific week grouping?
How to Group Data by Week in SQL Server
Set DateFirst 1;
-- The above changes the start of the week to Monday.
-- This makes the week as starting on Monday and ending on Sunday
-- DayOfWeek 1 means Monday
-- DayOfWeek 7 means Sunday
with cte as (
select
Date_Column,
MONTH(Date_Column) as [MONTH], -- Month in the year
DAY(Date_Column) as [DAY], -- Day in the month
DATEPART(week,Date_Column) as [WeekOfTheYear], --Week number of the year
DATEPART(dw,Date_Column) as [DayOfWeek], -- The week day of the week
Min(Date_Column) OVER (Partition by DATEPART(week,Date_Column), MONTH(Date_Column), YEAR(Date_Column) ) as [MinDateWeekGroup],
Max(Date_Column) OVER (Partition by DATEPART(week,Date_Column), MONTH(Date_Column), YEAR(Date_Column) ) as [MaxDateWeekGroup]
from date_dimension
--order by YEAR(Date_Column), MONTH(Date_Column), DAY(Date_Column)
)
select
Date_Column,
case when [MinDateWeekGroup] = [MaxDateWeekGroup]
THEN CONCAT('Wk ',
Right('0'+Convert(varchar(10), Day([MinDateWeekGroup])),2),
Convert(char(3), [MinDateWeekGroup], 0),Convert(char(4),YEAR([MinDateWeekGroup])) )
ELSE
CONCAT('Wk ',
Right('0'+Convert(varchar(10), Day([MinDateWeekGroup])),2),
Convert(char(3), [MinDateWeekGroup], 0),Convert(char(4),YEAR([MinDateWeekGroup])),
'-',
Right('0'+Convert(varchar(10), Day([MaxDateWeekGroup])),2),
Convert(char(3), [MaxDateWeekGroup], 0),Convert(char(4),YEAR([MaxDateWeekGroup]))
)
END as [HR_WeekGroup]
from cte
order by YEAR(Date_Column), MONTH(Date_Column), DAY(Date_Column)

Creating FISCAL_WEEK column in SQL Server Calendar table

We have a requirement. We need to create a fiscal_week column in a SQL Server table.
Table will have data as Normal_date column as fiscal_date and fiscal_year column which will have year part of the date.
Logic for FISCAL_WEEK is like this:
FIRST FISCAL WEEK WILL START FROM 1 JAN OF EVERY YEAR AND IT WILL BE TILL FIRST FRIDAY.
SECOND WEEK STARTS FROM SATURDAY AND IT WILL RUN TILL NEXT FRIDAY.
THIS WILL GO ON TILL THE END OF YEAR (31 JAN)
We will have data something as below table.
Table With Fields as per Requirement
How would I create query for this ? We will have data from 2010 till 2035 years in the table.
Thanks,
Mahesh
You can use an ad-hoc tally table to create the dates and then the window function sum() over() to calculate the Fiscal_Week
Declare #Date1 date = '2020-01-01'
Declare #Date2 date = '2035-12-31'
Select Fiscal_Date = D
,Fiscal_Year = DatePart(YEAR,D)
,Day_Name = DateName(WEEKDAY,D)
,Fiscal_Week = case when DateName(WEEKDAY,#Date1)='Saturday' then 0 else 1 end
+sum(case when DateName(WEEKDAY,D)='Saturday' then 1 else 0 end) over (partition by DatePart(YEAR,D) order by D)
From ( Select Top (DateDiff(DAY,#Date1,#Date2)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),#Date1)
From master..spt_values n1,master..spt_values n2,master..spt_values n3
) A
Results
Fiscal_Date Fiscal_Year Day_Name Fiscal_Week
2020-01-01 2020 Wednesday 1
2020-01-02 2020 Thursday 1
2020-01-03 2020 Friday 1
2020-01-04 2020 Saturday 2
2020-01-05 2020 Sunday 2
2020-01-06 2020 Monday 2
...
Other way I found would be as below.
SET DATEFIRST 6
GO
SELECT FISCAL_DATE, DATEPART(WEEK,Fiscal_Date) FISCAL_WEEK FROM ERP.CUSTOM_FISCAL_CALENDER

Sum over defined Week limits

I have a rolling date with associated hours. I want to sum the hours over my defined 7-day week range of Saturday to Friday.
So I need to define any date as a week beginning Saturday, week ending Friday and sum over this range.
The table is in the form of:
Date
Day
Hours
2021-06-12
Saturday
3
2021-06-18
Friday
3
2021-06-21
Monday
1
2021-06-22
Tuesday
2
Grouping the above table into Saturday-Friday Week sums.
Saturday
Friday
Total_Hours
2021-06-12
2021-06-18
6
2021-06-19
2021-06-25
3
You can use date functions to get for each date (other than Saturday) the previous Saturday which is the start of the week it belongs too and group by that:
WITH cte AS (
SELECT *, DATEADD(day, -DATEPART(dw, Date) % 7, Date) Saturday
FROM tablename
)
SELECT Saturday,
DATEADD(day, 6, Saturday) Friday,
SUM(Hours) Total_Hours
FROM cte
GROUP BY Saturday
See the demo.
This code works in SQL Server but similar logic and functions can be used for other databases.
You don't have to tie this to datepart() or datename(), which in turn depends on DATEFIRST (alas!).
Instead, you can use date arithmetic. This in turn depends on the fact that 0 date is a Monday. But that is not configurable (as far as I know).
So:
select v.week as saturday, dateadd(day, 6, v.week) as friday,
sum(hours)
from t cross apply
(values (dateadd(day, 7*datediff(week, 0, dateadd(day, 1, t.date)) - 2, 0))
) v(week)
group by v.week
order by v.week;
Here is a db<>fiddle.

SQL Statement that will pull MINDATE from dates for current month and year

I need a sql statement that will pull the following
the MINIMUM visit date for the current month and year (May 2021)
emp_id visit_date
1 5/3/2021
1 5/4/2021
1 5/10/2021
1 6/5/2021
2 5/2/2021
2 5/6/2021
2 6/7/2021
3 5/9/2021
3 7/8/2021
Result:
1 5/3/2021
2 5/2/2021
3 5/9/2021
SELECT emp_id, visit_date
FROM
THS_ClientVisit
WHERE
THS_ClientVisit.visit_date =
(
SELECT MIN(THS_ClientVisit.visit_date)
FROM dbo.THS_ClientVisit
WHERE MONTH YEAR from current month[i.e. 05-2021] = MONTH YEAR from visit_date {i.e. 05-2021]
);
Thank you for your assistance!
SELECT
emp_id,
MIN(CONVERT(date,rev_timein)) as MinVisitDate
FROM
THS_ClientVisit
WHERE
DATEPART(mm, THS_ClientVisit.rev_timein)= MONTH(CURRENT_TIMESTAMP) AND DATEPART(yy, THS_ClientVisit.rev_timein)=YEAR(CURRENT_TIMESTAMP)
GROUP BY
THS_ClientVisit.emp_id

Issue with Date_SUB And BETWEEN function

I came across this issue while creating a parametrised query; Then intent of the query is to pull past 5 months (excluding current month) data based on the date passed as a variable. Basic table schema for Table A is as follows:
as_of_date Y X
2019-12-31 1 AB
2019-11-30 2 CD
2019-10-31 3 EF
2019-09-30 4 GH
2019-08-31 5 MN
2019-07-31 6 XYZ
2020-01-31 7 PQR
2020-02-29 8 AAA
Following is the query I wrote:
WITH
date
AS
(
SELECT CAST("2020-02-29" AS Date) as run_date
)
SELECT DISTINCT CAST(a.as_of_date AS DATE) as_of_date,
FROM A as a
WHERE CAST(a.as_of_date AS DATE) BETWEEN DATE_SUB((SELECT run_date FROM date), INTERVAL 5 Month) AND DATE_SUB((SELECT run_date FROM date), INTERVAL 1 Month)
This query runs fine when run_date is set to "2020-01-31" and returns past 5 months data i.e. Dec, Nov, October, Sept, and August. But fails when date is set to "2020-02-29" it only returns 4 months data.
Simple "fix" is to add DATE_TRUNC(..., MONTH) as in below example
SELECT DISTINCT CAST(a.as_of_date AS DATE) as_of_date,
FROM `project.dataset.tableA` AS a
WHERE DATE_TRUNC(CAST(a.as_of_date AS DATE), MONTH)
BETWEEN DATE_TRUNC(DATE_SUB((SELECT run_date FROM date_cte), INTERVAL 5 Month), MONTH)
AND DATE_TRUNC(DATE_SUB((SELECT run_date FROM date_cte), INTERVAL 1 Month), MONTH)