Oracle date datatype vs sysdate - sql

In my table sales there is expiry date field which is of date type.
Now, I have to write query which selects all records having expiry date greater than current system date.
select * from Sales where expiry_date > sysdate;
in output I am getting all records with expiry date 31/12/9999 00:00:00,
which is not desired.

" in output i am getting all records with expiry date 31/12/9999 00:00:00 which is not desired."
But that's what your query asks for: you must admit that the year 9999 is greater than the current year.
So either your query is correct and you have misunderstood the requirement, or you need to re-write the query to explicitly exclude records with the maximum date.
Presumably in this case EXPIRY_DATE was defined as NOT NULL and it was too late to change it when somebody raised the matter of records which never expire. So instead we have a magic value of 31-12-9999 is ,which means of "these records do not expire".
Anyhow, here is the query now:
select * from Sales
where expiry_date > sysdate
and expiry_date != date '9999-12-31';
This is a common problem with magic values: they offer a quick fix for an architectural problem but levy an ongoing tax on application logic.

Ahh the end of time, a date so far in the future the system storing it is unlikely to ever encounter it for real. The problem with that is that systems have a nasty habit of lasting longer than expected in one form or another.
Be that as it may, it looks like you want to exclude the end of time since the assumption is that those records don't truly expire, but gosh darn it you needed some kind of date in there for that index to work the way you wanted it to.
So you either need to directly exclude records where the expiration date equals your end of time value, or use a range condition that does the same:
where expiry_date between sysdate and date '9999-12-30 23:59:59'

Related

Finding the Closest Unbooked Dates Using SQL

Scenario
A user selects a date. Based on the selection I check whether the date & time is booked or not (No issues here).
If a date & time is booked, I need to show them n alternative dates. Based on their date and time parameters, and those proposed alternative dates have to be as close as to their chosen date as possible. The list of alternative dates should start from the date the query is ran on My backend handles this.
My Progress So Far
SELECT alternative_date
FROM GENERATE_SERIES(
TIMESTAMP '2022-08-20 05:00:00',
date_trunc('month', TIMESTAMP '2022-08-20 07:00:00') + INTERVAL '1 month - 1 day',
INTERVAL '1 day'
) AS G(alternative_date)
WHERE NOT EXISTS(
SELECT * FROM events T
WHERE T.bookDate::DATE = G.alternative_date::DATE
)
The code above uses the GENERATE_SERIES(...) function in PSQL. It searches for all dates, starting from 2022-08-20, and up to the end of August. It specifically returns the dates which does not exist in the bookDate column (Meaning it has not yet been booked).
Problems I Need Help With
When searching for alternative dates, I'm providing 3 important things
The user's preferred booking date, so I can suggest which other dates are close to him that he can choose? How would I go about doing this? It's the part where I'm facing most trouble.
The user's start and end times, so when providing a list of alternative dates, I can tell him, hey there's free space between 06 and 07 on the date 2022-08-22 for instance. I'm also facing some issues here, a push in the right track will be great!
I want to add another WHERE but it fails, the current WHERE is a NOT EXISTS so it looks for all dates not equaling to what is given. My other WHERE basically means WHERE the place is open for booking or not.
To get closest free dates, you can ORDER BY your result by "distance" of particular alternative date to user's preferred date - the shortest intervals will be first:
ORDER BY alternative_date - TIMESTAMP '2022-08-20 05:00:00'
If you want to recommend time slots smaller than whole dates (hour range), you need to switch the whole thing from dates to hours, i.e. generate_series from 1 day to 1 hour (or whatever your smallest bookable unit is) and excluse invalid hours (nighttime I assume) in WHERE. From there, it is pretty much the same as with dates.
As for "second where", there can be only one WHERE, but it can be composed from multiple conditions - you can add more conditions using AND operator (and it can also be sub-query if needed):
WHERE NOT EXISTS(
SELECT * FROM events T
WHERE T.bookDate::DATE = G.alternative_date::DATE
) AND NOT EXISTS (
SELECT 1 FROM events WHERE "roomId" = '13b46460-162d-4d32-94c0-e27dd9246c79'
)
(warning: this second sub-query is probably dangerous in real world, since the room will be used more than one time, I assume, so you need to add some time condition to the subquery to check against date)

Displays dates less than the current day's date

