SQL QUERY FROM 25(LAST MONTH) to 25(CURRENT MONTH) - sql

I would like a query that would include from day 25 of last month to 25 of current month. Example: 25/12/2017-25/01/2018
I can't do something like transaction_date >= getdate()-31 because there are months that have 28,29 days.
Thanks!

You could use:
SELECT *
FROM your_tab
WHERE transaction_date
BETWEEN DATEFROMPARTS(IIF(MONTH(GETDATE()) = 1,YEAR(GETDATE())-1,YEAR(GETDATE())),
IIF(MONTH(GETDATE()) = 1, 12 , MONTH(GETDATE())-1)
,25)
AND DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 25);

One easy way
where
transaction_date between dateadd(dd, 25, eomonth(getdate(),-2))
and dateadd(dd, 25, eomonth(getdate(),-1))

I suggest DATEFROMPARTS to make a date with a set day, and subtract 1 month from the beginning:
WHERE [transaction_date] BETWEEN DATEADD(month, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 25)) AND DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 25)

You can use datetime functions to substract a month from a date:
-- Feb 2016 is 29 days
select dateadd(month, -1, '2016-01-25 00:00')
>> 2015-12-25 00:00:00.000
select dateadd(month, -1, '2016-02-25 00:00')
>> 2016-01-25 00:00:00.000
select dateadd(month, -1, '2016-03-25 00:00')
>> 2016-02-25 00:00:00.000
-- Feb 2017 is 28 days
select dateadd(month, -1, '2017-01-25 00:00')
>> 2016-12-25 00:00:00.000
select dateadd(month, -1, '2017-02-25 00:00')
>> 2017-01-25 00:00:00.000
select dateadd(month, -1, '2017-03-25 00:00')
>> 2017-02-25 00:00:00.000
declare #thatDate datetime = '2017-01-25 00:00'
select *
from ThisTable
where ThisDate between dateadd(month, -1, #thatDate) and #thatDate

If you are on mysql this might work:
SELECT *
FROM SOME_TABLE
WHERE transaction_date
BETWEEN
DATE_FORMAT(NOW(), '%Y-%m-25') - INTERVAL 1 MONTH
AND
DATE_FORMAT(NOW(), '%Y-%m-25')

You could do something along the lines of:
Select fields from table
where whateverDate > '25/12/2017' and
whateverDate < '25/01/2018'

Related

Get every 2 weeks on particular days SQL Server

I have a query getting the days in particular day that I selected and show the days in a month. My problem is that I need every two weeks of the month. And I also need to get long date format: dddd, dd MMMM yyyy and eliminate the time. Please help me.
DECLARE #startDate DATETIME = '9/1/2019'
DECLARE #endDate DATETIME = '12/31/2019'
DECLARE #dayOfWeek INT = 1;
WITH cte_Recursion AS
(
SELECT #startDate AS [Date]
UNION ALL
SELECT DATEADD(DAY, 1, [Date])
FROM cte_Recursion
WHERE [Date] < #endDate
)
SELECT [Date]
FROM cte_Recursion
WHERE DATEPART(WEEKDAY, [Date]) = #dayOfWeek
OPTION (MAXRECURSION 0)
The data returned looks like this:
2019-09-01 00:00:00.000
2019-09-08 00:00:00.000
2019-09-15 00:00:00.000
2019-09-22 00:00:00.000
2019-09-29 00:00:00.000
2019-10-06 00:00:00.000
2019-10-13 00:00:00.000
2019-10-20 00:00:00.000
2019-10-27 00:00:00.000
2019-11-03 00:00:00.000
2019-11-10 00:00:00.000
2019-11-17 00:00:00.000
2019-11-24 00:00:00.000
And I need to get like this (every other week):
2019-09-01 00:00:00.000
2019-09-15 00:00:00.000
2019-09-29 00:00:00.000
2019-10-13 00:00:00.000
2019-10-27 00:00:00.000
2019-11-10 00:00:00.000
2019-11-24 00:00:00.000
By changing your CTE to start on the correct day of the week, you can then change the recursion to add 14 days instead of 1, giving you the desired result without further manipulation:
DECLARE #startDate DATETIME = '9/1/2019'
DECLARE #endDate DATETIME = '12/31/2019'
DECLARE #dayOfWeek INT = 1;
WITH cte_Recursion AS
(SELECT DATEADD(DAY, ((#dayOfWeek - DATEPART(WEEKDAY, #startDate)) % 7 + 7) %7, #startDate) AS [Date]
UNION ALL SELECT DATEADD(DAY, 14, [Date])
FROM cte_Recursion
WHERE DATEADD(DAY, 14, [Date]) < #endDate)
SELECT [Date] FROM cte_Recursion
Output:
Date
01/09/2019 00:00:00
15/09/2019 00:00:00
29/09/2019 00:00:00
13/10/2019 00:00:00
27/10/2019 00:00:00
10/11/2019 00:00:00
24/11/2019 00:00:00
08/12/2019 00:00:00
22/12/2019 00:00:00
Demo on dbfiddle
To change the date format to dddd, dd MMMM yyyy, simply replace the final SELECT with:
SELECT FORMAT([Date], 'dddd, dd MMMM yyyy') AS [Date] FROM cte_Recursion
Output:
Date
Sunday, 01 September 2019
Sunday, 15 September 2019
Sunday, 29 September 2019
Sunday, 13 October 2019
Sunday, 27 October 2019
Sunday, 10 November 2019
Sunday, 24 November 2019
Sunday, 08 December 2019
Sunday, 22 December 2019
Demo on dbfiddle
you can use it :
DECLARE #startDate DATETIME = '9/1/2019'
DECLARE #endDate DATETIME = '12/31/2019'
DECLARE #dayOfWeek INT = 1;
WITH cte_Recursion AS
(
SELECT #startDate AS [Date]
UNION ALL SELECT DATEADD(DAY, 1, [Date])
FROM cte_Recursion WHERE [Date] < #endDate
)
SELECT [Date] FROM cte_Recursion
WHERE DATEPART(WEEKDAY, [Date]) = #dayOfWeek
and DATEPART(WEEK, [Date]) % 2 = 0
OPTION (MAXRECURSION 0)
You could use a recursive CTE as
WITH CTE AS
(
SELECT '2019-09-01 00:00:00.000' ADate
UNION SELECT '2019-09-08 00:00:00.000'
UNION SELECT '2019-09-15 00:00:00.000'
UNION SELECT '2019-09-22 00:00:00.000'
UNION SELECT '2019-09-29 00:00:00.000'
UNION SELECT '2019-10-06 00:00:00.000'
UNION SELECT '2019-10-13 00:00:00.000'
UNION SELECT '2019-10-20 00:00:00.000'
UNION SELECT '2019-10-27 00:00:00.000'
UNION SELECT '2019-11-03 00:00:00.000'
UNION SELECT '2019-11-10 00:00:00.000'
UNION SELECT '2019-11-17 00:00:00.000'
UNION SELECT '2019-11-24 00:00:00.000'
),
F AS
(
SELECT CAST('2019-09-01 00:00:00.000' AS DATETIME) ADate
UNION ALL
SELECT DATEADD(Day, 14, F.ADate)
FROM F
WHERE ADate < '2019-11-24 00:00:00.000'
)
SELECT *
FROM F;

Extract only dates for first Day of Month from a daily Date Dimension Table without nesting

I am using SQL Server 2014 and I have the following T-SQL query which retrieves the dates of the first day of each month (based on my filters) from a Date Dimension Table:
SELECT * FROM (
SELECT DATEADD(month, DATEDIFF(month, 0, [date]), 0) AS [Date2]
FROM DateDimension
WHERE [date] BETWEEN '2018-07-01' AND '2019-06-01'
) x
GROUP BY x.[Date2]
The output is as follows:
Date2
2018-07-01 00:00:00.000
2018-08-01 00:00:00.000
2018-09-01 00:00:00.000
2018-10-01 00:00:00.000
2018-11-01 00:00:00.000
2018-12-01 00:00:00.000
2019-01-01 00:00:00.000
2019-02-01 00:00:00.000
2019-03-01 00:00:00.000
2019-04-01 00:00:00.000
2019-05-01 00:00:00.000
2019-06-01 00:00:00.000
I have used a nested query to achieve this. My question is whether I can achieve the same result without using the nested query. My Date Dimension table is a table with daily dates.
Just repeat the date calculation part inside GROUP BY:
SELECT DATEADD(month, DATEDIFF(month, 0, [date]), 0) AS [Date2]
FROM DateDimension
WHERE [date] between '2018-07-01' and '2019-06-01'
GROUP BY DATEADD(month, DATEDIFF(month, 0, [date]), 0)
PS: this:
DATEADD(month, DATEDIFF(month, 0, [date]), 0)
could be written as:
DATEADD(DAY, 1, EOMONTH([date], -1))
Can't we just write this with a distinct,
SELECT DISTINCT DATEADD(month, DATEDIFF(month, 0, [date]), 0) AS [Date2]
FROM DateDimension
where [date] between '2018-07-01' and '2019-06-01'

Filtering data from the previous day using DateTime values

I am trying to retrieve data for yesterday's shift using SQL Server 2008 r2.
The shift starts at 20:00 pm, and ends 10:00 am following day.
What date function can I use to retrieve data for the entire shift?
Using this:
CAST([LastStartedDate] as time)> cast('20:00' as Time)
Will only retrieve data up to midnight.
You can filter your dates with a WHERE clause that uses some date manipulation like so:
WHERE LastStartedDate >= DATEADD(HOUR, 20,
CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME));
This first gets yesterdays date, as a DATE so it removes the time portion:
SELECT CAST(DATEADD(DAY, -1, GETDATE()) AS DATE)
-- 2017-03-06
Then converts it back to a DATETIME to add the time as midnight of that day:
SELECT CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME)
-- 2017-03-06 00:00:00.000
Then it adds 20 hours to get you to 20:00 - 8.00PM:
SELECT DATEADD(HOUR, 20,CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME));
-- 2017-03-06 20:00:00.000
For your scenario, you need to do the same again to get the 10am cut off too and use BETWEEN.
Example:
CREATE TABLE #shift
(
LastStartedDate DATETIME ,
WorkItemsDone INT
);
INSERT INTO #shift
( LastStartedDate, WorkItemsDone )
VALUES ( DATEADD(HOUR, -18, GETDATE()), 10 ),
( DATEADD(HOUR, -15, GETDATE()), 20 ),
( DATEADD(HOUR, -14, GETDATE()), 30 ),
( DATEADD(HOUR, -10, GETDATE()), 40 ),
( DATEADD(HOUR, -5, GETDATE()), 25 ),
( DATEADD(HOUR, -2, GETDATE()), 15 ),
( DATEADD(HOUR, 4, GETDATE()), 5 ),
( DATEADD(HOUR, 10, GETDATE()), 15 );
-- all data
SELECT *
FROM #shift
-- limited data
SELECT *
FROM #shift
WHERE LastStartedDate BETWEEN
DATEADD(HOUR, 20, CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME))
AND DATEADD(HOUR, 10, CAST(CAST(GETDATE() AS DATE) AS DATETIME))
DROP TABLE #shift;
Produces:
-- all data
LastStartedDate WorkItemsDone
2017-03-06 16:18:04.877 10
2017-03-06 19:18:04.877 20
2017-03-06 20:18:04.877 30
2017-03-07 00:18:04.877 40
2017-03-07 05:18:04.877 25
2017-03-07 08:18:04.877 15
2017-03-07 14:18:04.877 5
2017-03-07 20:18:04.877 15
-- filtered data
LastStartedDate WorkItemsDone
2017-03-06 20:18:04.877 30
2017-03-07 00:18:04.877 40
2017-03-07 05:18:04.877 25
2017-03-07 08:18:04.877 15

How can i get the First Date and Last Date between selected months?

How can i get the First Date and Last Date between selected months?
For example I Enter year 2015, and month 09 to 2016 08
The return values must be:
StartDate EndDate
20150901 20150930
20151001 20151031
20151101 20151130
20151201 20151231
20160101 20160131
20160201 20160229
20160301 20160331
20160401 20160430
20160501 20160531
20160601 20160630
20160701 20160731
20160801 20160831
I've found multiple queries that do the same but just for 1 inserted date. for example:
DECLARE #mydate DATETIME
SELECT #mydate = GETDATE()
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(#mydate)-1),#mydate),101) AS Date_Value,
'First Day of Current Month' AS Date_Type
UNION
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,#mydate))),DATEADD(mm,1,#mydate)),101) ,
'Last Day of Current Month'
But I couldn't find one that can do this for Between statement
I have two udf's which can be used independently or in conjunction. They dynamically create date ranges with variable dateparts and/or increments.
Select * from [dbo].[udf-Create-Range-Date-Span]('2015-09-01','2016-08-01','MM',1)
DateR1 DateR2
2015-09-01 00:00:00.000 2015-10-01 00:00:00.000
2015-10-01 00:00:00.000 2015-11-01 00:00:00.000
2015-11-01 00:00:00.000 2015-12-01 00:00:00.000
2015-12-01 00:00:00.000 2016-01-01 00:00:00.000
2016-01-01 00:00:00.000 2016-02-01 00:00:00.000
2016-02-01 00:00:00.000 2016-03-01 00:00:00.000
2016-03-01 00:00:00.000 2016-04-01 00:00:00.000
2016-04-01 00:00:00.000 2016-05-01 00:00:00.000
2016-05-01 00:00:00.000 2016-06-01 00:00:00.000
2016-06-01 00:00:00.000 2016-07-01 00:00:00.000
2016-07-01 00:00:00.000 2016-08-01 00:00:00.000
Now, I specifically use the cap so I can query data (including time) which are between the DateR1 and DateR2 and
However, with a little twist, you can change the output. For example:
Select DateR1=cast(DateR1 as Date),DateR2=DateAdd(DD,-1,cast(DateR2 as Date)) from [dbo].[udf-Create-Range-Date-Span]('2015-09-01','2016-08-01','MM',1)
DateR1 DateR2
2015-09-01 2015-09-30
2015-10-01 2015-10-31
2015-11-01 2015-11-30
2015-12-01 2015-12-31
2016-01-01 2016-01-31
2016-02-01 2016-02-29
2016-03-01 2016-03-31
2016-04-01 2016-04-30
2016-05-01 2016-05-31
2016-06-01 2016-06-30
2016-07-01 2016-07-31
The two function are as follows:
CREATE FUNCTION [dbo].[udf-Create-Range-Date] (#DateFrom datetime,#DateTo datetime,#DatePart varchar(10),#Incr int)
Returns
#ReturnVal Table (RetVal datetime)
As
Begin
With DateTable As (
Select DateFrom = #DateFrom
Union All
Select Case #DatePart
When 'YY' then DateAdd(YY, #Incr, df.dateFrom)
When 'QQ' then DateAdd(QQ, #Incr, df.dateFrom)
When 'MM' then DateAdd(MM, #Incr, df.dateFrom)
When 'WK' then DateAdd(WK, #Incr, df.dateFrom)
When 'DD' then DateAdd(DD, #Incr, df.dateFrom)
When 'HH' then DateAdd(HH, #Incr, df.dateFrom)
When 'MI' then DateAdd(MI, #Incr, df.dateFrom)
When 'SS' then DateAdd(SS, #Incr, df.dateFrom)
End
From DateTable DF
Where DF.DateFrom < #DateTo
)
Insert into #ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)
Return
End
AND
CREATE FUNCTION [dbo].[udf-Create-Range-Date-Span] (#Date1 datetime,#Date2 datetime,#DatePart varchar(10),#Incr int)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-10-01','2020-10-01','YY',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-01-01','2016-12-31','MM',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-10-01','2016-10-31','MI',15)
-- Syntax Select * from [dbo].[udf-Create-Range-Date-Span]('2016-10-01','2016-10-02','SS',1)
Returns Table
As
Return (
Select DateR1 = RetVal
,DateR2 = LEAD(RetVal,1,#Date2) OVER (ORDER BY RetVal)
From (Select * from [dbo].[udf-Create-Range-Date](#Date1,#Date2,#DatePart,#Incr) ) A
Where RetVal<#Date2
)
You don't need UDFs for this - You can do this with a single query:
Declare #FromYear Int = 2015,
#FromMonth Int = 9,
#ToYear Int = 2016,
#ToMonth Int = 8
Declare #FromDate Date = (Select DateAdd(Year, #FromYear - 1900, DateAdd(Month, #FromMonth - 1, 0))),
#ToDate Date = (Select DateAdd(Year, #ToYear - 1900, DateAdd(Month, #ToMonth - 1, 0)))
;With Date (Date) As
(
Select #FromDate Union All
Select DateAdd(Month, 1, Date)
From Date
Where Date < #ToDate
)
Select Convert(Varchar, Year(Date)) + Right('00' + Convert(Varchar, Month(Date)), 2) + Right('00' + Convert(Varchar, Day(Date)), 2) As StartDate,
Convert(Varchar, Year(Date)) + Right('00' + Convert(Varchar, Month(Date)), 2) + Right('00' + Convert(Varchar, Day(DateAdd(Day, -1, DateAdd(Month, DateDiff(Month, 0, Date) + 1, 0)))), 2) As EndDate
From Date
Option (MaxRecursion 0)
Output
StartDate EndDate
20150901 20150930
20151001 20151031
20151101 20151130
20151201 20151231
20160101 20160131
20160201 20160229
20160301 20160331
20160401 20160430
20160501 20160531
20160601 20160630
20160701 20160731
20160801 20160831
If you're able to move to SQL Server 2012 or later, however, the query is much simpler:
Declare #FromYear Int = 2015,
#FromMonth Int = 9,
#ToYear Int = 2016,
#ToMonth Int = 8
Declare #FromDate Date = DateFromParts(#FromYear, #FromMonth, 1),
#ToDate Date = DateFromParts(#ToYear, #ToMonth, 1)
;With Date (Date) As
(
Select #FromDate Union All
Select DateAdd(Month, 1, Date)
From Date
Where Date < #ToDate
)
Select Format(Date, N'yyyyMMdd') As StartDate,
Format(EoMonth(Date), N'yyyyMMdd') As EndDate
From Date
Option (MaxRecursion 0)
Try this. Its also a very small script. I like the idea of the CTE from Siyual. But this is much shorter.
DECLARE #inputYear INT = 2015,
#inputMonth INT = 09
SELECT DATEADD(MONTH, #inputMonth-1, DATEADD(YEAR, #inputYear-1900, 0)) AS FirstDayOfTheMonth,
DATEADD(s,-1, DATEADD(MONTH, #inputMonth, DATEADD(YEAR, #inputYear-1900, 0))) AS LastDayOfTheMonth
Your task is also possible using one single ANSI sql statement.
However, you need two tables ALL_YEARS and ALL_MONTHS that contain the used set of years and month.
E.g. if you consider possible years between 1900 and 2099, the table ALL_YEARS must contain the numbers between 1900 and 2099.
The table ALL_MONTHS must contain the numbers between 1 and 12.
Using these two tables, the statement looks as follows:
select to_date('01.' || to_char(all_months.month_value) || '.' || to_char(all_years.year_value ), 'dd.mm.yyyy') first_day ,
add_months(to_date('01.' || to_char(all_months.month_value) || '.' || to_char(all_years.year_value ), 'dd.mm.yyyy'), 1) -1 last_day
from all_years,
all_months
where to_date('01.' || to_char(all_months.month_value) || '.' || to_char(all_years.year_value ), 'dd.mm.yyyy') between
to_date('01.02.2014', 'dd.mm.yyyy') and
to_date('01.07.2016', 'dd.mm.yyyy');
The output is as follows:
01.02.14 28.02.14
01.03.14 31.03.14
01.04.14 30.04.14
01.05.14 31.05.14
01.06.14 30.06.14
...
01.06.16 30.06.16
01.07.16 31.07.16

find records from previous x days?

How can I come up with a stored procedure that selects results for past 30 days?
where MONTH(RequestDate) > 6 and DAY(RequestDate) >= 10
and MONTH(RequestDate) < 21 and DAY(RequestDate) < 7
SELECT *
FROM Table
WHERE GETDATE() >= DATEADD(DAY, -30, GETDATE())
Substitute the first GETDATE() with the appropriate column name.
SELECT *
FROM Table
WHERE Table.ColumnName >= DATEADD(DAY, -30, GETDATE())
Are you looking for last 30 days or last month? To find start and end of each month ("generic" as your comment says), use:
select dateadd(month,datediff(month,0,getdate()),0),
dateadd(mm,datediff(mm,-1,getdate()),-1)
Something like this?
CREATE PROC GetSomeHistory
#NumDaysPrevious int
AS
BEGIN
SELECT * FROM MyTable
WHERE RequestDate BETWEEN DATEADD(dd, -1 * #NumDaysPrevious, getdate())
AND getdate();
END
......
EXEC GetSomeHistory 55;
SELECT *
FROM Table
WHERE myDate >= DATEADD(MONTH, -1, GETDATE())
doing it by month is different than doing it in 30-day blocks. Test this out as follows...
declare #mydate smalldatetime
set #mydate = '07/6/01'
select #mydate
select DATEADD(month, 2, #mydate), DATEDIFF(day, DATEADD(month, 2, #mydate), #mydate)
select DATEADD(month, 1, #mydate), DATEDIFF(day, DATEADD(month, 1, #mydate), #mydate)
select DATEADD(month, -1, #mydate), DATEDIFF(day, DATEADD(month, -1, #mydate), #mydate)
select DATEADD(month, -2, #mydate), DATEDIFF(day, DATEADD(month, -2, #mydate), #mydate)
select DATEADD(month, -3, #mydate), DATEDIFF(day, DATEADD(month, -3, #mydate), #mydate)
Here are the results:
2001-07-06 00:00:00
2001-09-06 00:00:00 | -62
2001-08-06 00:00:00 | -31
2001-06-06 00:00:00 | 30
2001-06-06 00:00:00 | 30
2001-05-06 00:00:00 | 61
2001-04-06 00:00:00 | 91