Date Logic Question - business-logic

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

Related

Oracle Apex 19 - Date Picker - The application item stores the wrong 20th century, selecting a 19th date from the calendar

On my page I have an application item where the user has to select the date of birth from a date picker calendar. Since the user must be of age (according to Italian law) and I do not allow entry for people over 90, I have set the minimum and maximum to -100 and -18. When selecting the year, if the user selects a 19th century date from the date picker, the system mistakenly stores the corresponding 20th century year. How can I solve? I would like to avoid dividing the date into 3 distinct elements(day+month+year).
I solved the issue with explicit setting the format mask DD-MON-YYYY on the date picker application item. The YYYY format uses the selected century correctly. I guess that by default the date picker format considered is DD-MON-RRRR.
This helps
"What is the difference between 'YYYY' and 'RRRR' in Oracle SQL"
What is the difference between 'YYYY' and 'RRRR' in Oracle SQL

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.

Get Data for every weeks average of high and low prices

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

months_between for a leap year

When I find months between 28-FEB-11 and 29-FEB-12, months_between function in oracle returns 12. Actually it should be 12.096. This function is not calculating for the leap year proper.
For between 28-FEB-11 and 29-FEB-12, it is 1 year(12 months) and 1 day.
select months_between('28-FEB-12', '28-FEB-11') from dual; -- 12
**select months_between('29-FEB-12', '28-FEB-11') from dual; -- 12**
select months_between('28-FEB-12', '27-FEB-11') from dual; -- 12.0322
select months_between('27-FEB-12', '28-FEB-11') from dual; -- 11.9677
is this an Oracle bug??..
-Vishwa
From the Oracle documentation:
MONTHS_BETWEEN returns number of months between dates date1 and date2. If date1 is later than date2, then the result is positive. If date1 is earlier than date2, then the result is negative. If date1 and date2 are either the same days of the month or both last days of months, then the result is always an integer. Otherwise Oracle Database calculates the fractional portion of the result based on a 31-day month and considers the difference in time components date1 and date2.
So it's following the documented behavior. It's just not what you expected.
It's not a bug because ORACLE says so, it's a logical error driven by a human (and documenting as something rigth) which is worse.
How come if difference between the last days of January and February months is exactly 1 month (29 exact days). Please see below:
MONTHS_BETWEEN('29-FEB-12','31-JAN-12')
1
With an extra day (30 days) the difference in months is less than 1. Please see below:
MONTHS_BETWEEN('29-FEB-12','30-JAN-12')
.967741935
WRONG. That's not rigth at all!
SQL Server in another hand handle this correctly:
select DATEDIFF(MM,'29-FEB-12','30-JAN-12')
select DATEDIFF(MM,'29-FEB-12','31-JAN-12')
both are 1

complex sql query for finding the average working time of a person in office

I need to retrieve using an oracle based query the working time of an employee which is the time coming in and time going out for an employee based on his transactions in the transaction table.
The transaction table has a date-time field which can be used for this purpose.
The steps involved would be as follows:
1) find the first transaction on a date and the last transaction on the same date - that would be his time in and timeout for that date
2) calculate the overall time-in as the avg of all time-ins on each date, similarly do for time-out
Transaction table is as follows: transctn(transid, resourceid, event, currentdate)
The second requirement is to find the average transactions performed each day, which is basically find the count of transids for each day and then average of that.
The final answer should be, when a userid is provided the query the return result is:
frequent working time(based on average): 9:43 am - 6:45 pm
average transactions performed/day = 43
How do I write the above requirement in oracle SQL or more smartly using Hibernate if Transctn is my Domain class
I have something like this:
select 'frequent working time: '
||(select rtrim(to_char(min(currentdate),'hh:mi pm')) from transctn)
||' - '||(select rtrim(to_char(max(currentdate),'hh:mi pm')) from transctn)
||', average transactions performed/day = '
||(select rtrim(to_char(count(distinct transid)/
count(distinct(to_char(currentdate,'rrmmdd')))) from transctn)
from dual
Firstly, your query has lots of selects from the same table stuck together, which isn't efficient, and makes it harder to read than necessary. And the rtrim isn't doing anything as you've already dictated the format. What you have can be rewritten as:
select 'frequent working time: '|| to_char(min(currentdate),'hh:mi pm')
||' - '|| to_char(max(currentdate),'hh:mi pm'),
'average transactions performed/day = '
|| to_char(count(distinct transid)
/count(distinct to_char(currentdate,'rrmmdd')))
from transctn;
But this isn't averaging properly, and isn't for a specific user. I'm join to assume this is homework and in the usual spirit of the site, try to give you pointers rather than the complete answer...
1) find the first transaction on a date and the last transaction on
the same date - that would be his time in and timeout for that date
You're not far off here, but you're breaking down by date. To get the time-in and time-out for every user, for each day, you could use:
select resourceid, trunc(currentdate), min(currentdate), max(currentdate)
from transctn
group by resourceid, trunc(currentdate)
order by resourceid, trunc(currentdate);
2) calculate the overall time-in as the avg of all time-ins on each
date, similarly do for time-out
You can't average dates directly in Oracle; you'd get ORA-00932: inconsistent datatypes: expected NUMBER got DATE. There are various ways to achieve the effect, you just need to figure out a safe way to treat the date - or more specifically here the time part - as a number. For example, you could treat the time portion as the difference between the actual time and the start of the day, which Oracle returns as a number:
select avg(min(currentdate) - trunc(currentdate)),
avg(max(currentdate) - trunc(currentdate))
from transctn
group by trunc(currentdate);
But you than have to translate that fractional number back into something recognisable. One way of doing that is to add the number to an arbitrary fixed date, and then just extract the time part as a string as you were already doing:
select to_char(date '2000-01-01' + avg(min(currentdate) - trunc(currentdate)),
'HH:MI pm') as avg_time_in,
to_char(date '2000-01-01' + avg(max(currentdate) - trunc(currentdate)),
'HH:MI pm') as avg_time_out
from transctn
group by trunc(currentdate);
This look messy and you might find a better way to do it. If it is homework then I would assume you've been taught methods for doing this sort of thing, or something that can be adapted to be applicable.
This is still for all resources, so you'll need to add a filter to restrict to one user ID. Hopefully this gives you some ideas for tackling the second requirement as well.

Resources