Oracle update sql query - sql

My query is this. It is not showing error. But having a long execution time that Iam forced to close. Please check
update trans_rec a
set a.qty = (select b.qtydes from itbg_store_delchellan b where b.icode =
a.icode and a.controlno=b.DEL_NO AND A.controlno IS NOT NULL)
where exists
(select b.qtydes from itbg_store_delchellan b where b.icode = a.icode and
a.controlno=b.DEL_NO AND A.controlno IS NOT NULL )

You can re-write your query as follow:
UPDATE trans_rec a
SET a.qty =
(SELECT b.qtydes
FROM itbg_store_delchellan b
WHERE b.icode = a.icode and a.controlno=b.DEL_NO)
WHERE a.controlno IS NOT NULL
AND EXISTS
(SELECT b.qtydes FROM itbg_store_delchellan b
WHERE b.icode = a.icode AND a.controlno=b.DEL_NO)
After this you must add indexes on your field search, as follow:
add following filter on these fields
b.icode
a.controlno
a.icode

You may use a MERGE statement in Oracle.
MERGE INTO trans_rec t USING
( select DISTINCT icode,del_no,qtydes
FROM itbg_store_delchellan s
)
ON (
s.icode = t.icode AND t.controlno = s.del_no
)
WHEN MATCHED THEN UPDATE SET t.qty = s.qtydes
WHERE t.controlno IS NOT NULL

Try this update:
UPDATE A
SET qty = B.qtydes
from trans_rec AS A
INNER JOIN itbg_store_delchellan B
ON B.icode = A.icode
AND A.controlno=b.DEL_NO
AND A.controlno IS NOT NULL

To improve performance, create a composite index on itbg_store_delchellan:
create index idx_itbg_store_delchellan_3 on itbg_store_delchellan(icode, del_no, qtydes)
Note that the condition A.controlno IS NOT NULL is redundant. The correlation condition will already filter out NULL values, so you can remove this from both subqueries.

Related

Change Select statement to an update statement

SELECT A.GRPNO, A.EMPNO, A.DEPNO, A.PENDCD FROM EMPDEP A, EEDPELIG B
WHERE A.GRPNO=B.GRPNO
AND A.EMPNO=B.EMPNO
AND A.DEPNO=B.DEPNO
AND A.GRPNO = 6606 AND A.SPOUSE = 'T'
AND B.ELIGFLAG01 = 'T' AND SNAPTHRUDT ='DEC312999'
Our selection statement has been successful at pulling the information we need however we're new with SQL and are struggling to create an update statement that is replacing the "a.pendcd=0" to "a.pendcd=20" from the information in the select statement. Any help is appreciated, thank you.
update a
a.pendcd=20
FROM EMPDEP A inner join EEDPELIG B
on A.GRPNO=B.GRPNO
AND A.EMPNO=B.EMPNO
AND A.DEPNO=B.DEPNO
AND A.GRPNO = 6606 AND A.SPOUSE = 'T'
AND B.ELIGFLAG01 = 'T' AND SNAPTHRUDT ='DEC312999'
where a.pendcd=0
Oracle does not support FROM or JOIN in UPDATE (under most circumstances).
Just use EXISTS:
UPDATE EMPDEP ed
SET . . .
WHERE EXISTS (SELECT 1
FROM EEDPELIG p
WHERE ed.GRPNO = p.GRPNO AND
ed.EMPNO= p.EMPNO AND
ed.DEPNO= p.DEPNO AND
p.ELIGFLAG01 = 'T'
)
ed.GRPNO = 6606 AND
ed.SPOUSE = 'T' AND
ed.SNAPTHRUDT ='DEC312999';
It is unclear if the condition on SNAPTHRUDT is on the outer table or inner table. If it is on p, then move it to the subquery.
You can use MERGE statement as following:
Lets assume EMPDEP table has primary key which is EMPDEP_UID.
MERGE INTO EMPDEP TRG
USING
(SELECT A.EMPDEP_UID, A.PENDCD
FROM EMPDEP A, EEDPELIG B
WHERE A.GRPNO=B.GRPNO
AND A.EMPNO=B.EMPNO
AND A.DEPNO=B.DEPNO
AND A.GRPNO = 6606
AND A.SPOUSE = 'T'
AND B.ELIGFLAG01 = 'T'
AND SNAPTHRUDT ='DEC312999') SRC
ON (TRG.EMPDEP_UID = SRC.EMPDEP_UID)
WHEN MATCHED THEN
UPDATE SET TRG.PENDCD = 0
WHERE TRG.PENCD = 20;
You can use unique keys instead of primary key to identify the records to be updated. But it is safe to use primary key as unique key can contain nulls which can change the behaviour of our query.
Cheers!!

SQL Update a Column From a Select

