I am having some problem creating update query based on select query with ROWNUM as WHERE condition.
I did experiments with these queries:
SELECT *
FROM
(SELECT ROWNUM, RVT.* FROM RVT)
WHERE RVT_ID IS NOT NULL;
This works, but
SELECT *
FROM
(SELECT ROWNUM, RVT.* FROM RVT) AS TEMP_TABLE1
WHERE TEMP_TABLE1.RVT_ID IS NOT NULL;
doesn't work.
What I want to achieve is this:
UPDATE REVIEW_T
SET RVT_RATING = 1
FROM (SELECT ROWNUM, RVT.* FROM RVT )
WHERE ROWNUM = 1;
Which does not work. Also,
UPDATE REVIEW_T
SET RVT_RATING = 1
FROM (SELECT ROWNUM, RVT.* FROM RVT) AS TEMP_TABLE
WHERE TEMP_TABLE.ROWNUM = 1;
doesn't work either.
What am I doing wrong?
I want to create 'index' 1,2,3,....600 for the all rows of one of my existing table
If that's so, then
UPDATE REVIEW_T SET RVT_RATING = rownum;
Related
I need to write a function to check the first and last date validity of the employee.
ncount NUMBER;
SELECT
*
FROM employee emp
WHERE emp.name = e.name
and emp.dept_name = e.dept_name
and emp.designation = e.designation
and emp.name = ‘Claire’ and
emp.designation = ‘MGR’ ;
select count(*) into nCount from employee;
Please let me know how can i get correct result for the previous record when no last date given.
The query provided seems overly complicated.Self join isn't required as we are validating existence of a record based on values from variables for certain condition.
The query below should suffice:
WITH employee_records as
(SELECT *
FROM employee emp
WHERE emp.name = 'Claire'
and emp.dept_name = 'SALES'
and emp.designation = 'MGR'
and ( First_Date between emp.first_date and NVL(emp.end_date, TO_DATE('12/31/9999','MM/DD/YYYY')) OR
End_Date between emp.first_date and NVL(emp.end_date, TO_DATE('12/31/9999','MM/DD/YYYY')) OR
End_Date is null)
select count(*) into nCount from employee_records;
If we want to fetch information based on condition on single column, we do like this
SELECT * FROM contact WHERE firstName = 'james'
IF we want to put conditions on multiple columns, we do this
SELECT * FROM contact WHERE firstName = 'james' OR lastName = 'james' OR businessName = 'james'
But What if we have more than 50 columns.
Is there better way other than WHERE Condition with OR Keyword?
The approach should not involve writing all column names.
There is a way to do this in MySql as shown here.
If you're wanting to search all VARCHAR2 columns, then the following script ought to help:
set pages 0;
set lines 200
select case when rn = 1 and rn_desc = 1 then 'select * from '||table_name||' where '||column_name||' = ''james'';'
when rn = 1 then 'select * from '||table_name||' where '||column_name||' = ''james'''
when rn_desc = 1 then ' and '||column_name||' = ''james'';'
else ' and '||column_name||' = ''james'''
end sql_stmt
from (select table_name,
column_name,
column_id,
row_number() over (partition by table_name order by column_id) rn,
row_number() over (partition by table_name order by column_id desc) rn_desc
from user_tab_columns
where data_type in ('VARCHAR2')
-- and table_name in (<list of tables>) -- uncomment and amend as appropriate!
)
order by table_name, column_id;
If you only want to search specific tables, you would have to put a filter in for the table_names you're after.
Running the above as a script will give you a script containing multiple queries that you can then run
There is no way you can avoid writing all the column names,
But you can use an IN condition to make writing this a bit shorter:
SELECT *
FROM contact
WHERE 'james' in (firstName, lastName, businessName)
I am trying to modify a query that someone else wrote which is taking a really long time to run. The problem has to do with the <> portion of the exists query. Any idea how this can be changed to run quicker?
SELECT m.level4 center, cc.description, m.employeename, m.empno,
TO_DATE (ct.tsdate, 'dd-mon-yyyy') tsdate, ct.starttime, ct.endtime,
ct.DURATION,
NVL (DECODE (ct.paycode, ' ', 'REG', ct.paycode), 'REG') paycode,
ct.titlecode, ct.costcenter, m.tsgroup
FROM clairvia_text ct, MASTER m, costcenteroutbound cc
WHERE ct.recordtype = '1'
AND ct.empno = m.empno
AND m.level4 = cc.center
AND EXISTS (
SELECT ct1.recordtype,ct1.empno,ct1.tsdate,ct1.processdate
FROM clairvia_text ct1
WHERE ct.recordtype = ct1.recordtype
AND ct.empno = ct1.empno
AND ct.tsdate = ct1.tsdate
AND ct.processdate = ct1.processdate
group by ct1.recordtype,ct1.empno,ct1.tsdate,ct1.processdate
having count(*) < 2)
Oracle can be finnicky with exists statements and subqueries. A couple of things to try:
Change the exists to an "in"
Change the exists to a group by statement with a "having count(1) > 1". This could even be changed into a join.
I'm assuming indexes are not an issue.
You can use analytic function count here to eliminate duplicated rows.
select * from (
SELECT m.level4 center, cc.description, m.employeename, m.empno,
TO_DATE (ct.tsdate, 'dd-mon-yyyy') tsdate, ct.starttime, ct.endtime,
ct.DURATION,
NVL (DECODE (ct.paycode, ' ', 'REG', ct.paycode), 'REG') paycode,
ct.titlecode, ct.costcenter, m.tsgroup,
count(1) over (partition by ct.recordtype,ct.empno,ct.tsdate,ct.processdate
order by null) cnt
FROM clairvia_text ct, MASTER m, costcenteroutbound cc
WHERE ct.recordtype = '1'
AND ct.empno = m.empno
AND m.level4 = cc.center
) where cnt=1
I do not have your structures and data, so I run similar queries with all_tab_cols and first query took ~500s on my laptop and second query ~2s.
-- slow test
select count(1)
from all_tab_cols atc
where exists (
select 1
from all_tab_cols atc1
where atc1.column_name = atc.column_name
group by column_name
having count(1) = 1)
-- fast test
select count(1)
from (
select column_name,
count(1) over (partition by atc.column_name order by null) cnt
from all_tab_cols atc
)
where cnt = 1
I was wondering if the following code is a good practice
CURSOR c_price_hist_parent IS
select tran_type, reason, event,
unit_cost, unit_retail, selling_unit_retail,
selling_uom, multi_units, multi_unit_retail,
multi_selling_uom
from price_hist
where rowid = ( SELECT row_id
from ( SELECT rowid row_id
FROM price_hist
WHERE item = l_item_parent
and tran_type in (4,8)
and loc = l_location
and ACTION_DATE <= l_create_date
order by action_date desc
)
where rownum = 1
);
If we delete a row and then insert the same row all the columns remain same but the rowid doesn't, so in this case it will not match. Please let me know your thoughts.
As mentioned before, using rownum can be tricky, because inserts or deletes can happen at the same time which could change rownums.
If I understand your query correctly, you are simply trying to get the record with the latest action_date. Why not do the following:
CURSOR c_price_hist_parent IS
select sub.tran_type, sub.reason, sub.event,
sub.unit_cost, sub.unit_retail, sub.selling_unit_retail,
sub.selling_uom, sub.multi_units, sub.multi_unit_retail,
sub.multi_selling_uom
from (
select *
from price_hist
where item = l_item_parent
and tran_type in (4,8)
and loc = l_location
and ACTION_DATE <= l_create_date
order by action_date desc
) sub
where rownum = 1
);
I have seen this Oracle SQL query for using rownum with the combination of between keyword .
select *
from
( select rownum rnum, a.*
from (your_query) a
where rownum <= :M )
where rnum >= :N;
in order to get rows n through m from 'your query.'
I want to try it , Could anybody please tell me how can i get the data from an Emp table to fetch records from 4 to 8 Records
select *
from
( select rownum rnum, a.*
from (select * from emp) a
where rownum <= 4 )
where rnum >= 8;
But this isn't working , could anybody please tell me why .
Thank you very much .
This is because you are limiting your query to <=4 rows, so when you filter to show records >=8 there are only 4 records to look at....
Invert the numbers and you should see a result:
select *
from
( select rownum rnum, a.*
from (select * from emp) a
where rownum <= 8 )
where rnum >= 4;
If I had to guess, I'd say that the reason you're not seeing what you expect (in addition to having the operators backwards, as pointed out by #diagonalbatman) is that you didn't tell the database what order you wanted the rows in. You're essentially telling the database to return any 5 rows. You can't even be sure that this query will always return the same five rows. Any time you're getting a subset like this, you should use an order by clause in the innermost query, so that the sort is applied before the rownum values are issued:
SELECT *
FROM (SELECT ROWNUM rnum, a.*
FROM (SELECT *
FROM emp
ORDER BY emp_id) a
WHERE ROWNUM <= 8)
WHERE rnum >= 4;
When you are querying the whole data in the inner statement (if you have huge data amounds, no good idea!) you could as well use the BETWEEN keyword.
SELECT *
FROM
(SELECT rownum AS rnum,
a.*
FROM EMP) a
WHERE rnum BETWEEN 4 AND 8;