How to get the Monday position of a month in T-SQL - sql-server

For example consider the April 2023. In this year the Monday dates are 3, 10, 17, and 24. Now I want to get the date 10 position of April.
My target result is: April 10 = second or 2

SELECT (DAY('2023-04-10') - 1) / 7 + 1

Position outputs the searched number for a date
WITH CTE_DATES
AS(
SELECT CAST(DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) -1, 0) AS DATE) AS [DATE] -- start previous month
UNION ALL
SELECT CAST(DATEADD(DD, 1, [DATE]) AS DATE)
FROM [CTE_DATES]
WHERE [DATE] < CAST(DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 0, 0)) AS DATE) -- end previous month
)
SELECT
[date]
,DATENAME(WEEKDAY, [date]) AS 'Weekday'
,DATEPART(WEEKDAY, [date]) AS 'Day'
,ROW_NUMBER() OVER (ORDER BY [date] ASC) AS 'POSITION'
FROM [CTE_DATES]
WHERE DATEPART(WEEKDAY, [date]) IN (1)

Related

How to get data of current date using sum in SQL?

I'm working on a SQL query trying to fetch sum data for the current day/date. Can anyone have a look at my query, and find me a working solution?
SELECT SUM(amount)
FROM tbl_expense_record
WHERE dateonly = CAST(GETDATE() AS Date)
But I get data when mentioning a specific date in where condition like
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly = '2020-06-12'
I want the a code to auto pick current date. Also I would like to fetch sum of ranged dates like a whole week, and a month!
select datename(month, '2020-06-12'), datename(month, getdate());
--1week
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(week, -1, cast(getdate() as date))
and dateonly <= cast(getdate() as date)
--1month
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly <= cast(getdate() as date)
--build muscle memory (it is always safe to check for < date+1 instead of <= date)
--1month
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date));
--6months
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -6, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date));
if not exists
(
select *
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date))
)
begin
select 'no rows within the last month'
end
else
begin
select 'there are rows within the last month';
end;
Examples:
declare #tbl_expense_record table(dateonly date, amount decimal(9,2));
insert into #tbl_expense_record
values ('20200501', 10), ('20200612', 10), ('20200613', 11), ('20200614', 12),
('20200710', 5), ('20200720', 6), ('20200820', 20), ('20200825', 30),
('20201102', 1), ('20201110', 2), ('20201120', 3);
--aggregation per month, for all rows
select year(dateonly) as _year, month(dateonly) as _month, sum(amount) as sum_amount_per_month, count(*) as rows_per_month
from #tbl_expense_record
group by year(dateonly), month(dateonly);
--aggregation per iso-week
select year(dateonly) as _year, datepart(iso_week, dateonly) as _isoweek, sum(amount) as sum_amount_per_isoweek, count(*) as rows_per_isoweek
from #tbl_expense_record
group by year(dateonly), datepart(iso_week, dateonly);
--aggregation per month, for all rows with a dateonly that falls in the last month
--check the difference between aggregation per month earlier and this..
--filter rows first == where .... and then aggregate
--there are two rows with dateonly > 06 november (the row at 05 is filtered out by the where clause)
select year(dateonly) as _year, month(dateonly) as _month, sum(amount) as sum_amount_per_month, count(*) as rows_per_month
from #tbl_expense_record
where dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date))
group by year(dateonly), month(dateonly);
--aggregate per week diff from today/getdate()
select
datediff(week, getdate(), dateonly) as week_diff_from_today,
dateadd(day,
--datepart(weekday..) is used...account for ##datefirst setting / set datefirst
1-(##datefirst+datepart(weekday, dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date))))%7,
dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date)))
as startofweek,
dateadd(day, 6, --add 6 days to startofweek
dateadd(day,
--datepart(weekday..) is used...account for ##datefirst setting / set datefirst
1-(##datefirst+datepart(weekday, dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date))))%7,
dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date)))
) as endofweek,
sum(amount) as sum_amount, count(*) as rows_within_week
from #tbl_expense_record
group by datediff(week, getdate(), dateonly);

How to get date from day name?

