Hi I have startdate as GetDate()-5 and enddate as GetDate()
I am passing this date in variable i.e. this dates are not stored in any table so how can I get records as
GetDate()-5,GetDate()-4,GetDate()-3,GetDate()-2,GetDate()-1,GetDate()
in sql server
I have tried below query which is totally wrong, Can any one please suggest me
declare #startdate date
declare #enddate date
set #startdate =GETDATE()-5
set #enddate =GETDATE()
STUFF((SELECT DISTINCT ','+CONVERT(VARCHAR, CONVERT(DATE,GETDATE()-5))
FROM [Table]--What should be here?
WHERE CONVERT(date,AETE.TimeEntryDate) between CONVERT(DATE,#startdate)
AND CONVERT(DATE, #enddate)
FOR XML PATH('')), 1,1,'')
A CTE might come in handy here:
declare #startdate date = dateadd(D, -5, getdate())
declare #enddate date = getdate();
with cte(d) as (
select #startdate
union all
select dateadd(D, 1, d)
from cte
where d < #enddate
)
select stuff((
select ', ' + convert(nvarchar(255), d, 101)
from cte
for xml path('')), 1, 2, '')
gives you:
08/09/2018, 08/10/2018, 08/11/2018, 08/12/2018, 08/13/2018, 08/14/2018
Note that this gives you 6 days---the 5 days less than today, as well as today's date.
Related
I have an SQL Statement which accepts a parameter #EndDate as DateTime. I want to be able to pass several values for #EndDate one by one and then Union the results of all the Queries. I have tried using CTE for this but it is of no use. I want to pass several Dates for #EndDate. Any help would be greatly appreciated.
My Query is:
DECLARE #EndDate as DateTime
SET #EndDate = '2018/02/25'
SELECT
CONVERT(VARCHAR, #EndDate, 101) [R_Date]
,[Name]
[Type]
FROM [dbo].[S_Table]
This is Sample query how u can loop through multiple dates. A while loop should select all rows into one table, do not need to perform union all
DECLARE #table TABLE (
day INT
,Month INT
,DATE DATE
)
DECLARE #startdate DATE = '2018/02/25'
DECLARE #enddate DATE = cast(getdate() AS DATE)
WHILE #startdate <= #enddate
BEGIN
SELECT #startdate = dateadd(dd, 1, #startdate)
INSERT #table (
day
,Month
,DATE
)
SELECT day(#startdate)
,MONTH(#startdate)
,#startdate
END
SELECT *
FROM #table;
In your logic for passing multiple values into query , you can store result set into temporal table, which holds looped records
DECLARE #table TABLE (
[R_Date] DATE
,Name VARCHAR(155)
,Value VARCHAR(155)
)
DECLARE #enddate DATE = '2018/02/25'
DECLARE #enddate1 DATE = cast(getdate() AS DATE)
WHILE #enddate <= #enddate1
BEGIN
SELECT #enddate = dateadd(dd, 1, #enddate)
INSERT #table (
R_Date
,Name
,Value
)
SELECT CONVERT(VARCHAR, #EndDate, 101) [R_Date]
,[Name] [Type]
FROM [dbo].[S_Table]
WHERE DATE = #enddate
-------More filters
END
SELECT *
FROM #table;
I've got a recursive cte working to generate a list of dates between #startDate and #endDate, incrementing by quarters.
declare #startDate datetime
declare #endDate datetime
set #startDate= '01-jan-2014'
set #endDate= '01-jul-2017'
;With cte
As
( Select #startDate date1
Union All
Select DateAdd(Month,3,date1) From cte where date1 < #endDate
) select cast(cast( Year(date1)*10000 + MONTH(date1)*100 + 1 as
varchar(255)) as date) quarterlyDates From cte
This yields:
quarterlyDates
--------------
2014-01-01
2014-04-01
2014-07-01
2014-10-01 ...
I'd like to concatenate the output of the cte into a single string as follows:
"'01-jan-2014', '01-apr-2014, '01-jul-2014'..."
etc. I'm baffled by this last step - any help would be greatly appreciated!
Not sure why you want to... but just wrap that bottom cte and use stuff.
declare #table table(quarterlyDates date)
insert into #table
values
('2014-01-01'),
('2014-04-01'),
('2014-07-01'),
('2014-10-01')
SELECT stuff((
SELECT ', ' + cast(quarterlyDates as varchar(max))
FROM #table
FOR XML PATH('')
), 1, 2, '')
And in your code... though the second CTE isn't necessary I leave it for clarity.
declare #startDate datetime
declare #endDate datetime
set #startDate= '01-jan-2014'
set #endDate= '01-jul-2017'
;With cte
As
( Select #startDate date1
Union All
Select DateAdd(Month,3,date1) From cte where date1 < #endDate
),
cte2 as(
select cast(cast( Year(date1)*10000 + MONTH(date1)*100 + 1 as
varchar(255)) as date) quarterlyDates From cte)
SELECT stuff((
SELECT ', ' + cast(quarterlyDates as varchar(max))
FROM cte2
FOR XML PATH('')
), 1, 2, '');
use FOR XML Path with type directive to avoid encoding of illegal characters in result
;WITH cte
AS (SELECT #startDate date1
UNION ALL
SELECT Dateadd(month, 3, date1)
FROM cte
WHERE date1 < #endDate)
SELECT Stuff((SELECT ',' + CONVERT(VARCHAR(15), date1, 106) quarterlyDates
FROM cte
FOR xml path, type).value('.[1]', 'nvarchar(max)'), 1, 1, '');
Note : I have altered the unwanted manipulating in the final select. Use style 106 in Convert function to get the required output format
Late answer and just for fun.
Example
declare #startDate datetime = '01-jan-2014'
declare #endDate datetime = '01-jul-2017'
;With cte
As
( Select date1 = #startDate
,dates = ''''+convert(varchar(max),convert(varchar(11),#startDate,113))+''''
Union All
Select DateAdd(Month,3,date1)
,cte.dates+','''+convert(varchar(11),DateAdd(Month,3,date1) ,106)+''''
From cte where date1 < #endDate
)
Select Top 1 with ties
Dates=lower(replace(Dates,' ','-') )
From cte
Order By Date1 Desc
Returns
'01-jan-2014','01-apr-2014','01-jul-2014','01-oct-2014','01-jan-2015','01-apr-2015','01-jul-2015','01-oct-2015','01-jan-2016','01-apr-2016','01-jul-2016','01-oct-2016','01-jan-2017','01-apr-2017','01-jul-2017'
I have been wondering is there any operator/function in sql server to tell about weekday between given day.
Example :11-19-2016 to 11-29-2016 I want check if there is tuesday between that day?
Try This:
declare #start varchar(100)='11-19-2016'
declare #end varchar(100)='11-29-2016'
;with dateRange as
(
select date = dateadd(dd, 1, #start)
where dateadd(dd, 1, #start) < #end
union all
select dateadd(dd, 1, date)
from dateRange
where dateadd(dd, 1, date) < #end
)
select date,DATENAME(dw,CAST(DATEPART(m, GETDATE()) AS VARCHAR)
+ '/'+ CAST(DATEPART(d, date) AS VARCHAR)
+ '/'+ CAST(DATEPART(yy, getdate()) AS VARCHAR)) as 'Day'
from dateRange where (DATENAME(dw,CAST(DATEPART(m, GETDATE()) AS VARCHAR)
+ '/'+ CAST(DATEPART(d, date) AS VARCHAR)
+ '/'+ CAST(DATEPART(yy, getdate()) AS VARCHAR)))='Tuesday'
The query below uses a recursive query to unfold the date range.
Then uses DATEPART to select only the Tuesdays from it.
But one could also use DATENAME instead.
declare #StartDate DATE = '2016-11-19';
declare #EndDate DATE = '2016-11-29';
--SET DATEFIRST 7;
-- The dw for tuesday is 3 when ##datefirst = 7 (default setting)
-- Since it depends on a usersetting, lets calculate it anyway.
declare #TuesdayWeekday INT = (7-##datefirst + 2)%7+1;
;with DATES as
(
select #startdate as [Date]
union all
select dateadd(day, 1, [Date]) from DATES
where [Date] < #enddate
)
select [Date], datepart(dw,[Date]) as day_of_week, datename(dw,[Date]) as day_of_weekname
from DATES
where datepart(dw,[Date]) = #TuesdayWeekday;
I'm building a Common Table Expression (CTE) in SQL Server 2008 to use in a PIVOT query.
I'm having difficulty sorting the output properly because there are numeric values that sandwich the string data in the middle. Is it possible to do this?
This is a quick and dirty example, the real query will span several years worth of values.
Example:
Declare #startdate as varchar(max);
Declare #enddate as varchar(max);
Set #startdate = cast((DATEPART(yyyy, GetDate())-1) as varchar(4))+'-12-01';
Set #enddate = cast((DATEPART(yyyy, GetDate())) as varchar(4))+'-03-15';
WITH DateRange(dt) AS
(
SELECT CONVERT(datetime, #startdate) dt
UNION ALL
SELECT DATEADD(dd,1,dt) dt FROM DateRange WHERE dt < CONVERT(datetime, #enddate)
)
SELECT DISTINCT ',' + QUOTENAME((cast(DATEPART(yyyy, dt) as varchar(4)))+'-Week'+(cast(DATEPART(ww, dt) as varchar(2)))) FROM DateRange
Current Output:
,[2012-Week48]
,[2012-Week49]
,[2012-Week50]
,[2012-Week51]
,[2012-Week52]
,[2012-Week53]
,[2013-Week1]
,[2013-Week10]
,[2013-Week11]
,[2013-Week2]
,[2013-Week3]
,[2013-Week4]
,[2013-Week5]
,[2013-Week6]
,[2013-Week7]
,[2013-Week8]
,[2013-Week9]
Desired Output:
,[2012-Week48]
,[2012-Week49]
,[2012-Week50]
,[2012-Week51]
,[2012-Week52]
,[2012-Week53]
,[2013-Week1]
,[2013-Week2]
,[2013-Week3]
,[2013-Week4]
,[2013-Week5]
,[2013-Week6]
,[2013-Week7]
,[2013-Week8]
,[2013-Week9]
,[2013-Week10]
,[2013-Week11]
EDIT
Of course after I post the question my brain started working. I changed the DATEADD to add 1 week instead of 1 day and then took out the DISTINCT in the select and it worked.
DECLARE #startdate AS VARCHAR(MAX);
DECLARE #enddate AS VARCHAR(MAX);
SET #startdate = CAST((DATEPART(yyyy, GetDate())-1) AS VARCHAR(4))+'-12-01';
SET #enddate = CAST((DATEPART(yyyy, GetDate())) AS VARCHAR(4))+'-03-15';
WITH DateRange(dt) AS
(
SELECT CONVERT(datetime, #startdate) dt
UNION ALL
SELECT DATEADD(ww,1,dt) dt FROM DateRange WHERE dt < CONVERT(datetime, #enddate)
)
SELECT ',' + QUOTENAME((CAST(DATEPART(yyyy, dt) AS VARCHAR(4)))+'-Week'+(CAST(DATEPART(ww, dt) AS VARCHAR(2)))) FROM DateRange
I can't see the sample SQL code (that site is blacklisted where I am).
Here is a trick for sorting that data in the proper order is to use the length first and then the values:
select col
from t
order by left(col, 6), len(col), col;
Have you considered to sort on two temporary columns (year in smallint and week in tinyint to save space … or directly using the datepart integer if space is not a problem to you and you prefer fast run) along with the use of "order by year, week" ?
If you store dates using a more suitable type (what I suggest), it would then become :
WITH [Define the CTE expression name and column list]
AS
(
SELECT CAST(DATEPART(yyyy, dt) as smallint(4)) year, cast(DATEPART(ww, dt) as tinyint(2)) week, [your columns here]
FROM DateRange WHERE dt < #enddate
)
[Define the outer query referencing the CTE name]
ORDER BY year, week;
GO
Also, please note that string operations will slow your queries so avoid them when possible !
I like Gordon's answer, but if you were hell-bent on text manipulation in your order by:
ORDER BY CAST(REPLACE(LEFT('[2012-Week48]',5),'[','')AS INT)
,CAST(REPLACE(RIGHT('[2012-Week48]',CHARINDEX('Week','[2012-Week48]')-4),']','') AS INT)
Here is another option converting the beginning and ending parts of the column to integer.
SELECT *
FROM YourTable
ORDER BY CAST(SUBSTRING(yourcolumn,1,4) as int),
CAST(SUBSTRING(yourcolumn,CHARINDEX('Week',yourcolumn)+4,len(yourcolumn)) as int)
SQL Fiddle Demo
This will work assuming the format of the data is always the same.
Since you are using dt to generate the string, you should sort by using the date's parts:
WITH DateRange(dt) ...
SELECT DISTINCT ',' + QUOTENAM...
ORDER BY DATEPART(yyyy, dt), DATEPART(ww, dt)
I needed to change the DATEADD portion of the query and remove the DISTINCT. Once changed the order sorted properly on it's own
DECLARE #startdate AS VARCHAR(MAX);
DECLARE #enddate AS VARCHAR(MAX);
SET #startdate = CAST((DATEPART(yyyy, GetDate())-1) AS VARCHAR(4))+'-12-01';
SET #enddate = CAST((DATEPART(yyyy, GetDate())) AS VARCHAR(4))+'-03-15';
WITH DateRange(dt) AS
(
SELECT CONVERT(datetime, #startdate) dt
UNION ALL
SELECT DATEADD(ww,1,dt) dt FROM DateRange WHERE dt < CONVERT(datetime, #enddate)
)
SELECT ',' + QUOTENAME((CAST(DATEPART(yyyy, dt) AS VARCHAR(4)))+'-Week'+(CAST(DATEPART(ww, dt) AS VARCHAR(2)))) FROM DateRange
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())