Select data from date range between two dates - sql

I have a table Named Product_Sales and it holds data like this
Product_ID | Sold_by | Qty | From_date | To_date
-----------+---------+-----+------------+-----------
3 | 12 | 7 | 2013-01-05 | 2013-01-07
6 | 22 | 14 | 2013-01-06 | 2013-01-10
8 | 11 | 9 | 2013-02-05 | 2013-02-11
Now what is the query if I want to select sales data between two dates from a date range?
For example, I want to select sales data from 2013-01-03 to 2013-01-09.

As you can see, there are two ways to get things done:
enlist all acceptable options
exclude all wrong options
Obviously, second way is much more simple (only two cases against four).
Your SQL will look like:
SELECT * FROM Product_sales
WHERE NOT (From_date > #RangeTill OR To_date < #RangeFrom)

SELECT * from Product_sales where
(From_date BETWEEN '2013-01-03'AND '2013-01-09') OR
(To_date BETWEEN '2013-01-03' AND '2013-01-09') OR
(From_date <= '2013-01-03' AND To_date >= '2013-01-09')
You have to cover all possibilities. From_Date or To_Date could be between your date range or the record dates could cover the whole range.
If one of From_date or To_date is between the dates, or From_date is less than start date and To_date is greater than the end date; then this row should be returned.

Try following query to get dates between the range:
SELECT *
FROM Product_sales
WHERE From_date >= '2013-01-03' AND
To_date <= '2013-01-09'

SELECT * FROM Product_sales
WHERE From_date between '2013-01-03'
AND '2013-01-09'

This covers all conditions that you are looking for.
SELECT * from Product_sales where (From_date <= '2013-01-09' AND To_date >= '2013-01-01')

SELECT *
FROM Product_sales
WHERE (
From_date >= '2013-08-19'
AND To_date <= '2013-08-23'
)
OR (
To_date >= '2013-08-19'
AND From_date <= '2013-08-23'
)

Please try:
DECLARE #FrmDt DATETIME, #ToDt DATETIME
SELECT #FrmDt='2013-01-03', #ToDt='2013-01-09'
SELECT *
FROM Product_sales
WHERE (#FrmDt BETWEEN From_date AND To_date) OR
(#ToDt BETWEEN From_date AND To_date)

This is easy, use this query to find select data from date range between two dates
select * from tabblename WHERE (datecolumn BETWEEN '2018-04-01' AND '2018-04-5')

Just my 2 cents, I find using the "dd-MMM-yyyy" format safest as the db server will know what you want regardless of the regional settings on the server. Otherwise you could potentially run into issues on a server that has its date regional settings as yyyy-dd-mm (for whatsoever reason)
Thus:
SELECT * FROM Product_sales
WHERE From_date >= '03-Jan-2013'
AND To_date <= '09-Jan-2013'
It's always worked well for me ;-)

select *
from table
where
( (table.EndDate > '2013-01-05') and (table.StartDate < '2013-01-07' ) )

Check this query, i created this query to check whether the check in date over lap with any reservation dates
SELECT * FROM tbl_ReservedRooms
WHERE NOT ('#checkindate' NOT BETWEEN fromdate AND todate
AND '#checkoutdate' NOT BETWEEN fromdate AND todate)
this will retrun the details which are overlaping , to get the not overlaping details then remove the 'NOT' from the query

This query will help you:
select *
from XXXX
where datepart(YYYY,create_date)>=2013
and DATEPART(YYYY,create_date)<=2014

This working on SQL_Server_2008 R2
Select *
from Product_sales
where From_date
between '2013-01-03' and '2013-01-09'

SELECT NULL
FROM HRMTable hm(NOLOCK)
WHERE hm.EmployeeID = 123
AND (
(
CAST(#Fromdate AS date) BETWEEN CAST(hm.FromDate AS date)
AND CAST(hm.ToDate AS date)
)
OR (
CAST(#Todate AS date) BETWEEN CAST(hm.FromDate AS date)
AND CAST(hm.ToDate AS date)
)
)
)

You can also try using following fragments:
select * from Product_sales
where From_date >= '2013-01-03' and game_date <= '2013-01-09'

Here is a query to find all product sales that were running during the month of August
Find Product_sales there were active during the month of August
Include anything that started before the end of August
Exclude anything that ended before August 1st
Also adds a case statement to validate the query
SELECT start_date,
end_date,
CASE
WHEN start_date <= '2015-08-31' THEN 'true'
ELSE 'false'
END AS started_before_end_of_month,
CASE
WHEN NOT end_date <= '2015-08-01' THEN 'true'
ELSE 'false'
END AS did_not_end_before_begining_of_month
FROM product_sales
WHERE start_date <= '2015-08-31'
AND end_date >= '2015-08-01'
ORDER BY start_date;

DECLARE #monthfrom int=null,
#yearfrom int=null,
#monthto int=null,
#yearto int=null,
#firstdate DATE=null,
#lastdate DATE=null
SELECT #firstdate=DATEADD(month,#monthfrom-1,DATEADD(year,#yearfrom-1900,0)) /*Setting First Date using From Month & Year*/
SELECT #lastdate= DATEADD(day,-1,DATEADD(month,#monthto,DATEADD(year,#yearto-1900,0)))/*Setting Last Date using From Month & Year*/
SELECT * FROM tbl_Record
WHERE (DATEADD(yy, Year - 1900, DATEADD(m, Month - 1, 1 - 1)) BETWEEN CONVERT(DATETIME, #firstdate, 102) AND
CONVERT(DATETIME, #lastdate, 102))

You should compare dates in sql just like you compare number values,
SELECT * FROM Product_sales
WHERE From_date >= '2013-01-01' AND To_date <= '2013-01-20'

this is easy, use this query to find what you want.
select * from Product_Sales where From_date<='2018-04-11' and To_date>='2018-04-11'

Related

Calculating days of therapy in a sql query

I'm attempting to calculate days of therapy by month from an oracle database. The (vastly simplified) data is as follows:
Therapies
+-----------+-----------+----------+
| Rx Number | StartDate | StopDate |
|-----------+-----------+----------|
| 1 | 12-29-14 | 1-10-15 |
| 2 | 1-2-15 | 1-14-15 |
| 3 | 1-29-15 | 2-15-15 |
+-----------+-----------+----------+
For the purposes of this example, all times are assumed to be midnight. The total days of therapy in this table is (10-1 + 32-29) + (14-2) + (15-1 + 32-29) = 41. The total days of therapy in January in this table is (10-1) + (14-2) + (32-29) = 24.
If I wanted to calculate days of therapy for the month of January , my best effort is the following query:
SELECT SUM(stopdate - startdate)
FROM therapies
WHERE startdate > to_date('01-JAN-15')
AND stopdate < to_date ('01-FEB-15');
However, rx's 1 and 3 are not captured at all. I could try the following instead:
SELECT SUM(stopdate - startdate)
FROM therapies
WHERE stopdate > to_date('01-JAN-15')
AND startdate < to_date ('01-FEB-15');
But that would include the full duration of the first and third therapies, not just the portion in January. To make the matter more complex, I need these monthly summaries over a period of two years. So my questions are:
How do I include overhanging therapies such that only the portion within the target time period is included, and
How do I automatically generate these monthly summaries over a two year period?
How do I include overhanging therapies such that only the portion
within the target time period is included?
select sum(
greatest(least(stopdate, date '2015-01-31' + 1)
- greatest(startdate, date '2015-01-01'), 0)) suma
from therapies
How do I automatically generate these monthly summaries over a two
year period?
with period as (select date '2014-01-01' d1, date '2015-12-31' d2 from dual),
months as (select trunc(add_months(d1, level-1), 'Month') dt
from period connect by add_months(d1, level-1)<d2)
select to_char(dt, 'yyyy-mm') mth,
sum(greatest(least(stopdate, add_months(dt, 1)) - greatest(startdate, dt), 0)) suma
from therapies, months
group by to_char(dt, 'yyyy-mm') order by mth
Above queries produced desired output. Please insert your dates in proper places to change analyzed periods.
In second SQL inner subquery months gives 24 dates, one for each month. The rest is only maneuvering
with functions greatest(),least() and some math.
Use a case statement to set the start date and stop date. Like the below:
select sum(
Stopdate -
(case Startdate
when startdate < to_date(#YourBeginingDate) then To_date(#YourBeginingDate)
else startdate
end)
FROM therapies
WHERE stopdate > to_date(#YourBeginingDate)
AND StartDate < to_date(#YourEndingDate)
I would do something like the following:
WITH t1 AS (
SELECT 1 AS rx, DATE'2014-12-29' AS start_date
, DATE'2015-01-10' AS stop_date
FROM dual
UNION ALL
SELECT 2, DATE'2015-01-02', DATE'2015-01-14'
FROM dual
UNION ALL
SELECT 3, DATE'2015-01-29', DATE'2015-02-15'
FROM dual
)
SELECT TRUNC(rx_dt, 'MONTH') AS rx_month, SUM(rx_cnt) AS rx_day_cnt
FROM (
SELECT rx_dt, COUNT(*) AS rx_cnt
FROM (
SELECT rx, start_date + LEVEL - 1 AS rx_dt
FROM t1
CONNECT BY start_date + LEVEL - 1 < stop_date
AND PRIOR rx = rx
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
) GROUP BY rx_dt
) GROUP BY TRUNC(rx_dt, 'MONTH')
ORDER BY rx_month
Results:
12/1/2014 12:00:00 AM 2
1/1/2015 12:00:00 AM 24
2/1/2015 12:00:00 AM 15
See SQL Fiddle here.
What I am doing is using LEVEL and CONNECT BY to get all the days of therapy based on start_date and stop_date (not inclusive). I then GROUP BY the therapy date (rx_dt) to handle the overlapping therapies. Then I GROUP BY the month of the therapy using the TRUNC() function.
This should work just fine over a two-year period (or more); just add that filter before the last GROUP BY:
WHERE rx_dt >= DATE'2014-01-01'
AND rx_dt < DATE'2016-01-01'
GROUP BY TRUNC(rx_dt, 'MONTH')
Note that if your primary key is composite, you should include all the columns in the CONNECT BY clause:
CONNECT BY start_date + LEVEL - 1 < stop_date
AND PRIOR rx = rx
AND PRIOR patient_id = patient_id
--etc.
This is a bit tricky, as you need to capture days from sessions that:
Begin before the month and end after the month
Begin before the month and end during the month
Begin during the month and end after the month
Begin during the month and end during the month
To get those sessions, you can use a WHERE statement like this (the # symbol means that those are variables being passed in):
*examples are in TSQL, PLSQL might have somewhat different syntax
WHERE startdate < #endDate AND stopdate > #startDate
That should capture all four of those scenarios that I listed.
Then you only need to capture days that occurred during the month. I do this with a query that replaces the startdate/enddate with the date range limits if they exceed the range, like this:
SELECT
CASE WHEN enddate > #endDate then #endDate ELSE enddate END -
CASE WHEN startdate < #startDate THEN #startDate ELSE startdate END
So your whole query should look like this:
SELECT
SUM(
CASE WHEN enddate > #endDate then #endDate ELSE enddate END -
CASE WHEN startdate < #startDate THEN #startDate ELSE startdate END
)
FROM therapies
WHERE startdate < #endDate AND stopdate > #startDate
If you want to run that for two years, toss that code in a function that accepts #startDate and #endDate parameters, then call it from a query that gives you two years worth of months, like this:
WITH dateCTE AS (
SELECT
GETDATE() AS StartDate,
DATEADD(Month, 1, GETDATE()) AS EndDate
UNION ALL
SELECT
DATEADD(MONTH, -1, StartDate),
DATEADD(MONTH, -1, EndDate)
FROM dateCTE
WHERE StartDate > DATEADD(YEAR, -2, GETDATE())
)
SELECT
StartDate,
EndDate,
SomeFunction(StartDate, EndDate)
FROM dateCTE

Comparing dates in SQL Server

I have a DateTime column named EXP_Date which contains date like this :
2014-07-13 00:00:00.000
I want to compare them, like this query :
SELECT COUNT(*)
FROM DB
WHERE ('2014-07-15' - EXP_DATE) > 1
I expect to see the number of customers who have their services expired for over a month.
I know this query wouldn't give me the correct answer, the best way was if I separate the Year / Month / Day into three columns, but isn't any other way to compare them as they are?
You can use DATEADD
SELECT COUNT(*)
FROM DB
where EXP_DATE < DATEADD(month, -1, GETDATE())
Try this
SELECT COUNT(*)
FROM DB
where DATEADD(month, -1, GETDATE()) > EXP_DATE
SELECT COUNT(EXPIRE)FROM
(Select CASE WHEN EXP_DATE < DATEADD(month, -1, GETDATE())THEN 1 ELSE 0 END)AS EXPIRE FROM DB
)tt
Another way using DATEDIFF
SET DATEFORMAT DMY --I like to use "dateformat"
SELECT COUNT(*)
FROM DB
WHERE (DATEDIFF(DAY,#EXP_DATE,GETDATE())) >= 30 --Remember, instead "Day" you can use week, month, year, etc
Syntax: DATEDIFF ( datepart , startdate , enddate )
Depart: year, quarter, month, day, week...
For more information you can visit MSDN

Comparing results with today's date?

Is there a way to use the Now() function in SQL to select values with today's date?
I was under the impression Now() would contain the time as well as date, but today's date would have the time set to 00:00:00 and therefore this would never match?
OK, lets do this properly. Select dates matching today, using indexes if available, with all the different date/time types present.
The principle here is the same in each case. We grab rows where the date column is on or after the most recent midnight (today's date with time 00:00:00), and before the next midnight (tomorrow's date with time 00:00:00, but excluding anything with that exact value).
For pure date types, we can do a simple comparison with today's date.
To keep things nice and fast, we're explicitly avoiding doing any manipulation on the dates stored in the DB (the LHS of the where clause in all the examples below). This would potentially trigger a full table scan as the date would have to be computed for every comparison. (This behaviour appears to vary by DBMS, YMMV).
MS SQL Server: (SQL Fiddle | db<>fiddle)
First, using DATE
select * from dates
where dte = CAST(CURRENT_TIMESTAMP AS DATE)
;
Now with DATETIME:
select * from datetimes
where dtm >= CAST(CURRENT_TIMESTAMP AS DATE)
and dtm < DATEADD(DD, 1, CAST(CURRENT_TIMESTAMP AS DATE))
;
Lastly with DATETIME2:
select * from datetimes2
where dtm2 >= CAST(CURRENT_TIMESTAMP AS DATE)
and dtm2 < DATEADD(DD, 1, CAST(CURRENT_TIMESTAMP AS DATE))
;
MySQL: (SQL Fiddle | db<>fiddle)
Using DATE:
select * from dates
where dte = cast(now() as date)
;
Using DATETIME:
select * from datetimes
where dtm >= cast((now()) as date)
and dtm < cast((now() + interval 1 day) as date)
;
PostgreSQL: (SQL Fiddle | db<>fiddle)
Using DATE:
select * from dates
where dte = current_date
;
Using TIMESTAMP WITHOUT TIME ZONE:
select * from timestamps
where ts >= 'today'
and ts < 'tomorrow'
;
Oracle: (SQL Fiddle)
Using DATE:
select to_char(dte, 'YYYY-MM-DD HH24:MI:SS') dte
from dates
where dte >= trunc(current_date)
and dte < trunc(current_date) + 1
;
Using TIMESTAMP:
select to_char(ts, 'YYYY-MM-DD HH24:MI:SS') ts
from timestamps
where ts >= trunc(current_date)
and ts < trunc(current_date) + 1
;
SQLite: (SQL Fiddle)
Using date strings:
select * from dates
where dte = (select date('now'))
;
Using date and time strings:
select dtm from datetimes
where dtm >= datetime(date('now'))
and dtm < datetime(date('now', '+1 day'))
;
Using unix timestamps:
select datetime(dtm, 'unixepoch', 'localtime') from datetimes
where dtm >= strftime('%s', date('now'))
and dtm < strftime('%s', date('now', '+1 day'))
;
Backup of SQL Fiddle code
There is no native Now() function in SQL Server so you should use:
select GETDATE() --2012-05-01 10:14:13.403
you can get day, month and year separately by doing:
select DAY(getdate()) --1
select month(getdate()) --5
select year(getdate()) --2012
if you are on sql server 2008, there is the DATE date time which has only the date part, not the time:
select cast (GETDATE() as DATE) --2012-05-01
Not sure what your asking!
However
SELECT GETDATE()
Will get you the current date and time
SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Will get you just the date with time set to 00:00:00
Just zero off the time element of the date. e.g.
SELECT DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
I've used GetDate as that's an MSSQL function, as you've tagged, but Now() is probably MySQL or you're using the ODBC function call, still should work if you just replace one with the other.
Not sure exactly what you're trying to do, but it sounds like GETDATE() is what you're after. GETDATE() returns a datetime, but if you're not interested in the time component then you can cast to a date.
SELECT GETDATE()
SELECT CAST(GETDATE() AS DATE)
Building on the previous answers, please note an important point, you also need to manipulate your table column to ensure it does not contain the time fragment of the datetime datatype.
Below is a small sample script demonstrating the above:
select getdate()
--2012-05-01 12:06:51.413
select cast(getdate() as date)
--2012-05-01
--we're using sysobjects for the example
create table test (id int)
select * from sysobjects where cast(crdate as date) = cast(getdate() as date)
--resultset contains only objects created today
drop table test
I hope this helps.
EDIT:
Following #dwurf comment (thanks) about the effect the above example may have on performance, I would like to suggest the following instead.
We create a date range between today at midnight (start of day) and the last millisecond of the day (SQL server count up to .997, that's why I'm reducing 3 milliseconds). In this manner we avoid manipulating the left side and avoid the performance impact.
select getdate()
--2012-05-01 12:06:51.413
select dateadd(millisecond, -3, cast(cast(getdate()+1 as date) as datetime))
--2012-05-01 23:59:59.997
select cast(getdate() as date)
--2012-05-01
create table test (id int)
select * from sysobjects where crdate between cast(getdate() as date) and dateadd(millisecond, -3, cast(cast(getdate()+1 as date) as datetime))
--resultset contains only objects created today
drop table test
If you have a table with just a stored date (no time) and want to get those by "now", then you can do this:
SELECT * FROM tbl WHERE DATEDIFF(d, yourdate, GETDATE())=0
This results in rows which day difference is 0 (so today).
For me the query that is working, if I want to compare with DrawDate for example is:
CAST(DrawDate AS DATE) = CAST (GETDATE() as DATE)
This is comparing results with today's date.
or the whole query:
SELECT TOP (1000) *
FROM test
where DrawName != 'NULL' and CAST(DrawDate AS DATE) = CAST (GETDATE() as DATE)
order by id desc
You can try this sql code;
SELECT [column_1], [column_1], ...
FROM (your_table)
where date_format(record_date, '%e%c%Y') = date_format(now(), '%e%c%Y')
You can try:
WHERE created_date BETWEEN CURRENT_TIMESTAMP-180 AND CURRENT_TIMESTAMP
This worked for me:
SELECT * FROM table where date(column_date) = curdate()

SQL date question

I have a question. I have a SQL Server 2008 table with a field column. I have for example the Following dates:
1/1/2001
5/5/2004
8/5/2009
10/7/2011
5/5/2012
1/13/2014
Id like to be able to show all dates >= the current date (7/29/2011) as well as largest table date that is < current date. In this example, the result would be all dates >= 8/5/2009.
Can someone help guide me please??
select max(date) [date] from table where date < getdate()
union
select date from table where date >= getdate()
If I understand correctly, you want to include the date prior to the current date. GETDATE() will get the current date (with time). If you're alright with that, then this should work. Otherwise, you may have to parse out just the date from GETDATE()
SELECT TheDate
FROM DateTable
WHERE TheDate >= (SELECT MAX(TheDate) FROM DateTable WHERE TheDate < GETDATE())
This gets all dates greater than or equal to the most recent date before the current date.
I am not entirely sure I understand, but this looks like a BETWEEN the relevant dates. Or is there something more I am missing?
Assuming your table is called DateTable and your field is called TheDate, do it like this:
SELECT TheDate
FROM DateTable
WHERE TheDate >= DATEADD(d, -2, GETDATE())
Good luck!
It depends on the SQL server you're using. In postgres, for example, you need something like
SELECT fields FROM table WHERE date_field >= CURRENT_DATE - 1
But other SQL servers have different ways to specify "yesterday"
SELECT d1.*
FROM dates d1
LEFT JOIN dates d2 ON d1.Date < d2.Date AND d2.Date < GETDATE()
WHERE d2.Date IS NULL
Explanation:
Select every date for which there does not exist a date that is both earlier than today and later than the one being inspected.
Lots of guessing here based on loose narrative and unknown data types.
DECLARE #t TABLE(d DATE);
INSERT #t SELECT '20010101'
UNION ALL SELECT '20040505'
UNION ALL SELECT '20090805'
UNION ALL SELECT '20111007'
UNION ALL SELECT '20120505'
UNION ALL SELECT '20140113';
DECLARE #now DATE = SYSDATETIME();
WITH t AS
(
SELECT d, rn = ROW_NUMBER() OVER (ORDER BY d)
FROM #t
)
SELECT t.d
FROM t LEFT OUTER JOIN t AS x
ON t.rn = x.rn - 1
WHERE COALESCE(x.d, #now) >= #now
ORDER BY t.d;

Date Range in PL/SQL

If I have table with a Date column (Date field) called created_date, with values like "9/2/2010 5:25:42 PM".
I want to select all rows from a start_date to a end_date. However, the end_date may be null. In this case, I want to select all rows where created_date is greater than end_date.
Since toDate (which can be null) is a host variable, it's easier than the solutions already given (which are all wrong in that regard, btw)
select * from mytable
where created_date between v_fromdate
and nvl(v_todate, to_date('31.12.9999','dd.mm.yyyy'));
select *
from TABLE
where created_date >= '2010-09-02' and (created_date is NULL or created_date <= '2010-09-03')
Why just use a simple SQL query for that, like this one:
select xxx from table_names where created_date is null or (created_date >= to_date("02/09/2010", "dd/mm/yyyy") and created_date <= to_date("03/09/2010", "dd/mm/yyyy"));
Edit
You can define a query like the one defined by ammoQ, i.e. something like that:
select xxx from table_names where created_date is null or created_date >= start_date and created_date <= nvl(end_date, to_date("31/12/9999", "dd/mm/yyyy"));
However, as you are using PL/SQL, you can check the nullability of end_date parameter:
IF end_date IS NULL THEN
select xxx from table_names where created_date is null or created_date >= start_date;
ELSIF
select xxx from table_names where created_date is null or created_date >= start_date and created_date <= end_date;
END IF;
Note that you can remove the created_date is null condition if created_date is not a nullable column...
select * from yourtable
where created_date >= #StartDate AND created_date <=ISNULL(#EndDate,created_date)
SELECT *
FROM A_TABLE
WHERE CREATED_DATE >= &START_DATE AND
(CREATED_DATE <= &END_DATE OR
&END_DATE IS NULL)
If i took it right from your question
this should work:
SELECT *
FROM yourTable
WHERE created_date >= to_date('01.09.2010', 'dd.mm.yyyy')
AND (end_date <= to_date('02.09.2010', 'dd.mm.yyyy')
OR end_date IS NULL);