Delete rows by date in ANSI SQL - sql

I want to remove rows from last day, I have a date column, how can I do this in ansi?
delete from mytable where mydate < current_date;
This query deletes both yesterday's and today's records, I want to keep today's records ('today' is from 12 am onwards)

Your statement is valid ANSI SQL and will work on any DBMS that complies with the ANSI SQL specification with regards to DATE handling.
With Oracle the situation is different: a DATE column/value always contains a time as well. So current_date (or sysdate which is the same for the sake of this discussion) will not return 2014-09-17 but e.g. 2014-09-17 16:54:12.
Now if you have a row in your table that contains 2014-09-17 08:54:12 the condition mydate < current_date will be true because 08:54:12 is smaller than 16:54:12 and thus the row will be deleted.
You need to rewrite your statement to:
delete from mytable
where trunc(mydate) < trunc(current_date);
trunc() set the time part of a DATE to 00:00:00 and thus the comparison behaves as if there was no time part involves (because it's the same for both comparison values).
If you really, really need to write this condition in ANSI SQL and taking Oracle's non-standard DATE handling into account you need to do something like this:
select *
from mytable
where (extract(year from mydate) < extract(year from current_date))
or (extract(year from mydate) = extract(year from current_date) and extract(month from mydate) < extract(month from current_date))
or (extract(year from mydate) = extract(year from current_date) and extract(month from mydate) = extract(month from current_date) and extract(day from mydate) < extract(day from current_date));
The extract() function as shown is ANSI SQL.

Related

Query to return data only within the last year of a columns date

I have a column in a database table called EXPIRATION_DATE and need to filter my results to only bring in rows where the date in this column is within the last year.
The date format in the column is 18-JUN-21.
I imagine the filter need to be something like
WHERE EXPIRATION_DATE >= "logic to get todays date minus a year"
but I don't know what this logic is.
Thoughts?
Try with add_months :
WHERE EXPIRATION_DATE >= add_months( trunc(sysdate), -12);
I would do
where EXPIRATION_DATE >= sysdate - interval '1' year ;
WHERE EXPIRATION_DATE >= DATEADD(month, -12, GETDATE())
Or try the following:
WHERE EXPIRATION_DATE >= DATEADD(year, -1, GETDATE())
Although this is for T-SQL and I just noticed your tag is for ORACLE. I'll leave this here though for anyone using SSMS etc.

Boolean expression in CASE in WHERE clause does not work

I am having problems with Firebird SQL statement in version Firebird 2.5.
Based on today's date, I have to select either this month's data or the previous month's data.
SELECT * FROM FA_DOBAVNICA
WHERE
1=1
AND CASE WHEN
extract(day from cast('Now' as date)) < 9
THEN
DATUM_NAROCILA BETWEEN 'start of previous month' AND 'end of previous month'
ELSE
DATUM_NAROCILA BETWEEN 'start of this month' AND 'end of this month'
END
I am getting a 104 error Token unknown for BETWEEN. I have no idea what am I doing wrong.
If I understood your problem correctly you can rephrase it with an or clause like this and it should do the job:
SELECT * FROM FA_DOBAVNICA
WHERE
1=1
AND
((extract(day from cast('Now' as date)) < 9 AND DATUM_NAROCILA BETWEEN 'start of previous month' AND 'end of previous month')
or
(extract(day from cast('Now' as date)) > 8 AND DATUM_NAROCILA BETWEEN 'start of this month' AND 'end of this month'))
Personally, I would avoid forking out conditions variants in where and make it two queries instead. I suspect conditional where might suppress Firebird's query optimizer, and two distinct queries connected together might end up with a better query plan using indexes.
Especially if you have more conditions than actually shown there which 1=1 placeholder implies. You have to check and compare real plans using you real data and real added conditions.
SELECT * FROM FA_DOBAVNICA
WHERE extract(day from cast('Now' as date)) < 9
AND DATUM_NAROCILA BETWEEN 'start of previous month' AND 'end of previous'
UNION ALL
SELECT * FROM FA_DOBAVNICA
WHERE extract(day from cast('Now' as date)) >= 9
AND DATUM_NAROCILA BETWEEN 'start of this month' AND 'end of this month'
However in your specific case - why using CASE at all? Why not computing the target date span instead?
WITH
TargetDay as
(SELECT DATEADD( -8 DAY TO CURRENT_DATE) AS TPoint FROM RDB$DATABASE)
,TargetStart as
(SELECT DATEADD( 1 - EXTRACT(DAY FROM TPoint) DAY TO TPoint) AS TStart FROM TargetDay)
,TargetEnd as
(SELECT DATEADD( -1 DAY TO DATEADD( 1 MONTH TO TStart)) AS TEnd FROM TargetStart)
select TStart, TEnd, TPoint from TargetStart, TargetEnd, TargetDay
TSTART
TEND
TPOINT
2021-08-01
2021-08-31
2021-08-03
db<>fiddle here
See? you do not need any if-then-else at all!
Added bonus is that you now can easily turn your 9 into an SQL parameter, rather than having it a literal constant injected into SQL code via always fragile string splicing, because now you only use 9 once in your query, thus you no more have have to care about changing two different parameters/constants in a query always in sync.
WITH
TargetDay as
(SELECT DATEADD( 1 - (cast( ? as integer )) DAY TO CURRENT_DATE) AS TPoint FROM RDB$DATABASE)
,TargetStart as....
Or in languages like Delphi which simulate named parameters for Firebird, it can be like
WITH
TargetDay as
(SELECT DATEADD( 1 - (cast( :ThresholdDay as integer )) DAY TO CURRENT_DATE) AS TPoint FROM RDB$DATABASE)
,TargetStart as....

Netezza SQL show only last year's data

it sounds simple and it should be simple but for some reason I can't seem to make it happen in Netezza... So far I tried:
select *
from table
where placed_dt >= DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) - 1, 0);
and it looked like dateadd function doesn't work on Netezza. So I tried:
select *
from table
where placed_dt between (current_date - interval 1 year) and current_date
but still had no luck. Any help would be appreciated!
If you want the last year from the current date:
where placed_dt >= current_date - interval '1 year'
Note that the single quotes are needed.
and you can include the <= current_date if that is also needed.
If you want the last calendar year, there are various methods, but one is:
where date_trunc('year', placed_dt) = date_trunc('year', current_date) - interval '1 year'
You may try:
SELECT *
FROM yourTable
WHERE
placed_dt >= ADD_MONTHS(DATE_TRUNC('year', current_timestamp), -12) AND
placed_at < DATE_TRUNC('year', current_timestamp);
In the above inquality in the WHERE clause, for a current year of 2020, the lower bound represents 2019-01-01 and the upper bound represents 2020-01-01.

