Oracle Query for data in specific quarter from previous year - sql

I have an excel spreadsheet that queries an oracle database for some data. I sue excel to do some calculations and then post it share point.
I need to gather data from the 4th quarter of last year (2013) my data selection look like this
Where "TABLE". "DATEFIELD" >= ADD_MONTHS (TRUNC (SYSDATE, 'MONTH'), - 1)
and "TABLE". "DATEFIELD" < TRUNC (SYSDATE, 'MONTH')
How would I make this look at October, November, and December of 2013?

where to_char("TABLE"."DATEFIELD", 'qyyyy') = '42013'
Please refer to this oracle documentation link for the specific meaning of q and yyyy.
In short, to_char(<date expression>, <format model>) returns a string whose meaning is specified by the format model and whose values is dependent on the date expression.
Here, the q tells to return a single character identifying the quarter of the date expression (4 = Oct through Dec). Then yyyy specifies to return the year as four characters.
All dates that fall within the last quarter of 2013 are, according to this format model, equal to 42013.

Related

SELECT dates within one season (between two dates, of any year)

Is it possible in Oracle SQL to select rows where one column is a date, and we want this date to be between two dates irrespective of the year.
For example if the interval is summer, i'd want to be able to have any dates bewteen 20th of june and 22nd of september, where the year can be 1999, 2000, 2018, 2897 etc.
You can convert to a string of the form MM-DD and compare that:
where to_char(col, 'MM-DD') between '06-20' and '09-22'

Querying data from quite old IBM iseries AS400 DB2 (date format issue)

I am quite a newbie in querying data from databases and now I am currently having an issue with date format in very old (I don't know exact version) IBM iSeries AS400 DB2 database. My problem is that the date is stored in this DB in three separate columns as whole number (column day + column month + column year) and I need to connect to this DB via ODBC in Excel and filter just a few rows according to desired date span (e.g. from 1st December 2019 until 31st December 2019). In this case I don't want to use PowerQuery to do all the modifications, because the complete table has millions of rows. I want to specify the filter criteria within SQL string so the PowerQuery doesn't have to load all the rows...
My approach was following:
I've created 6 parameter cells in Excel sheet where I simply defined Date From (e.g. cell 1 = '01', cell 2 = '12' and cell 3 = '2019') and Date To (same logic for parameter cells 4, 5 and 6). Then I mentioned these parameter cells in SQL string where I defined:
(Day >= Parameter cell 1, Month >= Parameter cell 2, Year >= Parameter cell 3)
and
(Day <= Parameter cell 4 etc.)
This worked quite good for me, but only when I liked to export just a few hundreds of lines within the same year. But now I am facing to an issue when I like to export data from 1st December 2019 to 31st January 2020. In this case my "logic" doesn't work, because Month From is '12' and Month To is '01'.
I've tried another approach with concat SQL function to create text column like '2019-12-01' and then convert this column to datetime format (with cast to varchar8 first), but it seems that this approach doesn't work for me, because everytime I get an error which says: "Global variable DATETIME not found".
Before I post you some of my code, could I ask you for an advise, if you can think of a better solution or approach for my issue?
Many thanks and have a great day :-)
A simple solution would be
select * from table where year * 100 + month between 201912 and 202001

How to get the data for the last 12 months and split and month-wise in HIVE?

Table format for the date column is "yyyyMMdd" and I'm using the following functions to convert into standard format so that HIVE day, months and year can be performed to get the respective values.
(from_unixtime(unix_timestamp(cast(created_day as STRING) ,'yyyyMMdd'), 'yyyy-MM-dd'))
To get the current year data, I would subtract the year obtained from all the records with the year returned by the current date and if it return zero, then it falls in this year.
(year(current_date()) - year(from_unixtime(unix_timestamp(cast(created_day as STRING) ,'yyyyMMdd'), 'yyyy-MM-dd'))) = 0
Problem: If the current date falls in January, I would get only January data month, but i need to get the data from February(last year) to January(current year)?
Also I need to scale this to obtain the last 24 months.
I always set my date range parameters outside of Hive and pass them as arguments as this lends itself to reproducibility and testability.
select <fields> from <table> where created_day between ${hiveconf:start_day} and ${hiveconf:end_day}

SQL ORACLE Get week numbers from multiple datetime rows