I want to update 1 column (loadStatus) in the Loads table based on if another column (IBLoad) from a joined table is NULL. The end result when running my statement has 0 rows affected. I'm not sure what's wrong here but maybe my WHERE clause is incorrect?
This is the first time I've tried to update from a select so trying to figure it out :)
UPDATE Loads SET loadStatus = 'SCHEDULED'
FROM (
Select L.OID as [LoadID], T.IBLoad, L.loadStatus
From [Loads] L left join [Transaction] T on L.OID = T.IBLoad
Where T.IBLoad is null and load_type = 1 ) i
WHERE Loads.loadStatus = null
you do not need subquery, And use is null instead of = null
UPDATE L
SET loadStatus = 'SCHEDULED'
From [Loads] L left join [Transaction] T on L.OID = T.IBLoad
Where T.IBLoad is null and load_type = 1
and L.loadStatus is null
or use Loads.loadStatus = '' for empty string
You don't need to update from a select in this case. Here is another way to write the query:
UPDATE l
SET loadStatus = 'SCHEDULED'
FROM Loads l
WHERE l.loadStatus IS NULL AND
l.load_type = 1 AND
NOT EXISTS (SELECT 1 FROM [Transaction] t WHERE l.OID = t.IBLoad);

Slowness in update query using inner join

I am using the below query to update one column based on the conditions it is specified. I am using "inner join" but it is taking more than 15 seconds to run the query even if it has to update no records(0 records).
UPDATE CONFIGURATION_LIST
SET DUPLICATE_SERIAL_NUM = 0
FROM CONFIGURATION_LIST
INNER JOIN (SELECT DISTINCT APPLIED_MAT_CODE, APPLIED_SERIAL_NUMBER, COUNT(*) AS NB
FROM CONFIGURATION_LIST
WHERE
PLANT = '0067'
AND APPLIED_SERIAL_NUMBER IS NOT NULL
AND APPLIED_SERIAL_NUMBER !=''
AND DUPLICATE_SERIAL_NUM = 1
GROUP BY
APPLIED_MAT_CODE, APPLIED_SERIAL_NUMBER
HAVING
COUNT(*) = 1) T2 ON T2.APPLIED_SERIAL_NUMBER = CONFIGURATION_LIST.APPLIED_SERIAL_NUMBER
AND T2.APPLIED_MAT_CODE = CONFIGURATION_LIST.APPLIED_MAT_CODE
WHERE
CONFIGURATION_LIST.PLANT = '0067'
AND DUPLICATE_SERIAL_NUM = 1
The index is there with APPLIED_SERIAL_NUMBER and APPLIED_MAT_CODE and fragmentation is also fine.
Could you please help me on the above query performance.
First, you don't need the DISTINCT when using GROUP BY. SQL Server probably ignores it, but it is a bad idea anyway:
UPDATE CONFIGURATION_LIST
SET DUPLICATE_SERIAL_NUM = 0
FROM CONFIGURATION_LIST INNER JOIN
(SELECT APPLIED_MAT_CODE, APPLIED_SERIAL_NUMBER, COUNT(*) AS NB
FROM CONFIGURATION_LIST cl
WHERE cl.PLANT = '0067' AND
cl.APPLIED_SERIAL_NUMBER IS NOT NULL AND
cl.APPLIED_SERIAL_NUMBER <> ''
cl.DUPLICATE_SERIAL_NUM = 1
GROUP BY cl.APPLIED_MAT_CODE, cl.APPLIED_SERIAL_NUMBER
HAVING COUNT(*) = 1
) T2
ON T2.APPLIED_SERIAL_NUMBER = CONFIGURATION_LIST.APPLIED_SERIAL_NUMBER AND
T2.APPLIED_MAT_CODE = CONFIGURATION_LIST.APPLIED_MAT_CODE
WHERE CONFIGURATION_LIST.PLANT = '0067' AND
DUPLICATE_SERIAL_NUM = 1;
For this query, you want the following index: CONFIGURATION_LIST(PLANT, DUPLICATE_SERIAL_NUM, APPLIED_SERIAL_NUMBER, APPLIED_MAT_CODE, APPLIED_SERIAL_NUMBER).
The HAVING COUNT(*) = 1 suggests that you might really want NOT EXISTS (which would normally be faster). But you don't really explain what the query is supposed to be doing, you only say that this code is slow.
Looks like you're checking the table for rows that exist in the same table with the same values, and if not, update the duplicate column to zero. If your table has a unique key (identity field or composite key), you could do something like this:
UPDATE C
SET C.DUPLICATE_SERIAL_NUM = 0
FROM
CONFIGURATION_LIST C
where
not exists (
select
1
FROM
CONFIGURATION_LIST C2
where
C2.APPLIED_SERIAL_NUMBER = C.APPLIED_SERIAL_NUMBER and
C2.APPLIED_MAT_CODE = C.APPLIED_MAT_CODE and
C2.UNIQUE_KEY_HERE != C.UNIQUE_KEY_HERE
) and
C.PLANT = '0067' and
C.DUPLICATE_SERIAL_NUM = 1
I will try with a select first:
select APPLIED_MAT_CODE, APPLIED_SERIAL_NUMBER, count(*) as n
from CONFIGURATION_LIST cl
where
cl.PLANT='0067' and
cl.APPLIED_SERIAL_NUMBER IS NOT NULL and
cl.APPLIED_SERIAL_NUMBER <> ''
group by APPLIED_MAT_CODE, APPLIED_SERIAL_NUMBER;
How many rows do you get with this and how long does it take?
If you remove your DUPLICATE_SERIAL_NUM column from your table it might be very simple. The DUPLICATE_SERIAL_NUM suggests that you are searching for duplicates. As you count your rows you could introduce a simple table that contains the counts:
create table CLCOUNT ( N int unsigned, C int /* or what APPLIED_MAT_CODE is */, S int /* or what APPLIED_SERIAL_NUMBER is */, PLANT char(20) /* or what PLANT is */, index unique (C,S,PLANT), index(PLANT,N));
insert into CLCOUNT select count(*), cl.APPLIED_MAT_CODE, cl.APPLIED_SERIAL_NUMBER, cl.PLANT
from CONFIGURATION_LIST cl
where
cl.PLANT='0067' and
cl.APPLIED_SERIAL_NUMBER IS NOT NULL and
cl.APPLIED_SERIAL_NUMBER <> ''
group by APPLIED_MAT_CODE, APPLIED_SERIAL_NUMBER;
How long does this take?
Now you can simply select * from CLCOUNT where PLANT='0067' and N=1;
This is all far from being perfect. But you should be able to analyze (EXPLAIN SELECT ...) your queries and find why it takes so long.