Fetch yesterday details using extract in SQL

consultation(patient_id, cdate, doctor_id)
I want the details of patients which was treated yesterday using extract
But I am getting error
ORA-00911: invalid character
My code:
select *
from consultation
where extract(day from cdate) = extract(day from sysdate) - '1';
You may avoid extract and simply use:
select *
from consultation
where trunc(cdate) = trunc(sysdate-1)
Here I use trunc to remove the time part; also, notice that by using extract to compare the day, you will get not only records of yesterday, but even records from the past months.
If you need to get all the records where the day is 6 (assuming that sysdate is May, 7), no matter the month or year, you can use:
where extract(day from cDate) = extract(day from sysdate -1)
Prefer not to use EXTRACT on the date column, it is less efficient, especially if there's an index or partition on the date column. simply use TRUNC on SYSDATE
select * from consultation where
cdate >= TRUNC(sysdate) - 1
AND cdate < TRUNC(SYSDATE)
you need to put integer 1 not string '1'
select * from consultation where
extract(day from cdate) = extract(day from sysdate) - 1;

Oracle SQL Where Clause against a date column

I have a DATE column with a date in it but I need to query it to find records less than 30 days old.
START_DATE
----------
01-AUG-2010
09-AUG-2010
22-AUG-2010
09-SEP-2010
Query:
SELECT START_DATE
WHERE START_DATE < 30;
I know it is simple Query in ORACLE SQL but i am doing something wrong.
Use:
SELECT t.start_date
FROM YOUR_TABLE t
WHERE t.start_date > SYSDATE - 30
SYSDATE is Oracle's syntax to get the current date and time
In Oracle, you can do date arithmetic in the context of days, so SYSDATE - 30 means "current date, subtract thirty days" to get a date that is thirty days in the past
If you want to evaluate the date based on thirty days as of midnight, use the TRUNC function:
SELECT t.start_date
FROM YOUR_TABLE t
WHERE t.start_date > TRUNC(SYSDATE) - 30
Don't run TRUNC on the column - that will render an index on the column useless, ensuring a table scan.
SELECT t.start_date
FROM YOUR_TABLE t
WHERE t.start_date > SYSDATE - INTERVAL '30' DAY;
INTERVAL is more portable than assuming that you can add or subtract days, although I've noticed some slight differences in the INTERVAL syntax between Oracle and PostgreSQL.
WHERE START_DATE > SYSDATE - 1
or perhaps
WHERE TRIM(STARTDATE) > TRIM(SYSDATE) - 1