I have the current declared date parameters and "DATE" expression shown below. It provides the data in terms of date only, excluding the 'by hour' detail. I would like to change the below code to add the hour detail to the "DATE" field.
I'm an amateur in terms of SQL, so any suggestions help.
Here is the code...
Declare #Start_Date datetime, #End_Date datetime
set #Start_Date = DATEADD(DAY, DATEDIFF(DAY, '19000101', GETDATE()), '19000101')
set #End_Date = DATEADD(s,-1,DATEADD(dd, DATEDIFF(d,0,GETDATE())+7,0))
;
--Common Table Express1on (CTE) to get dates*****
With DateSequence( [Date] ) as
( Select #Start_Date as [Date]
union all
Select dateadd(day, 1, [Date])
from DateSequence
where Date < #End_Date)
Thanks in advance!
-Matt
Just add 1 hour instead of 1 day:
with DateHourSequence as (
select #Start_Date as yyyymmddhh
union all
select dateadd(hour, 1, yyyymmddhh)
from DateHourSequence
where yyyymmddhh < #End_Date
)
Related
While searching for a method to create date ranges I came across a problem with the following query:
DECLARE #StartDate DateTime = '2000-01-01 01:00';
DECLARE #EndDate DateTime = '2020-01-01 00:00';
with Dates as (
select
#StartDate fromDate
UNION ALL
(Select
fromDate = dateadd(day, 1, #EndDate)
from
Dates
where
fromDate >= #StartDate AND
fromDate < #EndDate ))
Select * from Dates
OPTION (MAXRECURSION 0);
The following query returns two rows, one of which is outside of the range,
fromDate
-----------------------
2000-01-01 01:00:00.000
2020-01-02 00:00:00.000
I am aware that there is a way to fix this issue by changing the second half of the query to be different, for example:
Select * from Dates Where fromDate <= #EndDate
I have the following questions:
what is wrong with the query as is?
Why is it that this query returns two values, one of which lies outside the range provided?
This is using Microsoft SQL Server 2008 R2
Because your Recursive CTE add one day from fromDate
Select
fromDate = dateadd(day, 1, #EndDate)
but your condition filter fromDate
where
fromDate >= #StartDate AND
fromDate < #EndDate ))
If you want to do make calendar table by Recursive CTE.
you can try this.
with Dates as (
select #StartDate fromDate,#EndDate endDate
UNION ALL
Select
fromDate = dateadd(day, 1, fromDate),endDate
from
Dates
where
dateadd(day, 1, fromDate) <= #EndDate
)
Select * from Dates
OPTION (MAXRECURSION 0);
The simple answer for #1 / #2: You are selecting DATEADD(day, 1, #endDate) -- which, by definition, is 1 day 'over' your date range.
The real answer: To get the result you want, change:
(Select
fromDate = dateadd(day, 1, #EndDate)
To:
(Select
fromDate = dateadd(day, 1, fromDate)
Im looking for a way if the user selects
#startdate = '12-01-2015'
then
#enddate = #startdate + 1 Week
this is for my parameter, but please be aware my report is a matrix and uses each week for a sample of data so the parameter needs to automatically select
its enddate from all startdates selected
i.e
startdates in ( '12-01-2015', '19-01-2015')
then endate in ( '18-01-2015', '26-01-2015')
this is what im using for my startdate parameter
select distinct
CAST(startdate AS DATE) as Startdate
FROM [Calendar]
where DatePart(YEAR,startdate) >= 2014
order by 1 asc
Use DATEADD
#startdate = '12-01-2015'
then
#enddate = DATEADD(wk, 1, #startdate)
or if startdate variable has DATE/DATETIME type
#startdate = '12-01-2015'
then
#enddate = #startdate + 7; -- Implicit cast add 7 days
EDIT:
select distinct
CAST(startdate AS DATE) as Startdate,
DATEADD(wk, 1, CAST(startdate AS DATE)) as EndDate
FROM [Calendar]
where DatePart(YEAR,startdate) >= 2014
order by 1 asc
Is it possible to do in SQL: for example I have period where #s_date = '20130101' and #e_date = '20130601' and I want to select all last days of months in this period.
This is example of result:
20130131
20130228
20130331
20130430
20130531
Thanks.
The easiest option is to have a calendar table, with a last day of the month flag, so your query would simply be:
SELECT *
FROM dbo.Calendar
WHERE Date >= #StartDate
AND Date <= #EndDate
AND EndOfMonth = 1;
Assuming of course that you don't have a calendar table you can generate a list of dates on the fly:'
DECLARE #s_date DATE = '20130101',
#e_date DATE = '20130601';
SELECT Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY Object_ID) - 1, #s_date)
FROM sys.all_objects;
Then once you have your dates you can limit them to where the date is the last day of the month (where adding one day makes it the first of the month):
DECLARE #s_date DATE = '20130101',
#e_date DATE = '20130601';
WITH Dates AS
( SELECT Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY Object_ID) - 1, #s_date)
FROM sys.all_objects
)
SELECT *
FROM Dates
WHERE Date <= #e_Date
AND DATEPART(DAY, DATEADD(DAY, 1, Date)) = 1;
Example on SQL Fiddle
You can run the following query and then adjust it by using your table details:
declare #s_date as datetime= '20130101'
declare #e_date as datetime= '20131020'
SELECT DateAdd(m, number, '1990-01-31')
FROM master.dbo.spt_values
WHERE 'P' = type
AND DateAdd(m, number, #s_date) < #e_date
example for 20130101 :
select CONVERT(VARCHAR(8),
dateadd(day, -1, dateadd(month, 1,
convert(datetime, '20130101',112))), 112)
result :
20130131
Try this query
WITH sample
AS (SELECT Cast('2013-04-01' AS DATETIME) Date
UNION ALL
SELECT Dateadd(day, 1, date) dt
FROM sample
WHERE date < Cast('2013-05-05' AS DATETIME))
SELECT *
FROM sample
Fiddle
EOMONTH(#date) is the function you need.
Here is the help page https://learn.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql?view=sql-server-2017
This query gets the las 50 End Of Months.
The original query used as an example is from here.
https://dba.stackexchange.com/a/186829
WITH cte AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) - 1 AS [Incrementor]
FROM [master].[sys].[columns] sc1
CROSS JOIN [master].[sys].[columns] sc2
)
SELECT top 50 EOMONTH(DATEADD(Month, -1 * cte.[Incrementor], GETDATE()))
FROM cte
WHERE EOMONTH(DATEADD(Month, -1 * cte.[Incrementor], GETDATE())) < GETDATE();
I want to split date range in months. I will pass startdate(1-jan-2011) and enddate(31-dec-2011) as a parameter then it must return result like
1-jan-2011 - 31-jan-2011
1-feb-2011 - 28-feb-2011
1-mar-2011 - 31-mar-2011
Please send me a stored procedure.....
Thanks,
Abhishek
Try this:
CREATE PROC SplitDateRange
#from DATETIME,
#to DATETIME
AS
BEGIN
SET NOCOUNT ON;
SET #from = CONVERT(VARCHAR, DATEADD(DAY, -DATEPART(DAY, #from)+1, #from), 112)
-- Sql 2000
CREATE TABLE #temp (DateFrom DATETIME, DateTo DATETIME)
WHILE #from < #to
BEGIN
INSERT #temp VALUES (#from, DATEADD(DAY, -1, DATEADD(MONTH, 1, #from)))
SET #from = DATEADD(MONTH, 1, #from)
END
SELECT * FROM #temp
DROP TABLE #temp
--sql 2005+
/*
;WITH Ranges(DateFrom, DateTo) AS
(
SELECT #from DateFrom, DATEADD(DAY, -1, DATEADD(MONTH, 1, #from)) DateTo
UNION ALL
SELECT DATEADD(MONTH, 1, DateFrom), DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(MONTH, 1, DateFrom)))
FROM Ranges
WHERE DateFrom < DATEADD(MONTH, -1, #To)
)
SELECT * FROM Ranges
OPTION(MAXRECURSION 0)
*/
END
GO
EXEC SplitDateRange '2011-01-02', '2012-06-06'
So that you can use the results in another SQL Query (which I assume is where you're going) I'd put that into a table valued function.
Assuming SQL Server 2005+ you could use this...
CREATE FUNCTION dbo.ufnMonthlyIntervals(
#from_date SMALLDATETIME,
#end_date SMALLDATETIME
)
RETURNS TABLE
WITH
intervals (
from_date,
end_date
)
AS
(
SELECT #from_date, DATEADD(MONTH, 1, #from_date ) - 1
UNION ALL
SELECT end_date + 1, DATEADD(MONTH, 1, end_date + 1) - 1 FROM intervals WHERE end_date < #end_date
)
RETURN
SELECT
from_date,
CASE WHEN end_date > #end_date THEN #end_date ELSE end_date END AS end_date
FROM
intervals
Then you just use SELECT * FROM dbo.ufnMonthlyIntervals('20110101', '20111201') AS intervals
Using SQL Server 2005 I have a field that contains a datetime value.
What I am trying to do is create 2 queries:
Compare to see if stored datetime is of the same month+year as current date
Compare to see if stored datetime is of the same year as current date
There is probably a simple solution but I keep hitting brick walls using various samples I can find, any thoughts?
Thanks in advance.
Compare the parts of the date:
WHERE YEAR( columnName ) = YEAR( getDate() )
While the other answers will work, they all suffer from the same problem: they apply a transformation to the column and therefore will never utilize an index on that column.
To search the date without a transformation, you need a couple built-in functions and some math. Example below:
--create a table to hold our example values
create table #DateSearch
(
TheDate datetime not null
)
insert into #DateSearch (TheDate)
--today
select getdate()
union all
--a month in advance
select dateadd(month, 1, getdate())
union all
--a year in advance
select dateadd(year, 1, getdate())
go
--declare variables to make things a little easier to see
declare #StartDate datetime, #EndDate datetime
--search for "same month+year as current date"
select #StartDate = dateadd(month, datediff(month, 0, getdate()), 0), #EndDate = dateadd(month, datediff(month, 0, getdate()) + 1, 0)
select #StartDate [StartDate], #EndDate [EndDate], TheDate from #DateSearch
where TheDate >= #StartDate and TheDate < #EndDate
--search for "same year as current date"
select #StartDate = dateadd(year, datediff(year, 0, getdate()), 0), #EndDate = dateadd(year, datediff(year, 0, getdate()) + 1, 0)
select #StartDate [StartDate], #EndDate [EndDate], TheDate from #DateSearch
where TheDate >= #StartDate and TheDate < #EndDate
What the statement does to avoid the transformations, is find all values greater-than or equal-to the beginning of the current time period (month or year) AND all values less-than the beginning of the next (invalid) time period. This solves our index problem and also mitigates any issues related to 3ms rounding in the DATETIME type.
SELECT * FROM atable
WHERE
YEAR( adate ) = YEAR( GETDATE() )
AND
MONTH( adate ) = MONTH( GETDATE() )
It sounds to me like DATEDIFF is exactly what you need:
-- #1 same month and year
SELECT *
FROM your_table
WHERE DATEDIFF(month, your_column, GETDATE()) = 0
-- #2 same year
SELECT *
FROM your_table
WHERE DATEDIFF(year, your_column, GETDATE()) = 0
The datepart function lets you pull the bits you need:
declare #d1 as datetime
declare #d2 as datetime
if datepart(yy, #d1) = datepart(yy, #d2) and datepart(mm, #d1) = datepart(mm, #d2) begin
print 'same'
end
You can use something like this
a)
select *
from table
where MONTH(field) = MONTH(GetDATE())
and YEAR(field) = YEAR(GetDATE())
b)
select *
from table
where YEAR(field) = YEAR(GetDATE())