Get Data for every weeks average of high and low prices - oracle

I have table named as
FP_BASIC_BD
whose structure is like as follows.
Name Null? Type
-------------- -------- ------------
FS_ID NOT NULL VARCHAR2(20)
DATE NOT NULL DATE
CURRENCY CHAR(3)
PRICE FLOAT(126)
PRICE_OPEN FLOAT(126)
PRICE_HIGH FLOAT(126)
PRICE_LOW FLOAT(126)
VOLUME FLOAT(126)
For any value of FS_ID I would like to calculate
weekends date
week start date
average(High of PRICE_HIGH+Low of PRICE_LOW)
for all the weeks.
Weekend is considered as Friday IF Fridays data not available then try to get 1 or any day before but after or equal to Monday of that week.
Week Start is considered as Monday. If Mondays data not available then get 1 or any day ahead but less or equal to to the weekend in above step.
Task of getting weekend and week start dates can be done in different query. But i want to use it as a range in a single query and get the required average.

First, please don't use Oracle keywords (e.g. date) as column names.
Second, your description of how you want to calculate the average is ambiguous, so I included a couple of options.
I think this should work to get your week start / end dates.
select
trunc("DATE", 'IW') as week,
min(trunc("DATE")) as week_start,
max(trunc("DATE")) as week_end,
(max(price_high) + min(price_low)) / 2 as avg_price_weekly,
avg(price_high+price_low) as avg_price_daily
from fp_basic_bd
where to_char("DATE", 'DY') not in ('SAT','SUN')
group by trunc("DATE", 'IW');
From your description, I'm guessing you don't have any Saturday/Sunday dates in this table. If you do, and you specifically want to exclude them from this query, let me know and I'll update my answer.
Edit: updated to exclude weekend days (sat/sun).

Related

Convert difference of dates to date with timestamp

How to convert the difference of 2 dates with a timestamp to date with timestamp again, Oracle giving number but i want to compare timestamp.
select emp_date>to_date(sysdate,'yyyy-MM-dd HH24:MI:SS')-todate('2021-03-22 10:20:12') from emp;
above query giving error: expected date but got NUMBER.
Thanks in advance
What you are saying makes no sense. Difference of two DATE datatype values is number of days between them. For example
SQL> select sysdate - to_date('21.03.2021 13:12', 'dd.mm.yyyy hh24:mi') diff from dual;
DIFF
----------
,943217593
SQL>
You CAN convert it to a prettier format (days, hours, minutes, seconds), but it is still a NUMBER, it is not a date.
Therefore, you can't compare EMP_DATE (which is a DATE datatype column, isn't it?) to a number as it just doesn't make sense.
Is 22nd of March 2021 larger or smaller than 0.94? It's neither.
[TL;DR] You cannot as your data types do not match and it does not make sense to compare a date/time value to an interval.
If you do:
date_value1 - date_value2
You will get a NUMBER data type representing the number of (fractional) days between the two date values.
You can explicitly cast the subtraction operation to get an INTERVAL DAY TO SECOND data type using:
(date_value1 - date_value2) DAY TO SECOND
So, for your code that would be:
SELECT emp_date > ( sysdate - TO_DATE( '2021-03-22 10:20:12', 'YYYY-MM-DD HH24:MI:SS' ) ) DAY TO SECOND
FROM emp;
However, that will fail as you cannot compare a DATE to an INTERVAL DAY TO SECOND and SQL does not have a boolean data type so > does not make sense.
To fix that later point you could use a CASE expression but the difference in data types is a show-stopper as you can't compare a date to an interval.
but i want to compare timestamp.
You don't have a TIMESTAMP data type, you have either a number (representing an interval in days) or an INTERVAL data type. If you want to convert it back to a DATE or TIMESTAMP then you need to add your interval to an epoch value.

Alter a timestamp column in an oracle table with default value as '0000-00-00 00:00:00'

Can we assign a default value '0000-00-00 00:00:00' in oracle as we do in mysql as shown below ?
Sample query in mysql:
ALTER TABLE . MODIFY COLUMN TIMESTAMP DEFAULT '0000-00-00 00:00:00';
No - in Oracle neither year, month, or day can be set to zero. I suggest using NULL instead.
dbfiddle here
EDIT
Of course, having now gone back through one of my old questions and crawled down a wormhole or two I see that you can get a year of zero to be accepted - but it still appears that month and day cannot be zero. To get the year of zero in you have to use an ANSI date literal - e.g. DATE '0000-01-01' is considered acceptable. I don't know if the various date routines and date calculations will like this - for example, TO_CHAR(DATE '0000-01-01', 'DD-MON-YYYY') produces a result of '00-000-0000', which is certainly not what I'd expect, but perhaps it's good enough for your purposes. Note that you can't go the other way with this - TO_DATE('00-000-0000', 'DD-MON-YYYY') produces the expected ORA-01847 - day of month must be between 1 and last day of month error.
Does anybody really know what time it is..? :-)

