How to select a date range without using a from table clause? - sql

I want to write a basic sql query where it outputs all dates between 3-15 months from current date:
DATEADD(month, 3, GETDATE()) AND (DATEADD(month, 15, GETDATE()))
The catch is though there is no table to select from. I just want to perform a basic SELECT to get the list of dates. Is this possible?

Following will help you to pull all dates between two dates.
DECLARE #Date1 DATE, #Date2 DATE
SET #Date1 = '2015-05-28'
SET #Date2 = '2015-06-30'
SELECT DATEADD(DAY,number+1,#Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY,number+1,#Date1) < #Date2

Although there already is an accepted answer, I propose an alternative that doesn't depend on undocumented and unsupported system tables.
declare #Date1 date = '2015-05-28';
declare #Date2 date = '2015-06-30';
declare #Dates table (Date Date);
while #Date1 <= #Date2
begin
insert into #Dates (Date) values (#Date1);
set #Date1 = DateAdd(Day, 1, #Date1);
end
select * from #Dates;

Related

Get the Date Difference Between two dates excluding fridays in SQL Server

I have the following two dates :
startDate = '2017-04-04' and endDate = '2017-04-12'
I would like to find the total count of days between these two dates excluding 'Fridays' using SQL Server.
Any Help from the SQL Server Experts will be highly appreciated!! Thanks in Advance!!
You can use DATENAME to check for 'Friday' do this, something like this :
DECLARE #startDate DATETIME
DECLARE #endDate DATETIME
SET #startDate = '2017-04-04'
SET #endDate = '2017-04-12'
Declare #count int
set #count=0
while #startDate < #endDate
Begin
IF DATENAME(dw, #startDate) <> 'Friday'
SET #count = #count + 1
SET #startDate = DateAdd(d, 1, #startDate)
END
select #count
This will result in :
7
just add below clause to your query
select count(*) from table
where startDate >= '2017-01-12' and endDate <= '2017-04-27'
and datename(WEEKDAY,startdate))<>'Friday'

Displaying the number of valid results for a range of dates

I currently have a table with a creation date and a expiry date. I currently have a sql command to get the number of valid items for a given date.
select
count(id) ,CONVERT(date, getdate())
from
table
where
createDate < getdate() and expDate > getdate()
This returns the count and current date.
Is it possible to wrote a sql query that will return the result for a range of dates, say I if wanted to plot the number of valid items over a range of 15 days?
Thanks!
Try this:
create table #datelist (ValidDateCheck date, ValidResults int)
declare #startdate date = '1/1/2015'
declare #enddate date = '2/1/2015'
declare #interval int = 1 --Use 1 if you want every day between your dates, use 2 if you want every other day, etc.
declare #datecounter date = #startdate
declare #count int
while #datecounter <= #enddate
begin
set #count =
(select count(*)
from Table
where CrtDt <= #datecounter and ExpDt > #datecounter)
insert into #datelist values (#datecounter, #count)
set #datecounter = dateadd(dd, #interval, #datecounter)
end
select * from #datelist order by 1
It loops through all the dates in your range, counting valid results for each one.
Check this,
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = '20110501'
,#EndDate = '20110801';
SELECT
DATEADD(d, x.number, #StartDate) AS MonthName1
,
x.number
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate);
The above query give the list of dates between 2 dates.
As per your table and question, check this also.
declare #table table(id int,frdt datetime, todt datetime)
insert into #table values (1,GETDATE()-20, GETDATE()-19)
,(2,GETDATE()-9, GETDATE()-8)
,(3,GETDATE()+20, GETDATE()+18)
,(4,GETDATE(), GETDATE()-1)
,(5,GETDATE()-20, GETDATE())
,(6,GETDATE()-10, GETDATE()+10 )
select * from #table
declare #frdt datetime = null , #todt datetime = getdate()-10
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)
select #frdt = GETDATE()-15 , #todt = GETDATE()
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)

get last date in tsql

i show you my logic is getting error only when month is December
declare #startDate datetime
declare #endDate datetime
set #startDate = convert(varchar(2),#month)+'/1/'+ convert(varchar(4),#year)
set #endDate = dateadd(DD,-1,(convert(varchar(2),#month+1)+'/1/'+convert(varchar(4),#year)))
while(#startDate < #endDate+1)
begin
insert into #tempday
select #startDate
set #startDate = dateadd(day, 1, #startDate )
end
please help
Once you have #startdate, use:
set #enddate = dateadd(day,-1,dateadd(month,1,#startdate))
And I don't think you mean plsql...
There are other things you could think about too, such as not using a while-loop. Why not query a table that has plenty of rows (such as sys.all_columns) and use:
insert #tempday
select top (datediff(day,#startdate,#enddate)+1)
dateadd(day,row_number() over (order by (select 1))-1,#startdate)
from sys.all_columns;
In case of December #month+1 will get you 13 which is not a valid month number

SQL Current status for given day (FOR loop)

For simplicity lets assume that I have a view with three fields
date_in (date)
Container (varchar)
date_out (date)
Now, the container is IN if the date_in is lesser or equal to given date and date_out is null or greater than given date. Now I am trying to count the containers for given time period. In pseudocode between two values STARTDATE and ENDDATE it would be something like
FOR X =STARTDATE, X<= ENDDADE, X++ {
if date_in <=X and date_out>x
count (container)
}
or closer to SQL:
declare #startdate date,
#d date;
set #startdate = '1/01/2014'
set #d = #startdate
"FOR on the #d variable would go here" {
select #d as SNAP_DATE, count (container) where date_in <#d
and (date_out is null or date_out> #d)
}
It might be simple - I guess I could make a new table and manually do multiple SELECT INTO (and later query from this new table) but its not very elegant solution.
Edit: just to precise - in the end I'd like to have something like:
DATE Count
1/02/2014 10
2/02/2014 15
...
7/03/2014 19
You could do this procedurally as follows:
Use a while loop to loop from start to end date.
Use a table variable to store each date-count pair.
Select from the table variable to get the summarised result.
declare #start date = '1/01/2014'
declare #end date = '7/03/2014'
declare #tbl table(Date date, Count int)
while(#start < #end)
begin
insert into #tbl
select #start, count(*)
from your_view
where (in_date < #start)
and ((out_date is null) or (out_date > #start))
set #start = dateadd(day, 1, #start)
end
select * from #tbl
You might be able to do something like the following. It uses a numbers table, which can be a real or derived table. It contains rows of integers. You need a table that begins with 0 and has enough values to cover your date range. Check here for more information on a numbers table.
DECLARE #StartDate DATE = '1/2/2014'
DECLARE #EndDate DATE = '1/4/2014'
SELECT DATEADD(d, n.num, #StartDate) AS DATE, COUNT(*) AS COUNT
FROM Numbers n
JOIN MyView mv ON mv.date_in < DATEADD(d, n.num, #StartDate)
AND (mv.date_out IS NULL OR mv.date_out > DATEADD(d, n.num, #StartDate))
WHERE DATEADD(d, n.num, #StartDate) BETWEEN #StartDate AND #EndDate
GROUP BY DATEADD(d, n.num, #StartDate)
ORDER BY DATEADD(d, n.num, #StartDate)
The numbers in the numbers table are converted to the list of dates between the date range. Each date is joined to your view based on the criteria you need.

Compare current date with stored datetime using month an year only

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())