I have 70.000 rows of data, including a date time column (YYYY-MM-DD HH24-MM-SS.).
I want to split this data into 3 separate columns; Hour, day and Week number.
The date time column name is 'REGISTRATIONDATE' from the table 'CONTRACTS'.
This is what I have so far for the day and hour columns:
SELECT substr(REGISTRATIONDATE, 0, 10) AS "Date",
substr(REGISTRATIONDATE, 11, 9) AS "Hour"
FROM CONTRACTS;
I have seen the options to get a week number for specific dates, this assignment concerns 70.000 dates so this is not an option.
You (the OP) still have to explain what week number to assign to the first few days in a year, until the first Monday of the year. Do you assign a week number for the prior calendar year? In a Comment I asked about January 1, 2017, as an example; that was a Sunday. The week from January 2 to January 8 of 2017 is "week 1" according to your definition; what week number do you assign to Sunday, January 1, 2017?
The straightforward calculation below assigns to it week number 0. Other than that, the computation is trivial.
Notes: To find the Monday of the week for any given date dt, we can use trunc(dt, 'iw'). iw stands for ISO Week, standard week which starts on Monday and ends on Sunday.
Then: To find the first Monday of the year, we can start with the date January 7 and ask for the Monday of the week in which January 7 falls. (I won't explain that one - it's easy logic and it has nothing to do with programming.)
To input a fixed date, the best way is with the date literal syntax: date '2017-01-07' for January 7. Please check the Oracle documentation for "date literals" if you are not familiar with it.
So: to find the week number for any date dt, compute
1 + ( trunc(dt, 'iw') - trunc(date '2017-01-07', 'iw') ) / 7
This formula finds the Monday of the ISO Week of dt and subtracts the first Monday of the year - using Oracle date arithmetic, where the difference between two dates is the number of days between them. So to find the number of weeks we divide by 7; and to have the first Monday be assigned the number 1, instead of 0, we need to add 1 to the result of dividing by 7.
The other issue you will have to address is to convert your strings into dates. The best solution would be to fix the data model itself (change the data type of the column so that it is DATE instead of VARCHAR2); then all the bits of data you need could be extracted more easily, you would make sure you don't have dates like '2017-02-29 12:30:00' in your data (currently, if you do, you will have a very hard time making any date calculations work), queries will be a lot faster, etc. Anyway, that's an entirely different issue so I'll leave it out of this discussion.
Assuming your REGISTRATIONDATE if formatted as 'MM/DD/YYYY'
the simples (and the faster ) query is based ond to to_char(to_date(REGISTRATIONDATE,'MM/DD/YYYY'),'WW')
(otherwise convert you column in a proper date and perform the conversio to week number)
SELECT substr(REGISTRATIONDATE, 0, 10) AS "Date",
substr(REGISTRATIONDATE, 11, 9) AS "Hour",
to_char(to_date(REGISTRATIONDATE,'MM/DD/YYYY'),'WW') as "Week"
FROM CONTRACTS;
This is messy, but it looks like it works:
to_char(
to_date(RegistrationDate,'YYYY-MM-DD HH24-MI-SS') +
to_number(to_char(trunc(to_date(RegistrationDate,'YYYY-MM-DD HH24-MI-SS'),'YEAR'),'D'))
- 2,
'WW')
On the outside you have the solution previous given by others but using the correct date format. In the middle there is an adjustment of a certain number of days to adjust for where the 1st Jan falls. The trunc part gets the first of Jan from the date, the 'D' gets the weekday of 1st Jan. Since 1 represents Sunday, we have to use -2 to get what we need.
EDIT: I may delete this answer later, but it looks to me that the one from #mathguy is the best. See also the comments on that answer for how to extend to a general solution.
But first you need to:
Decide what to do dates in Jan before the first Monday, and
Resolve the underlying problems in the date which prevent it being converted to dates.
On point 1, if assigning week 0 is not acceptable (you want week 52/53) it gets a bit more complicated, but we'll still be able to help.
As I see it, on point 2, either there is something systematically wrong (perhaps they are timestamps and include fractions of a second) or there are isolated cases of invalid data.
Either the length, or the format, or the specific values don't compute. The error message you got suggests that at least some of the data is "too long", and the code in my comment should help you locate that.

Calculating remaining time to a given benchmark (in weeks) in Oracle