convert date to order day of the month

How can I convert date to the order day of the month in ORACLE?
Ex: 31/07/2000 -> "Monday, the Thirty-First of July, 2000".
Is there any format date which can solve this problem?
Thanks so much!
Yes, there is - you need to combine some format elements (and modifiers) with a bit of boilerplate text (to add "the" and "of"). Like this:
select to_char( to_date('31/07/2000', 'dd/mm/yyyy')
, 'fmDay, "the " Ddspth "of" Month, yyyy') as spelled_out_date
from dual;
SPELLED_OUT_DATE
---------------------------------------
Monday, the Thirty-First of July, 2000
Note that, while the names of days of the week and calendar months depend on your session's then-current NLS_DATE_LANGUAGE, the Ddspth element will always be in English. So, alas, this solution DOES NOT WORK for other languages.

SQL Query with date that does not exist

I was recently working on some SQL queries where I had to separate the values into various months (e.g. December, January, Feb...) and make some comparisons. However I was at a loss for wondering about what to use for the ending day of each month. So I was wondering what happens when you define a date that does not technically exist. For example.
WHERE myDate BETWEEN '2016-01-01' AND '2016-02-31' //note Feb 31 does not exist.
My assumption (based on my current query seeming to return the proper results) is that it simply ignores the extra dates that do not exist (e.g. when counting the dates, it simply has no dates for the range outside of the regular dates).
Is this undefined behavior that I may run into trouble with in the future? Or is there a better way to do this to cover all basis?
Why don't you want to use LAST_DAY() function:
SELECT SYSDATE, trunc(LAST_DAY(SYSDATE)) last,
LAST_DAY(SYSDATE) - SYSDATE days_left FROM DUAL;
Output:
SYSDATE LAST DAYS_LEFT
----------------- ----------------- ----------
03.02.16 18:38:26 29.02.16 00:00:00 26
1 row selected.

Date Logic Question

I am developing a billing system and need help as i am clueless here. I have some customers and their utility bill payment is responsibility of my bank. In my system I am registering customers with their utility company along with the following data.
**Biller Table
Customer Josh & Co.
Utility Company A
Consumer #............... AL12111
Bill Generation Date .... 07th of every month
Bill Due Date ........... 18th of every month
Cut off Date of my bank.. 12th of every month
Now on bill generation screen I am taking inputs like the following.
Consumer # ...... AL12111
Bill Entry Date.. 29-10-2010 (Readonly field System Date)
Customer .... Josh & Co.
Billing Month .... October
Amount Due ... 5,000 US$
Now my problem is that how do i figure out if accountant is generating bill before due date or not but in biller table i dont have month and year just the date of month.
I would appreciate your help and solution advise..
thanks
This isn't a SQL Server question or even a programming question - this is a business question that can only be answered by your business analyst/stakeholder.
To expand, you have a date of entry yyyy-mm-dd (lets call that dt_entry, a datetime) and a day of month which the bill is due, lets call that d (an integer).
You would manufacture a date in the same month as the date of entry (note that for dates near the end of the month, you will need to get some clarification from the business as to what the rules are - perhaps using some kind of sliding window).
So the due date in date form would be dt_entry - DAY(dt_entry) + d (SQL Server datetime can use simple integer addition for days, no need for DATEADD).
You can see where this will cause a problem near the end of the month, because d will be small (say 1), and the entry date will be large, (say 31) and then the hypothetical due date is really the next month. But what if a person is paying really early (like the 5th for a due date of the 25th)?
Also, you may need to consider the short months, since there cannot be a 31st in February on which to be due.
All these are programming problems which only have business answers.
CREATE PROCEDURE [sp_BillDateCheck]
#CURMONTH VARCHAR(3),
#MONTHNUM INT OUTPUT,
#EBDATEMATCH VARCHAR(90) OUTPUT
AS
BEGIN
DECLARE #ENTRYDATE DATETIME
SELECT #ENTRYDATE = GETDATE() --GET CURRENT ENTRY DATE
--GET MONTH NUMBER BY GIVING MONTH NAME
SELECT #MONTHNUM = DATEPART(mm,CAST(#CURMONTH + ' 1900' AS DATETIME))
IF DATEPART(MONTH, #ENTRYDATE) = #MONTHNUM
SELECT #EBDATEMATCH = 'ENTRY DATE AND BILLING MONTH ARE SAME'
IF DATEPART(MONTH, #ENTRYDATE) < #MONTHNUM
SELECT #EBDATEMATCH = 'ENTRY DATE IS LESS THAN BILLING MONTH'
IF DATEPART(MONTH, #ENTRYDATE) > #MONTHNUM
SELECT #EBDATEMATCH = 'ENTRY DATE IS GREATER THAN BILLING MONTH'
END
GO`
thanks to JNK for providing DATEPART hint. I am not a pee brain for sure

Resources