How can I get the date of specific day ? Like if I have Thursday or month number ?
If I give 12 for instance I want to get the date of 12th day of this month. Or if I give 'Sun' or 'Sat' is it possible to get the dates of these days ?
DATEFROMPARTS function can construct a date from day, month and year.
DATEPARTS does the opposite - gives you the day, month, year, hour, etc. of a date. Or you can use functions like YEAR, MONTH and DAY.
You can deconstruct the value returned by GETDATE function and construct whatever date you want. Here is for example how to get the date for 12th day of the current month:
select DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 12)
Converting 'Sun' or 'Sat' to date is a bit more difficult. First, they aren't quite deterministic. If today is Friday, "Sunday this week" means "next Sunday" in some parts of the world and "last Sunday" in others. You should implement your own logic based on the value returned by DATEPART(dw, GETDATE()) (which will give you the day of the week).
To find the weekday of the current month
DECLARE #daynumber INT = 12
SELECT datename(weekday, dateadd(d, #daynumber - 1, getdate()))
To find the dates of the current month of a given weekday
DECLARE #dayname char(3) = 'sat'
;WITH CTE as
(
SELECt TOP
(datediff(D, eomonth(getdate(), -1),eomonth(getdate())))
dateadd(d,row_number()over(ORDER BY 1/0),
eomonth(getdate(),-1))date
FROM
(values(1),(2),(3),(4),(5),(6))x(x),
(values(1),(2),(3),(4),(5),(6))y(x)
)
SELECT day(date) monthday, date
FROM CTE
WHERE left(datename(weekday, date),3) = #dayname
select sysdatetime(); --2018-12-13 16:29:56.0560574
---If I give 12 for instance I want to get the date of 12th day of this month.
declare #numDate int = 12;
select dateadd(m, datediff(m,0,getdate()),#numDate - 1 ); --2018-12-12 00:00:00.000
--Or if I give 'Sun' or 'Sat' is it possible to get the dates of these days ?
declare #text nvarchar(20) = 'Sunday';
declare #dateStart date = dateadd(month, datediff(month, 0, sysdatetime()), 0),
#days int =( select (DAY(dateadd(dd,-1,DATEADD(m,1,cast(2018 as varchar(4)) + '-' + cast(12 as varchar(2)) +'-01')))));
declare #dateEnd date = DATEADD(day,#days-1,#dateStart);
;WITH CTE (Dates,EndDate) AS
(
SELECT #dateStart AS Dates,#dateEnd AS EndDate
UNION ALL
SELECT DATEADD(day,1,Dates),EndDate
FROM CTE
WHERE DATEADD(day,1,Dates) <= EndDate
)
SELECT CTE.Dates, DATENAME(DW, CTE.Dates)
FROM CTE
where DATENAME(DW, CTE.Dates) = #text;
Result:
Dates,Day
2018/12/2,Sunday
2018/12/9,Sunday
2018/12/16,Sunday
2018/12/23,Sunday
2018/12/30,Sunday
-- Here is how to get week day name to week day number
DECLARE #T TABLE (Dow INT, NameOfDay VARCHAR(15), ShortName CHAR(3));
WITH Days AS
(
SELECT TOP 7
ROW_NUMBER() OVER(PARTITION BY object_id ORDER BY object_id) AS RowNo
FROM
sys.all_columns
)
INSERT INTO #T
SELECT
RowNo,
DATENAME(WEEKDAY, RowNo - 1),
LEFT(DATENAME(WEEKDAY, RowNo - 1), 3)
FROM
Days
SELECT
*
FROM
#T;
-- Here is how to get start of period
SELECT
DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) AS StartOfDay,
DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0) AS StartOfWeek,
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) AS StartOfMonth,
DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0) AS StartOfYear;
-- An example
WITH
StartPeriods AS
(
SELECT DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0) AS StartOfWeek
),
SelectedDay AS
(
SELECT
Dow - 1 AS Dow,
(SELECT StartOfWeek FROM StartPeriods) AS StartOfWeek
FROM
#T
WHERE
ShortName = 'Wed'
)
SELECT
DATEADD(DAY, Dow, StartOfWeek)
FROM
SelectedDay;

Creating date ranges from time stamp