Here's what I'm up to: I have some data that represents a goal that students are supposed to reach by a given benchmark (in this case, June 15th). I'm looking at a transactional table and running some rollup queries that attempt to figure out how many students were 'on track' at a given point in time, using the techniques described in 'Filling Gaps in Data' and 'Filling Gaps in an Inventory Table' to calculate running/cumulative totals and densify the data.
http://download.oracle.com/docs/cd/B28359_01/server.111/b28313/analysis.htm#i1014934
To express student 'progress to the goal' at each row in the table, I'm trying to figure out fractionally how much of the year is left until June 15th, allowing me to compare the running total to a pro-rated version of the goal.
My data looks like:
Measure Goal Year Week Date (YYYY-WW)
106141 400000 2011 42 2011-42
128886 400000 2011 43 2011-43
145449 400000 2011 44 2011-44
156921 400000 2011 45 2011-45
I have a workaround, but it's really hacky and awful.
,case
when year = 2012 then 24 - week
when year = 2011 then (52 - week) + 24
else null
end as weeks_to_june_15
(June 15th is the 24th week of 2012). Is there a more elegant even marginally correct way to do this? Every time I attempt the calculations using date functions I get illegal number or literal does not match format string errors.
It seemed like someone accomplished something somewhat related to what I was trying to do here: https://forums.oracle.com/forums/thread.jspa?threadID=633028
but I'm not sure if rebuilding that date using IYYY and IW would get me where I want to go.
Using Oracle 11gR2 Express and want to do this in the database, if at all possible.
Thanks!
This is going to depend a lot on your definition of a week. The IW and IYYY formats use the ISO standard which state that a week always begins on Monday and lasts 7 days. This means that, by the standard, 1/1/2011 was part of the 52nd week of 2010. If this doesn't work for you, then you need to start by defining exactly what you mean by a week.
Because the ISO standard is that well-defined, you can treat the first day of the week as equivalent to the week itself, which will allow you to use date math on it accurately. Below is a function that does just that. You could do it all in SQL as well, but PL/SQL makes this sort of thing a little simpler and easier to read.
CREATE OR REPLACE FUNCTION week_diff(p_year NUMBER,
p_week NUMBER,
p_end_date DATE)
RETURN NUMBER AS
v_end_date DATE;
v_start_date DATE;
v_weeks NUMBER;
v_last_week DATE;
BEGIN
v_end_date := TRUNC(TO_DATE(p_end_date, 'mm/dd/yyyy'), 'IW');
v_start_date := TRUNC(TO_DATE('2/1/' || p_year, 'mm/dd/yyyy'), 'IYYY')
+ (p_week * 7);
IF TRUNC(v_end_date, 'IYYY') = TRUNC(v_start_date, 'IYYY') THEN
v_weeks := (v_end_date - v_start_date) / 7;
ELSE
v_last_week := TRUNC(TO_DATE('12/31/' || TO_CHAR(v_start_date, 'yyyy'),
'mm/dd/yyyy'), 'IW');
v_weeks := (v_last_week - v_start_date) / 7
+ TO_NUMBER(TO_DATE(v_end_date, 'IW'));
END IF;
RETURN v_weeks;
END week_diff;
trunc (to_date('15-jun-2012') - sysdate)
will give you the number of calendar days between now and next June 15th.
That should get you started.
If you have a stored date/time data item, this expression:
trunc (stored,'DAY')
yields midnight on the preceding Sunday (see http://www.techonthenet.com/oracle/functions/trunc_date.php), so for example,
select count(*) events_per_week,
trunc(event_time,'DAY') week_starting
from event
group by trunc(event_time,'DAY')
will tell you how many events per week you have in the event table. This is a valuable way of summarizing data week by week, because it works over both short and multi-year time periods.
If your business rules require your week to start on Monday, do this instead.
1+trunc(stored-1,'DAY')
If you want a date/time data item from something like '2011-43' then do
to_date('2011-43','YYYY-WW')
or
to_date('2011-43','YYYY-IW')
depending on whether you use ISO week numbers. See http://www.techonthenet.com/oracle/functions/to_date.php.
I much prefer the Sunday-midnight way of identifying a week; it's quite intuitive to read ("Week beginning 13-Nov-2011") and handles end-of-year rollovers in a straightforward way.