In SQL Server how to write the query to get the month in between the startdate and enddate, days(in month) for the Month , actual number of days in the month
startdate and enddate is passed as a input parameter , i need to know the number of months, actual days and the count of days in the month
e.g :
Start date : 2012-04-02
End date : 2012-08-23
i need to get the result as,
Month Days ActualDays _ inMonth
----------------------------------------------
04 29 30 - (The no of days on Apr'12 )
05 31 31
06 31 31
07 31 31
08 31 31
04 -month
29 -(Frm startdate 2-Apr to till 30-Apr'12(Apr End))
30 - (The no of days on Apr'12 )
Here's a procedure to calculate the number of days in a month. I do not know what you mean by "actual days" or how that could be different.
if object_id('spMonthList') is not null
drop procedure spMonthList
go
create procedure dbo.spMonthList(
#start date
, #end date)
as
; with Months as
(
select dateadd(month, datediff(month, 0, #start), 0) as MonthStart
union all
select dateadd(month, 1, MonthStart)
from Months
where MonthStart < #end
)
select datepart(month, MonthStart) as Month
, datediff(day, MonthStart, dateadd(month, 1, MonthStart)) as NumberOfDays
from Months;
go
exec spMonthList '2012-04-01', '2012-08-01'
-->
Month NumberOfDays
4 30
5 31
6 30
7 31
8 31
Example at SQL Fiddle.
Related
I am trying to extract the last hour (TKT_DT) record for number of tickets (TKT_DN) from sales table (PS_TKT_HIST) for specific date (BUS_DAT).
I have the following code but it extracts the number of tickets (TKT_NO) for each hour. I want to filter the last hour only. Here is the code I used:
Select count(TKT_NO) AS SAL_TKTS,
DATEPART(HOUR, (TKT_DT))AS SAL_HR
FROM PS_TKT_HIST
WHERE BUS_DAT = '2022-03-30'
GROUP By DATEPART (HOUR, TKT_DT)
I get the flowing results
SAL_TKTS SAL_HR
5 10
1 11
3 12
5 13
10 14
13 15
23 16
18 17
12 18
6 19
6 20
4 21
I want to get only the record (4) for the last hour (21)
If you just want the number of tickets in the last hour on a given day:
DECLARE #date date = '20220330';
SELECT COUNT(*)
FROM dbo.PS_TKT_HIST
WHERE BUS_DAT = #date
AND TKT_DAT >= DATEADD(HOUR, 23, CONVERT(datetime2, #date));
For any hour other than the last hour (let's say, the 9PM hour):
WHERE BUS_DAT = #date
AND TKT_DAT >= DATEADD(HOUR, 21, CONVERT(datetime2, #date))
AND TKT_DAT < DATEADD(HOUR, 22, CONVERT(datetime2, #date));
If by "last hour" you don't mean 11 PM but rather the last hour there was a sale, you would have to do something like this:
DECLARE #date date = '20220330';
SELECT TOP (1) COUNT(*)
FROM dbo.PS_TKT_HIST
WHERE BUS_DAT = #date
GROUP BY DATEPART(HOUR, TKT_DAT)
ORDER BY DATEPART(HOUR, TKT_DAT) DESC;
We have table WeeklyResults that looks like this:
Year WeekNum Value
2021 47 11.0
2021 48 14.0
2021 49 12.0
2021 50 17.0
2021 51 11.8
2021 52 11.3
2021 53 11.1
2022 01 11.5
2022 02 11.5
2022 03 81.5
We have a report with two parameters: Date and WeekNum. The report needs to show the last 6 weeks based on the weeknumber selected.
The issue is that, if user selects Week 2 of 2022, how can I subtract 6 weeks so that I get weeks 50, 51, 52, 53 of 2021 and weeks 1, 2 from 2022?
So, if the user selects 2022 and Week 02, it would show the last 6 weeks based on Weeknum 2 of year 2022 (wk50 to Wk02). If user selects 2021 and 52, it would show wk47-52.
You can use a little < and <= logic along side TOP and ORDER BY to achieve this:
DECLARE #Year int = 2022,
#WeekNum int = 3; --Note, if you are storing WeekNum as a (var)char,
--your leading zeros imply you are, then define the
--variable as a char(2).
SELECT TOP (6)
[Year],
WeekNum,
[Value]
FROM dbo.YourTable
WHERE ([Year] = #Year AND WeekNum <= #WeekNum)
OR [Year] < #Year
ORDER BY [Year] DESC,
WeekNum DESC;
Try this:
DECLARE #Year int = 2022
, #WeekNum varchar(02) = '02'
;
WITH FinalTable AS
(
SELECT TOP 6 *
FROM WeeklyResults
ORDER BY LTRIM(Year) + WeekNum DESC
)
SELECT *
FROM FinalTable
ORDER BY Year, WeekNum
Another option that doesn't involve an ORDER BY. Using DATEPART you can determine the final week of the prior year and subtract the number of weeks to get the records needed.
You may need to adjust what day is the first day of the week for your count. See this post for more info on that.
DECLARE
#Year INT = 2022
, #WeekNum INT = 3;
SELECT
*
FROM
WeeklyResults
WHERE
Year = #Year
AND WeekNum <= #WeekNum
OR
(
#WeekNum < 6
AND Year = #Year - 1
AND WeekNum > DATEPART (WEEK, CONCAT ('12/31/', #Year - 1)) - #WeekNum
);
I need to get the first day and the last day of the week based on the number of the week, year and month
My week starts on saturday and finish in friday
Example:
Year: 2020
Week: 45
Normal period of week: First day: 2020-10-31 ~ Last day: 2020-11-06
I need return something like
October: First day: 2020-10-31 ~ last day: 2020-10-31
November: First day 2020-11-01 ~ last day: 2020-11-06
my query to return last day of week:
select DATEADD (WEEK, #PcpSemana, DATEADD (YEAR, ('20' + LEFT(#PcpPeriodo,2))-1900, 0)) - 5 as lastDayOfWeek
my query to return first day of week
SELECT WeekStart = DATEADD(DAY,
(CEILING(DATEPART(DAY, DATEADD (WEEK, #PcpSemana, DATEADD (YEAR, ('20' + LEFT(#PcpPeriodo,2))-1900, 0)) - 5) / 7.0) - 1) * 7,
DATEADD(MONTH, DATEDIFF(MONTH, 0,DATEADD (WEEK, #PcpSemana, DATEADD (YEAR, ('20' + LEFT(#PcpPeriodo,2))-1900, 0)) - 5), 0));
I'm using SET DATEFIRST 6
I can't evolve much
PcpPeriodo contains YYMM ( 2011) = 2020 / 11 )
PcpSemana contains weeknumber (45) (01 ~ 53)
I am not sure what your data looks like, but if you have the first day of the week, you can split it among months as:
select weeks.*
from (values (convert(date, '2020-10-31'))) w(weekstart) cross apply
(values (dateadd(day, 6, w.weekstart), eomonth(w.weekstart))
) v(weekend, eom) cross apply
(values (w.weekstart,
case when v1.weekend <= v1.eom then v1.weekend else v1.eom end
),
(case when v1.weekend > v1.eom then dateadd(day, 1, v1.eom) end,
case when v1.weekend > 1.eom then v1.weekend
)
) weeks(weekstart, weekend)
where weeks.weekstart is not null;
This is using apply as a way of storing intermediate results, such as the last day of the month and when the week ends.
DECLARE #d datetime;
SET DATEFIRST 6;
SET #d = '2020-11-01';
WITH weektest as (
select #d as d
union all
select DATEADD(DAY,1,d) from weektest where d<='2020-11-6'
)
SELECT
d,
DATEPART(week, d),
DATEPART(weekday,d),
DATENAME(weekday,d)
from weektest;
output:
d
----------------------- ----------- ----------- ------------------------------
2020-11-01 00:00:00.000 45 2 Sunday
2020-11-02 00:00:00.000 45 3 Monday
2020-11-03 00:00:00.000 45 4 Tuesday
2020-11-04 00:00:00.000 45 5 Wednesday
2020-11-05 00:00:00.000 45 6 Thursday
2020-11-06 00:00:00.000 45 7 Friday
2020-11-07 00:00:00.000 46 1 Saturday
I know you can set #Date to 01/01/2001 as beginning of the month.
and then call dates that are first of every month, for example:
01/01/2001
01/02/2001
01/03/2001
but how would I please if possible is always find the date in the middle of the month? I would use 15th, but issue you have is with February
I need to make analysis of sum of sales mid month
any ideas please team
you can use this formula
DECLARE #Date DATE ='20180201'
SELECT DATEADD(DAY, (DAY(EOMONTH(#Date)) / 2) - 1, #Date)
Solution:
Get the count of the days in the month and calculate the "middle" day. In the next example the count of the days (28, 29, 30 or 31) is divided by an integer divisor (2), so the result will be an integer that has any fractional part truncated. Choose your preferred method.
DECLARE #date date
SET #date = DATEFROMPARTS(2020, 2, 1)
-- 15 is the half of the month with 30 and 31 days, 14 for months with 28, 29 days
SELECT DATEDIFF(d, #date, DATEADD(month, 1, #date)) / 2
-- 16 is the half of the month with 31 days, 15 for months with 29, 30 days, 14 for month with 28 days
SELECT (DATEDIFF(d, #date, DATEADD(month, 1, #date)) + 1) / 2
Example:
WITH Months AS
(
SELECT SomeDate = DATEFROMPARTS(2018, 1, 1)
UNION ALL
SELECT DATEADD(month, 1, SomeDate)
FROM Months
WHERE DATEPART(month, SomeDate) < 12
)
SELECT
SomeDate AS FirstDate,
DATEADD(d, -1, DATEADD(month, 1, SomeDate)) AS LastDate,
DATEDIFF(d, SomeDate, DATEADD(month, 1, SomeDate)) AS DaysBetween,
DATEDIFF(d, SomeDate, DATEADD(month, 1, SomeDate)) / 2 AS HalfOfMonth1,
(DATEDIFF(d, SomeDate, DATEADD(month, 1, SomeDate)) + 1) / 2 AS HalfOfMonth2
FROM Months
Output:
FirstDate LastDate DaysBetween HalfOfMonth1 HalfOfMonth2
01/01/2018 31/01/2018 31 15 16
01/02/2018 28/02/2018 28 14 14
01/03/2018 31/03/2018 31 15 16
01/04/2018 30/04/2018 30 15 15
01/05/2018 31/05/2018 31 15 16
01/06/2018 30/06/2018 30 15 15
01/07/2018 31/07/2018 31 15 16
01/08/2018 31/08/2018 31 15 16
01/09/2018 30/09/2018 30 15 15
01/10/2018 31/10/2018 31 15 16
01/11/2018 30/11/2018 30 15 15
01/12/2018 31/12/2018 31 15 16
i have tried the following
SELECT DATEADD(dd, (datediff(DD, DATEADD(m, DATEDIFF(m, 0, GETDATE()), - 1), eomonth(getdate())) / 2), DATEADD(m, DATEDIFF(m, 0, GETDATE()), - 1)),
CEILING((datediff(DD, DATEADD(m, DATEDIFF(m, 0, GETDATE()), - 1), eomonth(getdate())) / 2.00))
An update to the answer
DECLARE #Date DATE ='2018-10-01'---'20180201'
SELECT DATEADD(DAY, CEILING((DAY(EOMONTH(#Date)) / 2.00)) - 1, #Date)
Here is a query that get start date of month and end date of month by using datediff you can find the number of day to add and subtract
Set #tdate = '02/10/2018';
Select DATEFROMPARTS(YEAR(#tdate),MONTH(#tdate),1) as startdate , dateadd(day,-1,DATEFROMPARTS(YEAR(#tdate),MONTH(#tdate)+1,1)) as enddate
Regards
How to get the previous week(s) in the month knowing the day .
for example if i have table like this :
emp_num trans_date
22 1-10-2015
22 5-10-2015
22 7-10-2015
22 11-10-2015
22 14-10-2015
22 19-10-2015
22 27-10-2015
Now every month has 4 weeks .
So i have a date like 11-10-2015 (in the second week)
i want to get the result of all previous weeks in the same month .
so in this example i want the result of the first week in Oct month like this :
emp_num trans_date
22 1-10-2015
22 5-10-2015
22 7-10-2015
Note :
The start day of the week is: sat
The end day of the week is:Fri
If I understand your question correctly, for October 2015, you anticipate the following results:
RunDate Weekday Result
01-10-2015 Thurs [nothing]
02-10-2015 Fri [nothing]
03-10-2015 Sat 01-10-2015, 02-10-2015
04-10-2015 Sun 01-10-2015, 02-10-2015 (same as above)
...
09-10-2015 Fri 01-10-2015, 02-10-2015 (same as above)
10-10-2015 Sat 01-10-2015, ... , 09-10-2015
...
16-10-2015 Fri 01-10-2015, ... , 09-10-2015 (same as above)
17-10-2015 Sat 01-10-2015, ... , 16-10-2015
20-10-2015 Tue 01-10-2015, ... , 16-10-2015 (same as above)
30-10-2015 Fri 01-10-2015, ... , 23-10-2015
31-10-2015 Sat 01-10-2015, ... , 30-10-2015
If that is the case, then the following query will do what you require:
SELECT trans_date, emp_num, COUNT(1)
FROM transaction_table
WHERE MONTH(trans_date) = MONTH(TODAY)
AND YEAR(trans_date) = YEAR(TODAY)
AND trans_date <= DECODE(WEEKDAY(TODAY),
6, TODAY -1,
TODAY - WEEKDAY(TODAY) -2)
GROUP BY 1, 2
ORDER BY 1, 2
The logic in the DECODE() is to manage the offset from the default behaviour of WEEKDAY(), where Sun => 0 and Sat => 6. The keyword TODAY in the query above can be replaced with a variable or any arbitrary single date.
I havent worked in informix but here is how it looks like in SQL:
DECLARE #SomeDate DATE
SET #SomeDate = '2015-10-11'
DECLARE #DayOfWeek INT
SELECT #DayOfWeek = ((DATEPART(dw, #SomeDate) ) % 7)
DECLARE #WeekStart DATE
SELECT #WeekStart = DATEADD(d, -#DayOfWeek, #SomeDate)
SELECT * FROM SomeTable
WHERE MONTH(trans_date) = MONTH(#SomeDate) AND trans_date < #WeekStart