need to replace subquery with JOIN

I need to use join in below instead of Subquery.
can anybody help me to rewrite this with JOIN.
update Table1
set status = 'Edited'
where val_74 ='1' and status ='Valid'
and val_35 is not null
and (val_35,network_id) in
(select val_35,network_id from
Table2 where val_35 is not null
and status='Correct_1');
update Table1 b SET (Val_12,Val_13,Val_14)=
(select Val_12,Val_13,Val_14 from
(select Val_35,network_id, Val_12, Val_13, Val_14
from Table2
where Val_34 is not null
and (REGEXP_LIKE(Val_13,'^[0-9]+$'))
and (Val_14 is null or (REGEXP_LIKE(Val_14,'^[0-9]+$')))
group by Val_35,network_id,Val_12,Val_13,Val_14
)
where Val_35 = b.Val_35 and network_id = b.network_id and rownum=1
)
where status = 'PCStep2' and (regexp_like(Val_13,'[MSS]+') or regexp_like(Val_14,'[MSS]+'));
I tried a lot with my less Knowledge In SQL JOINs. but getting multiple erros.
can anybody help me with the queries at the earliest.
Hearty thanks in advance
Actually you can not mix a update statement with a join statement. An update statement always expects exactly one table definition after the update command.
-- ORA-00971: missing SET keyword
update orders o, customers c
set o.order_value = c.account_value
where o.cust_id = c.cust_id
-- works fine
update orders o
set o.order_value = (select c.account_value
from customers c
where c.id = o.cust_id)

Update in child table, only one value got updated

Below I am trying to update value of a parent table from child table and counting matching values. Tables in my db:
issue_dimension with id = issue_id and have column accno.
star_schema with id star_id,this Child column have fk issue_id and column book_frequency
The book_frequency need to match the count of each accno in parent table , I tried this
update [test1] .[dbo] .star_schema
set [book_frequency] = (
select top 1 COUNT([issue_dimension].ACCNO)as book_frequency
from issue_dimension
group by ACCNO having (COUNT(*)>1) and
issue_dimension.ACCNO = star_schema .ACCNO
)
It only updates only 1st value count issue_dimension. I need to count every accno in issue_dimension and update it to matching accno of star_schema.
I never did update by joining two or more tables , can anyone help in this with joins
UPDATE s
SET [book_frequency] = i.CNT
FROM [test1].[dbo].star_schema s
INNER JOIN
(
SELECT ACCNO, COUNT(*) as CNT
FROM issue_dimension
GROUP BY ACC_NO
HAVING COUNT(*)>1
) i on (s.ACCNO = i.ACCNO)
I didn't check it but it should works
Try in this way, without grouping, just with the WHERE clause:
UPDATE [test1].[dbo].star_schema SET
[book_frequency] =
(
SELECT COUNT([issue_dimension].ACCNO)
FROM issue_dimension
WHERE issue_dimension .ACCNO = star_schema.ACCNO
HAVING COUNT(*)>1
)
It's not fully clear to me so the answer is a bit of guessing:
update s set
book_frequency = t.qty
from star_schema s
join issue_dimension i on s.issue_id = s.issue_id
join (select count(*) as qty, accno
from issue_dimension
group by accno
) t on i.accno = t.accno
Here's the example from BOL that does the kind of thing you're looking for, using AW:
USE AdventureWorks2008R2;
GO
UPDATE Sales.SalesPerson
SET SalesYTD = SalesYTD +
(SELECT SUM(so.SubTotal)
FROM Sales.SalesOrderHeader AS so
WHERE so.OrderDate = (SELECT MAX(OrderDate)
FROM Sales.SalesOrderHeader AS so2
WHERE so2.SalesPersonID = so.SalesPersonID)
AND Sales.SalesPerson.BusinessEntityID = so.SalesPersonID
GROUP BY so.SalesPersonID);