My requirement is to get the recent record grouped by columns c1,c2.I have 50 columns in my source, using query i can apply rownumber() over partition by c1,c2 order by record_time desc, and pick the record where rownumber=1. In short, my oracle query would be:
select c1,c2,....,c50
from (select c1,c2,....,c50,
row_number() over (partition by c1,c2 order by record_time desc ) rn
from table)
where rn = 1;
How can I achieve this using ODI mapping? Please suggest.
Thanks
You have not mentioned the version of ODI you are using, assuming you are using ODI 11g. You can create a yellow interface and create a column for rownum with expression as below
row_number() over (partition by c1,c2 order by record_time desc)
Now use this yellow interface as source in your interface and apply filter on rownum column as below
rownum = 1
While using this you will have to make sure your KM is not adding group by function, else it'll end up in error.
Related
I am new to Oracle I need to Update a Column of a Table with ROW_NUMBER() in oracle
i.e
UPDATE tablefull
SET newcolumn=ROW_NUMBER() OVER (PARTITION BY columnid ORDER BY datecolumn)-1
Since the Window function is not allowed in Update I had tried with joining the table with subquery of same table and do the update
update a
set a.newcolumn= b.upnum
from tablefull a
INNER JOIN (SELECT columnid,ROW_NUMBER() OVER (PARTITION BY columnid ORDER BY datecolumn)-1 AS upnum
FROM tablefull) b ON b.columnid=a.columnid
Since the join and update is also not possible in oracle the above also did not worked out
Please anyone help me in the way to update the newcolumn of the table with ROW_NUMBER() OVER (PARTITION BY columnid ORDER BY datecolumn)-1 in Oracle
Put this query with row_number as source table of merge statement:
merge into tablefull tgt
using (select rowid rwd, columnid,
row_number() over (partition by columnid order by datecolumn) - 1 rn
from tablefull) src
on (src.rwd = tgt.rowid and tgt.columnid = src.columnid)
when matched then update set newcolumn = rn;
dbfiddle
Why is below an invalid sql statement in mysql. It works perfectly in oracle.
SELECT originalAmount,fees,id FROM
(SELECT originalAmount,fees,id, ROW_NUMBER() OVER (PARTITION BY transaction_number ORDER BY eventdate ASC) RANK FROM kir_records where customerid= 1704)
WHERE RANK = 1;
I immediately get a syntax error as soon as paste this in mysql workbench.
Error:
Select is invalid at this position. Expecting '(' at first select.
Is there a workaround to make this work ?
try using this query.
SELECT originalAmount,fees,id FROM
((SELECT originalAmount,fees,id, ROW_NUMBER() OVER (PARTITION BY transaction_number ORDER BY eventdate ASC) RANK FROM kir_records where customerid= 1704))
WHERE RANK = 1;
Look like RANK is a reserved word in MySql. Used backquotes (``) around RANK and it worked as expected. One other thing to take care about is that every derived table (AKA sub-query) must indeed have an alias. Dervied Table alias
Here is the query which worked for me :
SELECT originalAmount,fees,id FROM
(SELECT originalAmount,fees,id, ROW_NUMBER() OVER (PARTITION BY transaction_number ORDER BY eventdate ASC) `RANK` FROM kir_records where customerid= 1704) AS SomeAlias
WHERE `RANK` = 1;
I have a table in Oracle SQL whose ids are in increasing, sequential order, but there are gaps in the ids due to editing, e.g. the ids are currently something like
22
23
24
32
33
44
...etc
I check one post and the solution provided was as below:
update (select t.*, row_number() over (order by id) as newid) toupdate
set id = newid
Solution Provided earlier.
Now my query:
1) I guess the "From clause" is missing in the above query.
Updated query:
update (select t.*,
row_number() over (order by emp_id) as newid
from employee t ) toupdate
set emp_id = newid;
2) When i run the above query, it gives me error "data Manipulation operation not legal on this view".
Can anyone explain how the mentioned solutions worked here. can anyone post the full update query. Thanks.
This solution to the same question you referenced shows how to do it:
update employee set emp_id = (
with tab as (
select emp_id, rownum r
from (select emp_id from employee order by emp_id)
)
select r from tab where employee.emp_id = tab.emp_id
);
That works. You cannot update a view that contains an analytic function like row_number - see Oracle 12C docs, look for "Notes on Updatable Views".
You could use a merge, but you'd need to join on something other than emp_id as you want to update that column. If there are no other unique columns you can use the rowid:
merge into employee target
using (select rowid, row_number() over (order by emp_id) as emp_id from employee) source
on (source.rowid = target.rowid)
when matched then update set target.emp_id = source.emp_id;
I think this would be easiest approach :
update mytable set id = ROWNUM;
Oracle SQL - update ids in oracle sql to be in sequential order
Hello I need a formula in column āCā which calculates/adds the amount of B Column based on the column A ID. If there are several amounts in same ID it should add the total amount and would show the result in column āCā as a single row.
the output can be obtained from Oracle SQL query or an Excel formula.your help would be appreciated.
You can get the same output from Oracle itself, using analytical functions like below.
SUM() OVER(PARTITION BY ... ) -> This actually do the cumulative sum
WITH MYTABLE(ID,AMT) AS
(SELECT '2UF2', '500' FROM DUAL
UNION ALL
SELECT '2TC6', '300' FROM DUAL
UNION ALL
SELECT '2TC6', '200' FROM DUAL
UNION ALL
SELECT '2TC6', '800' FROM DUAL
)
SELECT ID,
AMT,
CASE ROW_NUMBER() OVER(PARTITION BY ID ORDER BY NULL)
WHEN 1
THEN SUM(AMT) OVER(PARTITION BY ID ORDER BY NULL)
END AS FORMULA
FROM MYTABLE
ORDER BY ID, FORMULA NULLS LAST;
SQL Fiddle Demo
You can use rollup in oracle
Select id,amt,sum (amt) nullFrom table nullGroup by rollup (id,amt)
For more details see below link
https://oracle-base.com/articles/misc/rollup-cube-grouping-functions-and-grouping-sets
In SQL you need an aggregation function, in this case sum, and a group by clause. The generic query should look like the following:
Select sum(b) from table group by a
I hope this helps.
Problem: I need write stored procedure(s) that will return result set of a single page of rows and the number of total rows.
Solution A: I create two stored procedures, one that returns a results set of a single page and another that returns a scalar -- total rows. The Explain Plan says the first sproc has a cost of 9 and the second has a cost of 3.
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) AS RowNum, ...
) AS PageResult
WHERE RowNum >= #from
AND RowNum < #to
ORDER BY RowNum
SELECT COUNT(*)
FROM ...
Solution B: I put everything in a single sproc, by adding the same TotalRows number to every row in the result set. This solution feel hackish, but has a cost of 9 and only one sproc, so I'm inclined to use this solution.
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) RowNum, COUNT(*) OVER () TotalRows,
WHERE RowNum >= from
AND RowNum < to
ORDER BY RowNum;
Is there a best-practice for pagination in Oracle? Which of the aforementioned solutions is most used in practice? Is any of them considered just plain wrong? Note that my DB is and will stay relatively small (less than 10GB).
I'm using Oracle 11g and the latest ODP.NET with VS2010 SP1 and Entity Framework 4.4. I need the final solution to work within the EF 4.4. I'm sure there are probably better methods out there for pagination in general, but I need them working with EF.
If you're already using analytics (ROW_NUMBER() OVER ...) then adding another analytic function on the same partitioning will add a negligible cost to the query.
On the other hand, there are many other ways to do pagination, one of them using rownum:
SELECT *
FROM (SELECT A.*, rownum rn
FROM (SELECT *
FROM your_table
ORDER BY col) A
WHERE rownum <= :Y)
WHERE rn >= :X
This method will be superior if you have an appropriate index on the ordering column. In this case, it might be more efficient to use two queries (one for the total number of rows, one for the result).
Both methods are appropriate but in general if you want both the number of rows and a pagination set then using analytics is more efficient because you only query the rows once.
In Oracle 12C you can use limit LIMIT and OFFSET for the pagination.
Example -
Suppose you have Table tab from which data needs to be fetched on the basis of DATE datatype column dt in descending order using pagination.
page_size:=5
select * from tab
order by dt desc
OFFSET nvl(page_no-1,1)*page_size ROWS FETCH NEXT page_size ROWS ONLY;
Explanation:
page_no=1
page_size=5
OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY - Fetch 1st 5 rows only
page_no=2
page_size=5
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY - Fetch next 5 rows
and so on.
Refrence Pages -
https://dba-presents.com/index.php/databases/oracle/31-new-pagination-method-in-oracle-12c-offset-fetch
https://oracle-base.com/articles/12c/row-limiting-clause-for-top-n-queries-12cr1#paging
This may help:
SELECT * FROM
( SELECT deptno, ename, sal, ROW_NUMBER() OVER (ORDER BY ename) Row_Num FROM emp)
WHERE Row_Num BETWEEN 5 and 10;
A clean way to organize your SQL code could be trough WITH statement.
The reduced version implements also total number of results and total pages count.
For example
WITH SELECTION AS (
SELECT FIELDA, FIELDB, FIELDC FROM TABLE),
NUMBERED AS (
SELECT
ROW_NUMBER() OVER (ORDER BY FIELDA) RN,
SELECTION.*
FROM SELECTION)
SELECT
(SELECT COUNT(*) FROM NUMBERED) TOTAL_ROWS,
NUMBERED.*
FROM NUMBERED
WHERE
RN BETWEEN ((:page_size*:page_number)-:page_size+1) AND (:page_size*:page_number)
This code gives you a paged resultset with two more fields:
TOTAL_ROWS with the total rows of your full SELECTION
RN the row number of the record
It requires 2 parameter: :page_size and :page_number to slice your SELECTION
Reduced Version
Selection implements already ROW_NUMBER() field
WITH SELECTION AS (
SELECT
ROW_NUMBER() OVER (ORDER BY FIELDA) RN,
FIELDA,
FIELDB,
FIELDC
FROM TABLE)
SELECT
:page_number PAGE_NUMBER,
CEIL((SELECT COUNT(*) FROM SELECTION ) / :page_size) TOTAL_PAGES,
:page_size PAGE_SIZE,
(SELECT COUNT(*) FROM SELECTION ) TOTAL_ROWS,
SELECTION.*
FROM SELECTION
WHERE
RN BETWEEN ((:page_size*:page_number)-:page_size+1) AND (:page_size*:page_number)
Try this:
select * from ( select * from "table" order by "column" desc ) where ROWNUM > 0 and ROWNUM <= 5;
I also faced a similar issue. I tried all the above solutions and none gave me a better performance. I have a table with millions of records and I need to display them on screen in pages of 20. I have done the below to solve the issue.
Add a new column ROW_NUMBER in the table.
Make the column as primary key or add a unique index on it.
Use the population program (in my case, Informatica), to populate the column with rownum.
Fetch Records from the table using between statement. (SELECT * FROM TABLE WHERE ROW_NUMBER BETWEEN LOWER_RANGE AND UPPER_RANGE).
This method is effective if we need to do an unconditional pagination fetch on a huge table.
Sorry, this one works with sorting:
SELECT * FROM (SELECT ROWNUM rnum,a.* FROM (SELECT * FROM "tabla" order by "column" asc) a) WHERE rnum BETWEEN "firstrange" AND "lastrange";