The query below grabs the max date from column Time_Stamp as StartDate from Survey. Adding 90 days to it for EndDate. Then creating 2 more ranges with 90 day intervals by just adding more to the original EndDate.
I'm trying to have the StartDate fall within 4 buckets of either Jan1st, April1st, July1st, or Oct1. If the Max Time_Stamp is before 1 of these dates then that will be the first StartDate of my ranges...So for my example below, the max Time_Stamp is June4th so the StartDate needs to be July 1st. Is this doable within sql server?
Time_Stamp for Hospital1
Time_Stamp
-----------
2014-06-04 16:01:14.000
2014-06-04 15:55:33.000
2014-06-04 15:45:05.000
2014-06-04 15:36:15.000
2014-06-04 15:00:34.000
2014-06-04 14:35:24.000
2014-06-04 14:04:50.000
2014-06-04 13:46:55.000
2014-06-04 13:23:57.000
2014-06-04 11:27:51.000
Current output:
StartDate EndDate
----------- -----------
Jun 4 2014 Sep 2 2014
Sep 3 2014 Dec 2 2014
Dec 3 2014 Mar 3 2015
query
WITH Start AS
(
SELECT
MAX(Time_Stamp) as StartDate,
DATEADD(day, 90, MAX(Time_Stamp)) as EndDate
FROM Survey
WHERE MainHospital = 'Hospital1'
),
Results AS
(
SELECT StartDate, EndDate from Start
UNION
SELECT DATEADD(DAY, 1, EndDate), DATEADD(day, 91, EndDate) FROM Start
UNION
SELECT DATEADD(DAY, 92, EndDate), DATEADD(day, 182, EndDate) FROM Start
)
SELECT LEFT(StartDate,11) AS StartDate, LEFT(EndDate,11) AS EndDate FROM Results
Just an update, this gives me what I need for the 1st StartDate...
--Return first day of next quarter
SELECT DATEADD(qq, DATEDIFF(qq, 0, MAX(Time_Stamp)) + 1, 0)
FROM Survey
WHERE MainHospital = 'Hospital1'
DECLARE #Year DATE = '2013-01-01'
DECLARE #Quarter INT = 1;
SELECT DATEADD(QUARTER, #Quarter - 1, #Year) ,
DATEADD(DAY, -1, DATEADD(QUARTER, #Quarter, #Year))
You can use DATEPART(QUARTER, #Date) to figure out which quarter the record being selected and then you can use this query to find the begin/end dates of that quarter.
Use it like this:
SELECT DATEADD(QUARTER, DATEPART(QUARTER, Time_Stamp) - 2, DATEADD(YEAR, DATEDIFF(YEAR, 0, Time_Stamp), 0)) AS StartDate,
DATEADD(SECOND, -1, DATEADD(QUARTER, DATEPART(QUARTER, Time_Stamp) - 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, Time_Stamp), 0))) AS EndDate
FROM Hospital1
It seems that you are just trying to calculate the quarter of your date, Am i correct?
If so, you can just use:
SELECT DATENAME(Quarter, CAST(CONVERT(VARCHAR(8), GETDATE()) AS DATETIME)) as Quarter
to calculate a quarters date ranges:
select DATEADD(qq, datediff(qq, 0, getdate()),0) as first
select dateadd(dd, -1, DATEADD(qq, datediff(qq, 0, getdate()) +1, 0)) as last

how to split the number of days in monthwise between two month

hi i want to find the total days of two month and split the days for month wise..for example...
26-02-2013 to 3-3-2013
here for the february month it shows 2days leave but march month i wont display the total leave..this is my query..can anyone correct my query..it shows only febraury days only,,march days is not shown here..
SELECT month(fdate) as Month_Number
, datename(month, fdate) as Month
, case when month(fdate) <> month(tdate) then
datediff(day, fdate, DATEADD(month, ((YEAR(fdate) - 1900) * 12) + MONTH(fdate), -1))
else
datediff(day, fdate, tdate)
end as Leaves
from test
where empid like '112'
Try this, it will display the number of days for each month:
SELECT *
, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, t.fdate) + 1, 0)) Last_In_Month_Of_Beginning
, DATEADD(MONTH, DATEDIFF(MONTH, 0, t.tdate), 0) First_In_Month_Of_End
INTO #temp1
FROM test t
WHERE empid LIKE '112'
SELECT number Month_Number
, CASE
WHEN MONTH(fdate) = MONTH(tdate) THEN DATEDIFF(DAY, fdate, tdate) - 1
WHEN MONTH(Last_In_Month_Of_Beginning) = number THEN DATEDIFF(DAY, fdate, Last_In_Month_Of_Beginning)
WHEN MONTH(First_In_Month_Of_End) = number THEN DATEDIFF(DAY, First_In_Month_Of_End, tdate)
END Leave
INTO #temp2
FROM #temp1 a
JOIN master..spt_values v ON
v.type = 'P'
AND v.number BETWEEN MONTH(a.Last_In_Month_Of_Beginning) AND MONTH(a.First_In_Month_Of_End)
SELECT Month_Number
, SUM(Leave) Leaves
FROM #temp2
GROUP BY Month_Number
Here is an SQL Fiddle

Deterministic scalar function to get week of year for a date

Here is a great way of how to get day of week for a date, Deterministic scalar function to get day of week for a date.
Now, could anyone help me to create a deterministic scalar function to get week of year for a date please? Thanks.
This works deterministically, I can use it as a computed column.
datediff(week, dateadd(year, datediff(year, 0, #DateValue), 0), #DateValue) + 1
Test code:
;
with
Dates(DateValue) as
(
select cast('2000-01-01' as date)
union all
select dateadd(day, 1, DateValue) from Dates where DateValue < '2050-01-01'
)
select
year(DateValue) * 10000 + month(DateValue) * 100 + day(DateValue) as DateKey, DateValue,
datediff(day, dateadd(week, datediff(week, 0, DateValue), 0), DateValue) + 2 as DayOfWeek,
datediff(week, dateadd(month, datediff(month, 0, DateValue), 0), DateValue) + 1 as WeekOfMonth,
datediff(week, dateadd(year, datediff(year, 0, DateValue), 0), DateValue) + 1 as WeekOfYear
from Dates option (maxrecursion 0)

Resources