Related
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'
i am trying to write a sql query for getting the every day of the week.
like if i run SELECT GETDATE() i am getting today'day date if run the getdate()-1 i am getting only column with yesterday date. Instead i want to get the every day in a week in different columns, someone please help with the SQL. Any help will be appreciated.
try this:
SELECT DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) Monday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 1 Tuesday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 2 Wednsday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 3 Thursday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 4 Friday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 5 Saturday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 6 Sunday;
Does this work?
SELECT
Day1 = CAST(getdate() AS date),
Day2 = CAST(getdate()+1 AS date),
Day3 = CAST(getdate()+2 AS date),
Day4 = CAST(getdate()+3 AS date),
Day5 = CAST(getdate()+4 AS date),
Day6 = CAST(getdate()+5 AS date),
Day7 = CAST(getdate()+6 AS date);
Returns:
Day1 Day2 Day3 Day4 Day5 Day6 Day7
---------- ---------- ---------- ---------- ---------- ---------- ----------
2017-06-26 2017-06-27 2017-06-28 2017-06-29 2017-06-30 2017-07-01 2017-07-02
If this is not what you are looking for can you post what you want your query to return?
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?
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
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