In my program, I have a data grid view. I make some amounts due for payment today. I made a display of the amounts that are due and have not been paid (late) I want a code that displays the dates less than the current date of the day I tried that following code but it only fetches the lower days and does not look For the month or year if it is greater or not than the current day's date
tbl = db.readData("SELECT * from Payments where date_batch < CONVERT(varchar(50),GetDate(), 103)", "");
DgvSearch.DataSource = tbl;
The problem with the previous code is that it doesn't fetch the date lower by day, month and year.
Fetches the date less than the current date in terms of day only I want in terms of day, month and year
Ok, so I'm going to assume date_batch is a VARCHAR(10) or similar and contains data like:
28/12/2021
29/11/2021
30/08/2021
31/12/2021
As you can see these "strings that look like dates to a human" are in order. They are not in date order, they are in alphabetical order. Big difference - SQLServer sorts strings alphabetically. When you ask for strings "less than x" it uses alphabetical sorting rules to determine "less than"-ness
Don't stores dates in a string. SQLServer has several date specific datatypes. Use them.
The following process will dig you out of the hole you've dug yourself into:
ALTER TABLE Payments ADD COLUMN BatchDate DATE;
UPDATE Payments SET BatchDate = TRY_CONVERT(Date, date_batch, 103);
Now go look at your table and sanity check it:
SELECT * FROM payments WHERE batchdate is null and date_batch is not null
This shows any dates that didn't convert. Correct their wonky bad data and run the update again.
Do another select, of all the data, and eyeball it; does it look sensible? Do you have any dates that have been put in as 02/03/2021 when they should have been 03/02/2021 etc
Now your table is full of nice dates, get rid of the strings;
ALTER TABLE Payments DROP COLUMN date_batch;
Maybe rename the column, but in SQLServer and c# WeCallThingsNamesLikeThis, we_dont_call_them_names_like_this
sp_rename 'Payments.BatchDate', 'date-batch', 'COLUMN';
Now you can do:
SELECT * FROM payments WHERE batchDate < GetDate()
And never again store dates in a string

Include records occurring within a date period

50 records in databank. I prepared a query to select contracts with ending dates between 1/1/2019 and 12/31/2020. Some of the records have dates outside the 12/31/2020; 12/31/2021. I want those records included as they were active during the queried period.
The between query only returns records with the ending date of 12/31/2020. I changed the criteria to end period between 1/1/2019 and 12/31/2021 and not 12/31/2022. That returns records before end end date of 12/31/20 and outside the start of the end period of 1/1/2019.
I've tried about 10 other things (can't remember all of them) regardless am not getting the results I need.
I'm not VBA/SQL friendly, I'm a query kind of user. Sorry if that makes my question a little more difficult.
Thank you soooo much for any direction you can give me!!
select *, DATE_FORMAT(*datetime_column*,'%m/%d/%Y') from *table_name* where *datetime_column* between '1/1/2019' and '12/31/2020'
I think the format of date leads to 'query don't satisfy correct result' problem. You could convert the date to this format and check the result

query takes longer time to execute even if index are created

I have table DB_TBL where historical data are inserted from tool on 5th of every month. As its historical data the number of rows inserted is very large. For example i checked the count for this month and its 1626521.
This table contains 50 columns. But i am interested to check only 5 columns. There is gui from the front end which is using this 5 columns and where i am providing the filter to get the one month data everytime for example for previous month as closure_date between 01.01.2020 and 31.01.2020.
Select Client_key, Portfolia_Name, Closure_date,
Currency_Type, Balance from DB_TBL
where CLOSURE_DATE between
to_date ('01.01.2020','dd.mm.yyyy') and to_date ('31.01.2020','dd.mm.yyyy');
This query is very slow and takes more than 30 minute to run. This problem is very critical as the same issue i faced from the gui. I have provided index to Closure_date column. But still it does not improve performance.
Is there any way i can improve query performance ? May be i can create Virtual based index or create View ?
First, I would write the query using date literals:
Select Client_key, Portfolia_Name, Closure_date, Currency_Type, Balance
from DB_TBL
where CLOSURE_DATE between date '2020-01-01' and date '2020-01-31'
For this query, you want an index on db_tbl(closure_date). If you already have this index, then presumably you have such a large volume of data that it takes a lot of time to return the data. You can change the index to a covering index by including the rest of the columns in the index (after CLOSURE_DATE, which should be first).
That said, if you want all data from January 2020, I would recommend:
where CLOSURE_DATE >= date '2020-01-01' and
CLOSURE_DATE < date '2020-02-01'
This will return all rows, even those that have a time component. This is particularly important in Oracle, because the date data type can have a time component -- even though user interfaces often show only the date.

Get records as of today or up to a certain date in Oracle

Could somebody recommend the query to retrieve records up to today or certain dates?
I'm required to produce an Oracle report where user needs to enter a date and records up to that date will be shown.
I tried
select * from the_table where the_date <= sysdate
However it seems to produce an inaccurate result. What is the better query for this. For now I'm just playing around with sysdate. Later I will need to use a certain date keyed in by the user and all the records up to that date needs to be shown.
Any suggestions?
Sometimes you get inaccurate records because of little differences like minutes and seconds when two dates have the same day/month/year. Try the following
select * from the_table where TRUNC(the_date) <= sysdate
The TRUNC removes the minute and the seconds. Sometimes you get inaccurate records without using that