Order of evaluation of analytic function
Hello
have question quite like this:
with
-This query selects a 'representative' acct_id by Group (about 300 lines in total)
acct_repres as
(
Select distinct acct_id, origin_id, acct_parm_id of
(
Select a.*
source_id
, dense_rank() over (partition by order source_id by nulls first, acct_id acct_nbr origin_id) as odr
account a join account_parm on (a.parm_id = ap.acct_parm_id) ap
)
where odr = 1
)
Select col1
col2
, (select accct_id from ar acct_repres where ar.acct_parm_id = t2.acct_parm_id) col3
, col4 (select count (1) of acct_repres)
of une_table t1
Join other_table t2 on (...)
And here it is. "Acct_repres" subquery returns more than 300 lines when it is run separately. But when it is used in CTE sometimes (depending on the execution plan) she seems to have that one line - the value in the column col4 is '1 ',.
While the value of col3 is NULL for most of the cases.
It looks like the the dense_rank function and the State 'where odr = 1' are evaluated at the end.
When I use the hint to MATERIALIZE the result was the same.
But when I put the result of account_repres in the dedicated table and use this table instead of CTE output is correct.
What is a bug? Or I do something wrong?
PS: my version of db is 11 GR 1 material (11.1.0.7).
some unorganized comments:
-analytical functions are evaluated towards the end of the execution ("' the last set of operations performed in a query with the exception of the final ORDER
BY
clause"- http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm")
-but still the result of a SQL query must be deterministic, so I think that your results are not an expected behavior
-the CBO has some problems with common table expressions (http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/) if they are of great assistance in the structuring of complex queries. In these cases, you can avoid problems by using inline views
-Your query uses the common table expressions in scalar subqueries and scalar subqueries are also likely to confuse the CBO. In addition, they are executed once for each row in your result set (or at least for each different correlation value) and can have a negative impact on the performance of the queries in many cases. Often, they can be replaced by outer joins.
-you say that the suspicion of materialization brings you an erroneous result: the indicator object (online) gives you the correct results?
Concerning
Martin Preiss
Tags: Database
Similar Questions
-
analytical function and the aggregate function
What are the analytical function and the aggregate function. What is the difference between them?Hello
Analytic Functions : -.
Analytical functions calculate a value of aggregation based on a group of lines. They differ from aggregate functions because they return several rows for each group. The Group of rows is called a window and is defined by the analytic_clause. For each line, a sliding window of lines is defined. The window determines the range of lines used for the calculations for the current line. Window sizes can be based on a physical number of rows or a logic as the time interval.
Analytical functions are the last set of operations performed in a query with the exception of the last ORDER BY clause. Every joint and every WHERE, GROUP BY and HAVING clauses are met before the analytical functions are handled. As a result, analytic functions can only appear in the select list or the ORDER BY clause.
Analytical functions are commonly used to calculate cumulative aggregates, moving, centered and considered.Aggregate functions : -.
Aggregate functions return a line of single result based on the groups of lines, rather than on the unique lines. Aggregate functions can appear in selection lists, as well as in the HAVING and ORDER BY clauses. They are commonly used with the GROUP BY clause in a SELECT statement, where Oracle Database splits the rows in a table when asked or seen in groups. In a query that contains a GROUP BY clause, the select list items can be aggregation functions, GROUP BY constant expressions or expressions involving one of them. Oracle applies the functions of aggregation for each group of rows and returns a single result for each group line.
If you omit the GROUP BY clause, Oracle then applies any aggregate functions in the select list for all rows in the table queried or the view. You use aggregate functions in the HAVING clause to eliminate groups of the output based on the results of aggregate functions, rather than the values of the individual lines of the queried table or view.Let me know if you feel any problem understanding.
Thank you.Published by: varun4dba on January 27, 2011 15:32
-
Purpose of the ORDER BY clause in the analytic function Min Max
I was always using analytical functions like Min Max without ORDER BY clause. But today I used with the ORDER BY clause. The results are very different. I would like to know the purpose of the ORDER BY clause in Min, Max and analogues of analytical functions.user10566312 wrote:
I was always using analytical functions like Min Max without ORDER BY clause. But today I used with the ORDER BY clause. The results are very different. I would like to know the purpose of the ORDER BY clause in Min, Max and analogues of analytical functions.It is a good point that many developers are not so aware. As far as I understand it the way it works.
Some analytical functions do not need an order by or windowing clause (SUM, COUNT, MIN, etc.). If there is no specified window, then the full score is the window.
As soon as you add a command also add you a windowing clause. This window has the default value of 'rank ofrowsbetween unbounded preceding and current_row. So as soon as you add an order by clause, you get a sliding window.Documentation: http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm
windowing_clause
...
You cannot specify this clause unless you specified the order_by_clause. Window limits defined by the clause RANGE you can not specify only a single expression to the > order_by_clause. Please refer to 'Restrictions on the ORDER BY Clause'.example of
with testdata as (select 10 numval, level lv from dual connect by level < 10) select lv, numval, sum(numval) over () sum1, sum(numval) over (order by lv) sum2 from testdata; LV NUMVAL SUM1 SUM2 -- ------ ---- ---- 1 10 90 10 2 10 90 20 3 10 90 30 4 10 90 40 5 10 90 50 6 10 90 60 7 10 90 70 8 10 90 80 9 10 90 90
Published by: Sven w. on 25 Sep 2012 16:57 - default behavior has been corrected. Thanks to Chris
-
A question about the analytical function used with the GROUP BY clause in SHORT
Hi all
I created the following table named myenterprise
If I want to find which is the total sales by city? I'll run the following queryCITY STOREID MONTH_NAME TOTAL_SALES ---------- ---------- ---------- ---------------------- paris id1 January 1000 paris id1 March 7000 paris id1 April 2000 paris id2 November 2000 paris id3 January 5000 london id4 Janaury 3000 london id4 August 6000 london id5 September 500 london id5 November 1000
that works very well and produces the expected result, i.e.SELECT city, SUM(total_sales) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY;
Now in one of my books SQL (Mastering Oracle SQL) I found another method by using the SUM, but this time as an analytic function. Here's what the method of the book suggests as an alternative to the problem:CITY TOTAL_SALES_PER_CITY ---------- ---------------------- london 10500 paris 17000
I know that the analytic functions are executed after the GROUP BY clause has been transformed completely and Unlike regular aggregate functions, they return their result for each line belonging to the partitions specified in the partition clause (if there is a defined partition clause).SELECT city, SUM(SUM(total_sales)) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY;
Now my problem is that I do not understand what we have to use two functions SUM? If we only use one only, i.e.
This generates the following error:SELECT city, SUM(total_sales) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY;
The error is generated for the line 2 column 11 which is, for the expression SUM (total_sales), well it's true that total_sales does not appear in the GROUP BY clause, but this should not be a problem, it has been used in an analytical function, so it is evaluated after the GROUP BY clause.Error starting at line 2 in command: SELECT city, SUM(total_sales) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY Error at Command Line:2 Column:11 Error report: SQL Error: ORA-00979: not a GROUP BY expression 00979. 00000 - "not a GROUP BY expression" *Cause: *Action:
So here's my question:
Why use SUM (SUM (total_sales)) instead of SUM (total_sales)?
Thanks in advance!
:)
In case you are interested, that's my definition of the table:
Edited by: dariyoosh on April 9, 2009 04:51DROP TABLE myenterprise; CREATE TABLE myenterprise( city VARCHAR2(10), storeid VARCHAR2(10), month_name VARCHAR2(10), total_sales NUMBER); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id1', 'January', 1000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id1', 'March', 7000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id1', 'April', 2000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id2', 'November', 2000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id3', 'January', 5000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id4', 'Janaury', 3000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id4', 'August', 6000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id5', 'September', 500); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id5', 'November', 1000);
It is clear that thet Analytics is reduntant here...
You can even use AVG or any analytic function...SQL> SELECT city, 2 avg(SUM(total_sales)) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY 3 FROM myenterprise 4 GROUP BY city 5 ORDER BY city, TOTAL_SALES_PER_CITY; CITY TOTAL_SALES_PER_CITY ---------- -------------------- london 10500 paris 17000
-
Cannot use analytical functions such as lag/lead in odi components 12 c except in the expression
Hi I am a beginner of ODI 12 c
I'm trying to get the last two comments made on the product for a given product id. and load them into a target.
I have a source table something like
Product SR_NO comments LAST_UPDATED_TS
1 good car 2015/05/15 08:30:25
1 car average 2015/05/15 10:30:25
Jeep 2 super 2015/05/15 11:30:25
1 car bad 2015/05/15 11:30:25
Jeep 2 horrible 2015/05/15 09:30:25
Jeep 2 excellent 2015/05/15 12:30:25
I want a target table based on their last timestamp updated as (last two comments)
SR_NO Comment1 Comment2
1 bad average
2 super excellent
I used the logic below to get records in SQL Developer but in ODI 12 c, I'm not able to do this by mapping a source to the target table by applying analytical functions to the columns in the target table. Can someone help me solve this problem
SELECT * FROM)
SELECT SR_NO Comment1, LAG(Comment1,1,) ON Comment2 (SR_NO ORDER BY LAST_UPDATED_TS ASC PARTITION),
ROW_NUMBER() ON RN (SCORE FROM SR_NO ORDER BY LAST_UPDATED_TS DESC)
FROM Source_table
) M
WHERE RN = 1
;
UM, I'm afraid that ODI puts the filter too early in the request, if it generates:
SELECT * FROM)
SELECT SR_NO Comment1, LAG(Comment1,1,) ON Comment2 (SR_NO ORDER BY LAST_UPDATED_TS ASC PARTITION),
ROW_NUMBER() ON RN (SCORE FROM SR_NO ORDER BY LAST_UPDATED_TS DESC)
FROM Source_table
WHERE RN = 1
) M
;
Instead of:
SELECT * FROM)
SELECT SR_NO Comment1, LAG(Comment1,1,) ON Comment2 (SR_NO ORDER BY LAST_UPDATED_TS ASC PARTITION),
ROW_NUMBER() ON RN (SCORE FROM SR_NO ORDER BY LAST_UPDATED_TS DESC)
FROM Source_table
) M
WHERE RN = 1
;
Even by changing the 'run on Hint"of your component of the expression to get there on the source, the request will stay the same.
I think the easiest solution for you is to put everything before the filter in a reusable mapping with a signature of output. Then drag this reusable in your mapping as the new source and check the box "subselect enabled."
Your final mapping should look like this:
It will be useful.
Kind regards
JeromeFr
-
Truncate output of analytical function?
For example this query:
Select month, sum (tot_sales) monthly_sales,.
AVG (Sum (tot_sales)) (any order by month
between 1 above and 1 below) rolling_avg
orders
where year = 2001 and region_id = 6
Group by month;
gives me an output which includes several decimal places for the rolling_avg column.
Is there a way to truncate this? I tried to use the rounded outside the analytical function and surely enough, it didn't work. I can't think otherwise.
You can use an external selection on the result of this query
select trunc(rolling_avg) from ( rolling_avg query);
-
Nth salary using the analytic function
I use under function to calculate second highest with empno and deptno salary.
Is it possible to get the same result with another query without using Assembly only analytical functions condition.using and windows function is possible to get the desired output?
SELECT e.empno,
e.DEPTNO,
tmp. SAL as second_higher_salary
FROM emp e,.
(SELECT Empno,
DEPTNO,
SAL,
DENSE_RANK() (PARTITION BY deptno ORDER of sal) AS rnk
WCP
) tmp
WHERE tmp.deptno = e.deptno
and tmp.rnk = 2
EMPNO DEPTNO SAL
---------- ---------- ----------
7934 10 2450
7782 10 2450
7839 10 2450
7876 20 1100
7369 20 1100
7902 20 1100
7788 20 1100
7566 20 1100
7900 30 1250
7844 30 1250
7654 30 1250
7521 30 1250
7499 30 1250
7698 30 1250
7900 30 1250
7844 30 1250
7654 30 1250
7521 30 1250
7499 30 1250
7698 30 1250
Here's my solution:
Select empno,
DEPTNO,
FIRST_VALUE (sal) (PARTITION BY deptno ORDER by sal desc)
de)
SELECT EmpNo,
DEPTNO,
Decode (DENSE_RANK () OVER (PARTITION BY deptno order by sal desc), 1,-sal, sal) sal
WCP
)
/
EMPNO DEPTNO FIRST_VALUE (SAL) OVER (PARTITIONBYDEPTNOORDERBYSALDESC) ---------- ---------- -----------------------------------------------------
7782 10 2450 7934 10 2450 7839 10 2450 7566 20 2975 7876 20 2975 7369 20 2975 7788 20 2975 7902 20 2975 7499 30 1600 7844 30 1600 7654 30 1600 7521 30 1600 7900 30 1600 7698 30 1600 -
Why the different values for an analytic function of the same group/game
I have the suite of table I'll be using.
Select * from table1;
REC_ID | STATUS | DATE_FROM | DATE_TO
1. C | 7 January 2015 |
2. H | December 3, 2014. 6 January 2015
3. H | October 3, 2014. December 2, 2014
4. H | May 30, 2014. October 2, 2014
5. H | May 29, 2014 | May 29, 2014
6. H | April 16, 2014 | May 28, 2014
7. H | Tuesday, April 25, 2007 April 15, 2014
INSERT statement if you need.
TOGETHER TO DEFINE
CREATE THE TABLE1 TABLE:
(
NUMBER OF REC_ID,
VARCHAR2 (1 BYTE) STATUS NOT NULL,.
DATE_FROM DATE NOT NULL,
DATE OF DATE_TO
);
Insert into TABLE1
(REC_ID, STATUS, DATE_FROM)
Values
(1, 'C', TO_DATE (7 JANUARY 2015 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'));))
Insert into TABLE1
(REC_ID, STATUS, DATE_FROM, DATE_TO)
Values
(2, 'H', TO_DATE (3 DECEMBER 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'), TO_DATE (6 JANUARY 2015 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'));))
Insert into TABLE1
(REC_ID, STATUS, DATE_FROM, DATE_TO)
Values
(3, 'H', TO_DATE (3 OCTOBER 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'), TO_DATE (2 DECEMBER 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'));))
Insert into TABLE1
(REC_ID, STATUS, DATE_FROM, DATE_TO)
Values
(4, 'H', TO_DATE (MAY 30, 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'), TO_DATE (2 OCTOBER 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'));))
Insert into TABLE1
(REC_ID, STATUS, DATE_FROM, DATE_TO)
Values
(5, 'H', TO_DATE (29 MAY 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'), TO_DATE (29 MAY 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'));))
Insert into TABLE1
(REC_ID, STATUS, DATE_FROM, DATE_TO)
Values
(6, 'H', TO_DATE (APRIL 16, 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'), TO_DATE (28 MAY 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'));))
Insert into TABLE1
(REC_ID, STATUS, DATE_FROM, DATE_TO)
Values
(7, 'H', TO_DATE (APRIL 25, 2007 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'), TO_DATE (APRIL 15, 2014 00:00:00 ',' DD/MM/YYYY HH24:MI:SS'));))
COMMIT;
I will exercise more analytical query...
Select rec_id date_from, date_to, status,
min (date_from) over (partition by order of status by date_from desc) min_dt_from_grp,
ROW_NUMBER() over (partition by order of status by date_from desc) rownumberdesc,
ROW_NUMBER() over (partition by order of status by ASC date_from) rownumberasc
FROM table1;
the query result
REC_ID | DATE_FROM | DATE_TO | STATUS | MIN_DT_FROM_GRP | ROWNUMBERDESC | ROWNUMBERASC
1. 7 January 2015 | C | 7 January 2015 | 1. 1
2. December 3, 2014. 6 January 2015 | H | December 3, 2014. 1. 6
3. October 3, 2014. December 2, 2014 | H | October 3, 2014. 2. 5
4. May 30, 2014. October 2, 2014 | H | May 30, 2014. 3. 4
5. May 29, 2014 | May 29, 2014 | H | May 29, 2014 | 4. 3
6. April 16, 2014 | May 28, 2014. H | April 16, 2014 | 5. 2
7. Tuesday, April 25, 2007 April 15, 2014. H | Tuesday, April 25, 2007 6. 1
If you look at the output above, it dates back in the min_dt_from_grp column.
MY question is if the analytical function calculates for a particular/set group, which is by statute and for what min (date_from) partition is 25-apr-2007 for the GROUP H (Status column), then why I have different values returned by the query above in the min_dt_from_grp column.
Hello
Because you have specified an ORDER BY clause for the analytical function. In doing so, you calculate the rows on a window. Since you have not specified a windowing clause, the default applies:
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
-
Analytical functions: FIRST vs FIRST_VALUE
Hello
Can someone please help me understand the difference between PRIME and FIRST_VALUE in Anaytic functions.
I tried below 2 queries, but I see the same output. The only difference I see is that the field of the SAL is ordered FIRST_VALUE, but not the FIRST.
SELECT ename,
DEPTNO,
SAL,
MIN (SAL) keep (dense_rank FIRST
ORDER BY sal) by (deptno partition) FIRST
EMP;
SELECT ename,
DEPTNO,
SAL,
FIRST_VALUE (SAL) over (partition BY deptno arrested by sal) FIRST
EMP;
With the help of: Windows 8.1
Database Oracle 12 c Enterprise Edition Release 12.1.0.1.0 - 64 bit Production
PL/SQL Release 12.1.0.1.0 - Production
"CORE 12.1.0.1.0 Production."
AMT for 64-bit Windows: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production
Hello
Here is an example of when you can use the FIRST analytic function.
Say you want the average sal for each Department, but only for the first year (taken from the hiredate column) in the Department (i.e., the column called f in the query below).
WITH got_hireyear AS
(
SELECT deptno and ename, sal, hiredate
EXTRACT (YEAR FROM hiredate) AS hireyear
FROM scott.emp
)
SELECT deptno, hireyear, hiredate, ename, sal
AVG (sal) DUNGEON (DENSE_RANK FIRST ORDER BY hireyear)
COURSES (PARTITION BY deptno
) In the FORM f
FIRST_VALUE (sal) over (PARTITION BY deptno
ORDER BY hireyear
) AS fv
AVG (sal) over (PARTITION BY deptno
hireyear
), A
OF got_hireyear
ORDER BY deptno
hireyear
ename
;
Output:
HIREYEAR ENAME SAL HIREDATE DEPTNO F FV HAS
------ ---------- ----------- ---------- ------ --------- ------ ---------
10 1981 9 June 1981 CLARK 2450 2450 3725,00 3725.00
10 1981 17 November 1981 KING 5000 3725,00 2450 3725.00
10 1982 23 January 1982 MILLER 1300 3725,00 2450 1300.0020, 1980, 17 December 1980 SMITH 800 800.00 800.00 800
20, 1981, 3 December 1981 FORD 3000 800.00 800 2987.50
20, 1981, 2 April 1981 JONES 2975 800.00 800 2987.50
20, 1987, 23 May 1987 ADAMS 1100 800.00 800 2050.00
20, 1987, 19 April 1987 SCOTT 3000 800.00 800 2050.0030 1981 20 February 1981 ALLEN 1600 1566.67 950 1566.67
May 30 1981 1st 1981 BLAKE 2850 1566.67 950 1566.67
December 30 1981 3 1981 JAMES 950 1566.67 950 1566.67
30 1981 28 - sep - 1981 MARTIN 1250 1566.67 950 1566.67
30-08 - sep - 1981 1981 TURNER 1500 1566.67 950 1566.67
30 1981 22 February 1981 WARD 1250 1566.67 950 1566.67The analytical FIRST_VALUE function can do (except in the very special case where only 1 row has the lowest hireyear, as in deptno = 20). AVG analysis can do (except in the very special case that all lines have the same hireyear as in deptno = 30).
-
Hello experts.
I have data similar to what follows below
create table t1 ( id number(30), description varchar(4000) ); insert into t1 values (1, 'zone'); insert into t1 values (2, 'small'); create table t2 ( id number(30), place varchar(4000), info varchar(4000) ); insert into t2 values (1, 'USA', 'Class U'); insert into t2 values (1, 'Mexico', 'Class M'); insert into t2 values (2, 'Germany', 'Class G');
I need help with something similar to what follows below without using any analytic function
Description of the ID info Place
1 box USA class U
Mexico 1 M class
2 small Germany class G
Any help is appreciated. Thank you
Hello
user13328581 wrote:
... I use an older version of oracle. Oracle 7.
Normally, your developers are older than your software.
You should be able to do what you want with a self-join on t2; a copy (d) should be displayed, and the other copy (c) contains all related values you need for comparison.
SELECT t2d.id
DECODE (t2d.place
MAX (t2c.place)
t1.description
) AS description
t2d.place
t2d.info
FROM t1
, t2 t2d - display
t2 t2c - compare
WHERE t1.id = t2d.id
AND t2d.id = t2c.id
GROUP BY t1.description
t2d.id
t2d.place
t2d.info
ORDER BY t2d.id
t2d.place DESC
;
Output:
ID DESCRIPTION PLACE INFO
---------- -------------------- -------------------- --------------------
1 box USA class U
Mexico 1 M class
2 small Germany class G
I've tested this in Oracle 11, but it should work in Oracle 7.
If this isn't the case, you may need to create a view.
-
HelloI have a doubt about this analytical function to lead,
I have this table,
create table test3 (no number, name varchar2 (30));
Insert into TEST3 (NO, NAME) values (1, 'fen');
Insert into TEST3 (NO, NAME) Values (3, 'DEN');
Insert into TEST3 (NO, NAME) values (2, 'Sun');
Insert into TEST3 (NO, NAME) values (2, 'sen');
Insert into TEST3 (NO, NAME) values (1, 'end');
COMMIT;I put like that with this request.
Select lead don't (don't) over (partition by any order of name), name of test3.NO NAME
1 fen
end
2 Sun
Sen
DENBut I need as below output, I am unable to get the third 'NO' that has a value, I get null for that, even if I partitioned
by the 'NO '.NO NAME
1 fen
end
2 Sun
Sen
3 DENPlease clear my doubt.
Thanks in advance.
Like this
Select decode (NWR, 1, no, null) no
name
de)
Select row_number() over (partition by any order by name) rno
None
name
of test3
)
-
Hello
I have two tables b rates and transactions (b).
For each b.FS, I want to know new amount (b.amt time a.rate to the corresponding line of FS b and if a.na is valid based on the flag of the exclusion and the interval defined in the table's).
It is much easier to explain with an example.
So here we go...
Exclude_flag = E (exclude): for b.fs = 433638, b.na = 80000. I have 2 lines in the table for this fs. Both have E exclude_flag (exclude). I want to go on all the lines in this FS in the table in a query and I return only one row in the result, if and only if b.na falls out of scope of a.na_min_value and a.na_max_values. In this example, it falls outside the range excluded for both lines (first two lines of the table a).
Similarly, exclude_flag = I (Include). for b.fs = 432828, b.na = 17200. I have 2 lines in the table for this fs. Both have an exclude_flag of I (include). I want to go on all the lines in this FS in the table in a query and I return only one row in the result, if and only if b.na is between a.na_min_value and a.na_max_values. In this example, it falls in the range of both the range include for the two lines (line 6 and 7 of the table a).
The following query gives me two lines for each b.fs. It is possible to get what I'm looking for simply using sql (possibly write the analytical function?) or I have to write the pl/sql routine for this?
WITH rates_table
Did YOU (select ' E' include_exclude_flag, "81000 ' na_min_value, na_max_value '81999', '433638' FS, 0.8 of double rate
UNION
Select 'E' include_exclude_flag, na_min_value '84000', na_max_value '84999', '433638' FS, 0.8 of double rate
UNION
Select 'I' include_exclude_flag, na_min_value '12000', na_max_value '12999', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '13000', na_max_value '13999', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '15000', na_max_value '15000', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '16100', na_max_value '18000', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, '17100' na_min_value, na_max_value '18000', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '02440', na_max_value '02470', '016532' FS, 0.35 rate double
UNION
Select 'E' include_exclude_flag, na_min_value ' 21000 ', '21000' na_max_value, ' 200020' FS, 0.35 double rate).
transaction_table AS
(select '433638' FS '80000' NA, 300 double amt)
Union
Select '432828' FS '17200' NA, amt 500 double
)
Select * from rates_table a, transaction_table b
where 1 = 1
and ((b.na PAS entre a.na_min_value et a.na_max_value et a.include_exclude_flag = «E») GOLD ())
b.na between a.na_min_value and a.na_max_value and a.include_exclude_flag = 'I'))
and b.fs = a.fs
;
Any help is greatly appreciated. I use oracle 11i
@OP,
For this kind of problems, we get the number of rows that satisfy the required conditions or who do not meet the required conditions. And then eliminate the line that should be eliminated.
As below, I calculate four counts (number of join lines)
EOBCNT - excluded and Out of Bound
EIBCNT - excluded and in the limit
IOBCNT - included and Out of Bound
IIBCNT - included and within the limits
Once those are calculated, simply return the lines that have EIBCNT and IOBCNT are zero.
For Ex:
> WITH
rates_table
AS LONG AS)
Select 'E' include_exclude_flag, na_min_value '79999', na_max_value '79999', '433638' FS, 0.8 double UNION rates
-Select 'E' include_exclude_flag, na_min_value ' 79999', na_max_value '80000', '433638' FS, 0.8 double UNION rate - TEST - THE
-If you uncomment the last line and then 433638 will not be returned
Select 'E' include_exclude_flag, "81000 ' na_min_value, na_max_value '81999', '433638' FS, 0.8 double UNION rates
Select 'E' include_exclude_flag, na_min_value '84000', na_max_value '84999', '433638' FS, 0.8 double UNION rates
Select 'I' include_exclude_flag, na_min_value '12000', na_max_value '12999', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '13000', na_max_value '13999', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '15000', na_max_value '15000', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '16100', na_max_value '18000', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, '17100' na_min_value, na_max_value '18000', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '02440', na_max_value '02470', '016532' FS, 0.35 rate double UNION
Select 'E' include_exclude_flag, na_min_value ' 21000 ', '21000' na_max_value, ' 200020' FS, 0.35 double rate).
transaction_table AS
(select '433638' FS '80000' NA, amt 300 Union double
Select '432828' FS '17200' NA, amt 500 double
)
getcnts as)
SELECT a.*
b.na, b.amt
, sum (case when (b.na NOT BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'E '.
end) then 1 else 0) on (a.fs partition) Eobcnt
, sum (case when (b.na NOT BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'I '.
end) then 1 else 0) on (a.fs partition) Iobcnt
, sum (case when (b.na BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'E '.
end) then 1 else 0) on (a.fs partition) Eibcnt
, sum (case when (b.na BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'I '.
end) then 1 else 0) on (a.fs partition) Iibcnt
OF rates_table one
transaction_table b
WHERE b.fs = a.fs
)
getrows as)
Select x.*, row_number() on
(partition by order of fs with null desc) getcnts rn x
where IOBCNT = 0 and eibcnt = 0 - remove lines that are not needed (IF and ONLY if)
)
Select * from getrows
where rn = 1 - to limit a SINGLE row (arbitrarily)
INCLUDE_EXCLUDE_FLAG NA_MIN_VALUE NA_MAX_VALUE FS RATE NA AMT EOBCNT IOBCNT EIBCNT IIBCNT RN
-------------------- ------------ ------------ ------ ---------- ----- ---------- ---------- ---------- ---------- ---------- ----------
433638 84999 84000.8 E 80000 300 3 0 0 0 1
I hope this helps.
-
Return one row of an analytic function
Hello
I pulled the following query:
Select ID_STORNO, first_value (COD_CONTATTO) ON (Partition of COD_CONTATTO
order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT
rows between unbounded preceding and following unbounded)
as COD_CONTATTO_LAST
of WT_STR_ESG_CONTATTO;
The result is:
2160603 C1-H83J1N 2160603 C8-9FOHXJS 2258072 C1-H83J1N But I just need to take the following lines
2160603 C8-9FOHXJS 2258072 C1-H83J1N Because for the same value of ID_STORNO, I just need to get a value of COD_CONTATTO (to select the best value using COD_PRIORITY and FT_DAT_OPEN_CNT). What is wrong inside the query? I just use 2 or 3 times the oracle analytic functions.
Best regards
As SomeoneElse... you need a where clause clause in order to choose the ones you want.
To do this, the typical is to select a column that you use for this reason, such as:
"I want to just the first record in each group..."
Select id_storno, cod_contatto_last from)
Select ID_STORNO, first_value (COD_CONTATTO) ON (Partition of COD_CONTATTO
order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT
rows between unbounded preceding and following unbounded)
as COD_CONTATTO_LAST,
ROW_NUMBER() OVER (Partition of COD_CONTATTO
order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT
rows between unbounded preceding and following unbounded)
as rnum
of WT_STR_ESG_CONTATTO
)
where rnum = 1
/
I prefer to use rownumber in this case, so I always have a rnum = 1...
Usually, you must use the same partition/command by as your other folders (it is usually a good idea... maybe not, depending on your needs, however)
-
Is there a shorter way (better) with analytical functions?
Here's a little test scenario:
For each id, I want to add all the values of m only when they have a different type. It would be a long journey:create table t ( id number, pos number, typ number, m number); insert into t values (1,1,1,100); insert into t values (1,2,1,100); insert into t values (1,3,2, 50); insert into t values (2,1,3, 30); insert into t values (2,2,4, 70); insert into t values (3,1,1,100); insert into t values (3,2,2, 50); insert into t values (4,1,3, 30); insert into t values (4,2,5, 80); insert into t values (4,3,3, 30); insert into t values (5,1,3, 30); insert into t values (5,2,6, 30); insert into t values (6,1,2, 50); insert into t values (6,2,7, 50); insert into t values (6,3,2, 50); insert into t values (7,1,4, 70); insert into t values (7,2,4, 70); insert into t values (7,3,4, 70);
but I wonder, is it possible to get this result with a single statement select using analytic functions, something likewith t1 as (select id, typ, min(m) m1 from t group by id, typ) select id, sum(m1) f from t1 group by id order by 1; ID F ---------- ---------- 1 150 2 100 3 150 4 110 5 60 6 100 7 70
select id, sum(m) over (partition by distinct typ) F -- this does not work. It's only an idea how it might look like from t group by id;
This is firstly a collection with the id, type with calculation of the min for each id, type the combination.
By subsequently for each id of the sum of the minutes (for each combination of id, type for this particular id) is summarized.select distinct id, sum(min(m)) over (partition by id) from data group by id, typ order by id
Published by: chris227 on 15.03.2013 07:39
-
Analytical function - return 2 values
I don't know I need to use an analytical function to do this, I can't do things. I appreciate the help.
Statements of table and insert:
Here is what I tried that gets me close:create table TST_CK ( DOC_ID NUMBER(6) not null, ROW_SEQ_NBR NUMBER(6) not null, IND_VALUE VARCHAR2(2) null ) INSERT INTO TST_CK VALUES ('1','6',NULL); INSERT INTO TST_CK VALUES ('1','5',NULL); INSERT INTO TST_CK VALUES ('1','4','T'); INSERT INTO TST_CK VALUES ('1','3','R'); INSERT INTO TST_CK VALUES ('1','9',NULL); INSERT INTO TST_CK VALUES ('1','10',NULL); INSERT INTO TST_CK VALUES ('1','7','T'); INSERT INTO TST_CK VALUES ('1','8','R'); INSERT INTO TST_CK VALUES ('2','1',NULL); INSERT INTO TST_CK VALUES ('2','2',NULL); INSERT INTO TST_CK VALUES ('2','3','T'); INSERT INTO TST_CK VALUES ('2','4','R'); INSERT INTO TST_CK VALUES ('2','5',NULL); INSERT INTO TST_CK VALUES ('2','6',NULL); INSERT INTO TST_CK VALUES ('2','7','T'); INSERT INTO TST_CK VALUES ('2','8','R'); INSERT INTO TST_CK VALUES ('4','1',NULL); INSERT INTO TST_CK VALUES ('4','2',NULL); INSERT INTO TST_CK VALUES ('4','3','X1'); INSERT INTO TST_CK VALUES ('4','4',NULL); INSERT INTO TST_CK VALUES ('4','5',NULL); INSERT INTO TST_CK VALUES ('4','6',NULL); INSERT INTO TST_CK VALUES ('4','7','T'); INSERT INTO TST_CK VALUES ('4','8','R'); INSERT INTO TST_CK VALUES ('4','9',NULL); INSERT INTO TST_CK VALUES ('4','10',NULL); INSERT INTO TST_CK VALUES ('4','11',NULL); INSERT INTO TST_CK VALUES ('4','12',NULL); INSERT INTO TST_CK VALUES ('4','13','T'); INSERT INTO TST_CK VALUES ('4','14','R'); INSERT INTO TST_CK VALUES ('4','15',NULL); INSERT INTO TST_CK VALUES ('4','16',NULL); COMMIT;
Here is my desired outcome:SELECT MAX (TST_CK.DOC_ID), MAX (TST_CK.ROW_SEQ_NBR), TST_CK.IND_VALUE FROM ASAP.TST_CK TST_CK WHERE (TST_CK.IND_VALUE IS NOT NULL) GROUP BY TST_CK.IND_VALUE ORDER BY 2 ASC
CV_1 CV_2
Or even better result would be:
T R
Result:concat(CV_1,CV_2)
T,R
Thanks for looking
GGMoney says:
Basically, I just need to make sure what I captures the last T and R entered in the columnStill not clear. You want to find the last two lines (function ROW_SEQ_NBR) where IND_VALUE is 't' & 'R', right? If so:
with t as ( select doc_id, row_seq_nbr, ind_value, row_number() over(partition by ind_value order by row_seq_nbr desc) rn from tst_ck a where ind_value in ('T','R') ) select doc_id, row_seq_nbr, ind_value from t where rn = 1 / DOC_ID ROW_SEQ_NBR IN ---------- ----------- -- 4 14 R 4 13 T SQL>
SY.
Maybe you are looking for
-
How can I get rid of the unwanted bookmarks?
I need help deleting bookmarks. I tried the syntax highlighting and right-clicking to remove them, but nothing works.
-
If I am on a site and you click a link to open a new tab, the tab is open but never load the page. I just get a blank page, and instead of the name of the page on the new tab, it says 'click (GIF, produce 1 x 1 Image)' and the address bar will have t
-
Insert a space character between each character in a string
I have an array of length variant. Each element of the array contains a string. I want to put a space character "" between each character of each string in the array. The length of the string in each element of the array varies. I played with nest
-
I got this alert in Device Manager and can't find the right driver to slove. In any case my office seems to be normal in the operation at this stage. I'm not running "hp update", but he said "no new updates available". my details: Model: pavilion hpe
-
The script files are corrupted in vista on my computer laptop r61i
Technical support of McAfee said that my scripts files are corrupted in vista on my computer r61i laptop... How can I download and replace on a preinstalled OS * original title - scripts to repair files in thinkpad r61i of vista preinstalled v