I am trying to get the rowid from a query. My query is :
Table: test ( PersonId number, AssetId number);
Query:
with abc as(
select
personid ,
row_number() over(partition by personid order by personid,carid) rnk
from test
--group by personid,carid,rowid
)
select rowid, abc.* from abc ;
and its throwing error.
ORA-01446: cannot select ROWID from,or sample,a view with DISTINCT,GROUP BY etc
Is there any way i can get the rowid (this way) or its not allowed to get rowid using the way am trying to get in Oracle. Can anyone throw some views here. Thanks.
Try including rowid inside the with subquery ( I used an alias)
with abc as(
select
personid ,
rowid as r,
row_number() over(partition by personid order by personid,carid) rnk
from test
/***This was unwanted in question***/
--group by personid,carid,rowid
)
select r, personid, rnk
from abc ;
Using GROUP BY with ROWID will not aggregate rows as ROWID is unique so the size of each group will always be 1.
You can just do:
SELECT personid,
ROW_NUMBER() OVER ( PARTITION BY personid ORDER BY carid ) AS rnk,
ROWID
FROM test;
Related
I have the following select statments in Oracle 19:
select count(*) as facility_load_stg_cnt from facility_load_stg;
select count(*) as facility_cnt from facility;
select count(*) as loctn_typ_cnt from loctn_typ;
select count(*) as join_cnt from (
select f.facility_id, lt.loctn_typ_id
from facility_load_stg stg
inner join facility f on stg.facility_cd = f.facility_cd
inner join loctn_typ lt on stg.bldg = lt.loctn_typ_nm);
the object is simple, get the PK's for facility and loctn_typ (facility_id, loctn_typ_id) to insert into the table that will build the relationship.
The problem is when I run the above code, I get these results:
FACILITY_LOAD_STG_CNT
---------------------
987
FACILITY_CNT
------------
645
LOCTN_TYP_CNT
-------------
188
JOIN_CNT
----------
2905
why is the select with the join have 3x the rows of the facility_load_stg table? I am sure I am doing something silly, I just cannot see it.
Folks have asked to see the table definitions, here is the relavent parts:
create table FACILITY_MAINT_DATA.FACILITY_LOAD_STG
(
FACILITY_CD VARCHAR2(100) not null,
BLDG VARCHAR2(100)
)
create table FACILITY_MAINT_DATA.FACILITY
(
FACILITY_CD VARCHAR2(100),
FACILITY_ID NUMBER(14) not null
constraint PK_FACILITY
primary key
)
create table FACILITY_MAINT_DATA.LOCTN_TYP
(
LOCTN_TYP_ID NUMBER(14) default "FACILITY_MAINT_DATA"."LOCTN_TYP_ID_SEQ"."NEXTVAL" not null
constraint PK_LOCTN_TYP
primary key,
LOCTN_TYP_NM VARCHAR2(100),
)
The generall rule if you join and you encounter a higher count that you expect is that the join keys are not unique*
Here a simple example reproducting the same result as you have (limiting only to two tables).
create table tab1 as
select rownum id,
case when rownum <= 80 then 'CD_'||rownum else 'CD_X' end cd from dual connect by level <= 645;
create table tab2 as
select rownum id,
case when rownum <= 80 then 'CD_'||rownum
when rownum <= 85 then 'CD_X'
else 'CD_Y' end cd from dual connect by level <= 987;
select count(*) from tab1;
COUNT(*)
----------
645
select count(*) from tab2;
COUNT(*)
----------
987
select count(*)
from tab1
join tab2
on tab1.cd = tab2.cd;
COUNT(*)
----------
2905
Summary change the join to use the unique keys or limit the join only to such CDcolumns that are unique.
Thank you everyone for the comments, that got me looking at detail at the actual data and there are duplications. Now I just have to figure out why, just need some investigation:)
I have a function, which will get greatest of three dates from the table.
create or replace FUNCTION fn_max_date_val(
pi_user_id IN number)
RETURN DATE
IS
l_modified_dt DATE;
l_mod1_dt DATE;
l_mod2_dt DATE;
ret_user_id DATE;
BEGIN
SELECT MAX(last_modified_dt)
INTO l_modified_dt
FROM table1
WHERE id = pi_user_id;
-- this table contains a million records
SELECT nvl(MAX(last_modified_ts),sysdate-90)
INTO l_mod1_dt
FROM table2
WHERE table2_id=pi_user_id;
-- this table contains clob data, 800 000 records, the table 3 does not have user_id and has to fetched from table 2, as shown below
SELECT nvl(MAX(last_modified_dt),sysdate-90)
INTO l_mod2_dt
FROM table3
WHERE table2_id IN
(SELECT id FROM table2 WHERE table2_id=pi_user_id
);
execute immediate 'select greatest('''||l_modified_dt||''','''||l_mod1_dt||''','''||l_mod2_dt||''') from dual' into ret_user_id;
RETURN ret_user_id;
EXCEPTION
WHEN OTHERS THEN
return SYSDATE;
END;
this function works perfectly fine and executes within a second.
-- random user_id , just to test the functionality
SELECT fn_max_date_val(100) as max_date FROM DUAL
MAX_DATE
--------
27-02-14
For reference purpose i have used the table name as table1,table2 and table3 but my business case is similar to what i stated below.
I need to get the details of the table1 along with the highest modified date among the three tables.
I did something like this.
SELECT a.id,a.name,a.value,fn_max_date_val(id) as max_date
FROM table1 a where status_id ='Active';
The above query execute perfectly fine and got result in millisecods. But the problem came when i tried to use order by.
SELECT a.id,a.name,a.value,a.status_id,last_modified_dt,fn_max_date_val(id) as max_date
FROM table1 where status_id ='Active' a
order by status_id desc,last_modified_dt desc ;
-- It took almost 300 seconds to complete
I tried using index also all the values of the status_id and last_modified, but no luck. Can this be done in a right way?
How about if your query is like this?
select a.*, fn_max_date_val(id) as max_date
from
(SELECT a.id,a.name,a.value,a.status_id,last_modified_dt
FROM table1 where status_id ='Active' a
order by status_id desc,last_modified_dt desc) a;
What if you don't use the function and do something like this:
SELECT a.id,a.name,a.value,a.status_id,last_modified_dt x.max_date
FROM table1 a
(
select max(max_date) as max_date
from (
SELECT MAX(last_modified_dt) as max_date
FROM table1 t1
WHERE t1.id = a.id
union
SELECT nvl(MAX(last_modified_ts),sysdate-90) as max_date
FROM table2 t2
WHERE t2.table2_id=a.id
...
) y
) x
where a.status_id ='Active'
order by status_id desc,last_modified_dt desc;
Syntax might contain errors, but something like that + the third table in the derived table too.
I have to find record from the hive table where Id, der__timestamp, header__change_seq should be unique but in table (Id, der__timestamp, header__change_seq) can duplicate so in this case i have to fetch only one record if records are getting duplicate .
select b.*
from (SELECT ID, max(COALESCE(header__timestamp))
max_modified,MAX(CAST(header__change_seq AS DECIMAL(38,0))) max_sequence
FROM table_name group by ID) a
join table_name b on (a.id=b.id and
a.max_modified=b.header__timestamp and
a.max_sequence=b.header__change_seq)
So the total number of distinct id is count-->244441250
but through above query i am getting count-->244442548
due to some duplicate records but i have to find only distinct id where (header__change_seq and header__timestamp) should max .
#Rahul; please try this one. It makes use of row_number() so in case of duplicate id, header_timestamp and hearder_change_seq, it will select only one record. Hope it helps.
select *
from (
select *,
row_number() over ( partition by id order by header__timestamp desc, header__change_seq desc) as rnk
from table_name) t
where t.rnk = 1;
Same query running in Db2 , but in oracle it's giving error.
Please help. thanks in advance.
delete from (SELECT
EMP_ID,
SAL,
ROW_NUMBER() OVER (PARTITION BY EMP_ID ORDER BY SAL DESC) As RN
FROM FPM.FACT_PL_BS
WHERE MEASUREMENT_PERIOD_ID=20170811
AND SCENARIO_ID=1) A where RN>1}
Check documentation Notes on Updatable Views:
The view must not contain any of the following constructs:
A set operator
A DISTINCT operator
An aggregate or analytic function
A GROUP BY, ORDER BY, MODEL, CONNECT BY, or START WITH clause
A collection expression in a SELECT list
A subquery in a SELECT list
A subquery designated WITH READ ONLY
Joins, with some exceptions, as documented in Oracle Database Administrator's Guide
ROW_NUMBER is an Analytic Function, so update is not permitted.
I think this one should work (not tested):
delete from FPM.FACT_PL_BS
WHERE ROWID =ANY
(SELECT ROW_ID
FROM
(SELECT ROWID as ROW_ID,
EMP_ID,
SAL,
ROW_NUMBER() OVER (PARTITION BY EMP_ID ORDER BY SAL DESC) As RN
FROM FPM.FACT_PL_BS
WHERE MEASUREMENT_PERIOD_ID=20170811
AND SCENARIO_ID=1)
WHERE RN > 1;
or maybe
delete from FPM.FACT_PL_BS
WHERE MEASUREMENT_PERIOD_ID=20170811
AND SCENARIO_ID=1
AND ROWID <>ALL
(select MAX(ROWID) KEEP (DENSE_RANK FIRST ORDER BY SAL) OVER (PARTITION BY EMP_ID)
FROM FPM.FACT_PL_BS)
I have a table x_visa. I want to delete the duplicate columns from this table.
The query I am using for this is :
select * from (SELECT x_visa.*,
ROW_NUMBER() over (partition by effective_start_date, effective_end_date, person_id,
business_group_id, legislation_code , current_visa_permit, visa_permit_type, visa_permit_id, configuration_id
order by person_id) AS rn
from x_visa) T
WHERE rn > 1 );
The delete statement is giving an error :ORA-01752: cannot delete from view without exactly one key-preserved table
delete from
(select * from (SELECT x_visa.*,
ROW_NUMBER() over (partition by effective_start_date, effective_end_date, person_id,
business_group_id, legislation_code , current_visa_permit, visa_permit_type, visa_permit_id, configuration_id
order by person_id) AS rn
from x_visa) T
WHERE rn = 1 );
Is there a workaround to delete the duplicate data from this table ?
Each row has rowid identifier. So you can delete where rowid in results of your query.
delete from x_visa where rowid in (/*YOUR QUERY*/);
So we have:
delete from x_visa where rowid in (select r from (SELECT x_visa.rowid r, x_visa.*,
ROW_NUMBER() over (partition by effective_start_date, effective_end_date, person_id,
business_group_id, legislation_code , current_visa_permit, visa_permit_type, visa_permit_id, configuration_id
order by person_id) AS rn
from x_visa) T
WHERE rn > 1 ))