condition that applies to multiple lines before update is made in another table - sql

I have two tables, one table is linked by a foreign key to the other.
I need to create an update statement that would update table one based on a condition in table two. However, the conditions have to relate to one or more lines in table two.
Example - Table Two
Order A
line 1 = open (status column)
line 2 = closed (staus column)
When line 1 is also closed (same order number - in this case A), the condition is met so the order will then be closed (updated to closed) in the other table. Table on only has header information (no multiple lines).
I am having trouble with righting a condtion that looks at multiple lines in table two (all lines have to be closed) before the update to table one is made.
Any helpful suggestions would be appreciated.

Assuming that (1) the key name is ordernum, and (2) EVERY table1 entry has at least one entry in table2, this is a simple query that should work for you. Basically, the not exists clause is testing that there are no open lines in the second table.
update table1
set table1.status = 'closed'
where table1.status = 'open'
and not exists
(select 1
from table2
where table2.ordernum = table1.ordernum
and table2.status = 'open')
This may need tweaked further based on your business requirements.
Update based on user request: You could try this, but performance may take a hit, I've not tested it:
update table1
set table1.status = 'closed',
table1.count_lines =
(select count(1)
from table2 y
where y.ordernum = table1.ordernum
)
where table1.status = 'open'
and not exists
(select 1
from table2 z
where z.ordernum = table1.ordernum
and z.status = 'open')
Update 2: Try this from your last comment. You are wanting to update the ZORDER table with the sum of all the line item prices. So you must UPDATE ZORDER, not ZORDERLINE. The total is found by summing EXTENDED_PRICE on all ZORDERLINE rows that match the order id. There may be some additional business logic needed in the first sub-query (eg., if you need to exclude certain statuses like canceled items), but this should get you very close.
UPDATE zorder
SET zorder.status = 3,
zorder.total =
(SELECT SUM(Y.EXTENDED_PRICE)
FROM ZORDERLINE Y
WHERE Y.order_id = zorder.order_id)
WHERE zorder.status = 1
and not exists
(select 1
from zorderline z
where z.order_id = zorder.order_id
and z.status = 1)

Related

Get the "most" optimal row in a JOIN

Problem
I have a situation in which I have two tables in which I would like the entries from table 2 (lets call it table_2) to be matched up with the entries in table 1 (table_1) such that there are no duplicates rows of table_2 used in the match up.
Discussion
Specifically, in this case there are datetime stamps in each table (field is utcdatetime). For each row in table_1, I want to find the row in table_2 in which has the closed utcdatetime to the table 1 utcdatetime such that the table2.utcdatetime is older than the table_1 utcdatetime and within 30 minutes of the table 1 utcdatetime. Here is the catch, I do not want any repeats. If a row in table 2 gets gobbled up in a match on an earlier row in table 1, then I do not want it considered for a match later.
This has currently been implemented in a Python routine, but it is slow to iterate over all of the rows in table 1 as it is large. I thought I was there with a single SQL statement, but I found that my current SQL results in duplicate table 2 rows in the output data.
I would recommend using a nested select to get whatever results you're looking for.
For instance:
select *
from person p
where p.name_first = 'SCCJS'
and not exists (select 'x' from person p2 where p2.person_id != p.person_id
and p.name_first = 'SCCJS' and p.name_last = 'SC')

finding int_ids that have more than one row with a flag set to Y

I have a table that can store multiple descriptions for each code. However there is a flag in that table that is to indicate which of those is the main or primary description. In some instances, we have codes that have more than one with this flag set to Y which is not correct.
I am having trouble coming up with the SQL to get all the rows in that table that have more than one description set to Y.
I've used this SQL to identify rows that do not have ANY dsp_fg = 'Y'
select *
from table A
where dsp_fg = 'N'
and not exists (select 1 FROM table where cod_int_id = A.cod_int_id AND dsp_fg = 'Y')
But I am having trouble writing the SQL to get me the cod_int_ids that have more than one Y record, can someone help?
SELECT int_id FROM A
WHERE dsp_fg = 'Y'
GROUP BY int_id
HAVING count(1) > 1
This is not perfect, but it identifies what I need.

SQL-Oracle: Updating table multiple row based on values contained in the same table

I have one table named: ORDERS
this table contains OrderNumber's which belong to the same person and same address lines for that person.
However sometimes the data is inconsistent;
as example looking at the table screenshot: Orders table with bad data to fix -
you all can noticed that orderNumber 1 has a name associated to and addresses line1-2-3-4. sometimes those are all different by some character or even null.
my goal is to update all those 3 lines with one set of data that is already there and set equally all the 3 rows.
to make more clear the result expected should be like this:
enter image description here
i am currently using a MERGE statement to avoid a CURSOR (for loop )
but i am having problems to make it work
here the SQL
MERGE INTO ORDERS O USING
(SELECT
INNER.ORDERNUMBER,
INNER.NAME,
INNER.LINE1,
INNER.LINE2,
INNER.LINE3,
INNER.LINE4
FROM ORDERS INNER
) TEMP
ON( O.ORDERNUMBER = TEMP.ORDERNUMBER )
WHEN MATCHED THEN
UPDATE
SET
O.NAME = TEMP.NAME,
O.LINE1 = TEMP.LINE1,
O.LINE2 = TEMP.LINE2,
O.LINE3 = TEMP.LINE3,
O.LINE4 = TEMP.LINE4;
the biggest issues i am facing is to pick a single row out of the 3 randomly - it does not matter whihc of the data - row i pick to update the line/s
as long i make the records exaclty the same for an order number.
i also used ROWNUM =1 but it in multip[le updates will only output one row and update maybe thousand of lines with the same address and name whihch belong to an order number.
order number is the join column to use ...
kind regards
A simple correlated subquery in an update statement should work:
update orders t1
set (t1.name, t1.line1, t1.line2, t1.line3, t1.line4) =
(select t2.name, t2.line1, t2.line2, t2.line3, t2.line4
from orders t2
where t2.OrderNumber = t1.OrderNumber
and rownum < 2)

How to compare records and update one column

It is a little bit tricky for me so I need your help :)
I want to update the column Relevant to 0 WHERE Contract_Status_Code is 10 OR the Date_Contract_start YEAR is the same AND the Ranking_Value is lower than the other one ON all records that have the same VIN.
So I want to compare all records which have the same VIN.
Few examples to illustrate it:
I have there two records with the VIN = 123456. One of them (ID = 6847) has a higher Ranking_Value (7) than the other one (3). The YEAR is the same as well so I want to update the column relevant to 0 where the ID is 8105.
Two records with the VIN = 654321. Both of them have the same Ranking_Value but the record with the id = 11012 has the value 10 for the column Contract_Status_Code so I want to update the relevant column to 0 where the ID = 11012.
The last two records... They have the VIN = 171819. The first one (ID = 11578) has the higher Ranking_Value. But they have a different year where the contract has started. So I don't want to update both.
It is also possible that there are three or four records with the same VIN.
I hope you understand my problem. I'm from Germany so sorry for my English :)
By considering your ID column as unique or Identity column, I can suggest you the below query for your solution:
With cte
As
(Select a.Id, a.VIN From Table a
Join (Select max(Ranking_Value) ranks,VIN From Table Group By VIN, Year(Date_Contract_start)) b
on a.VIN=b.VIN And a.Ranking_Value = b.ranks)
update table
set Relevant = 0
where (Contract_Status_Code = 10) Or
ID Not In (Select id from cte)
update table1
set Relevant = 0
where Contract_Status_Code = 10
or (VIN,Year,Ranking_value) not in(
select VIN,Year,max(Ranking_Value)
from table1
group by VIN,Year
)

Update a table based on a results of a group by

Update a table based on a results of a group by
I've got a tricky update problem I'm trying to solve. There are two tables that contain the same three columns plus additional varied columns, looking like this:
Table1 {pers_id, loc_id, pos, ... }
Table2 {pers_id, loc_id, pos, ... }
None of the fields are unique. The first two fields collectively identify the records in a table (or tables) as belonging to the same entity. Table1 could have 15 records belonging to an entity, and table2 could have 4 records belonging to the same entity. The third column 'pos' is an index from 0 to whatever, and this is the column that I'm trying to update.
In Table1 and in Table2, the pos column begins at 0, and increments based on user selection, so that in the example (15 records in table1 and 4 records in table2), table1 contains 'pos' values of 0 - 14, and Table2 contains 'pos' values of 0-3.
I want to increment the pos field in Table1 with the results of the count of similar entities in Table2. This is the sql statement that correctly gives me the results from table2:
select table2.pers_id, table2.loc_id, count(*) as pos_increment from table2 group by table2.pers_id, table2.loc_id;
The end result of the update, in the example (15 records in table1 and 4 records in table2), would be all records in Table1 of the same entity being incremented by 4 (the result of the specific entity group by). 0 would be changed to 4, 15 to 19, etc.
Is this achievable in a single statement?
Since you only need to increment the pos field the solution is really simple:
update table1 t1
set t1.pos = t1.pos +
(select count(1)
from table2 t2
where t2.pers_id = t1.pers_id
and t2.loc_id = t1.loc_id)
Yes, this is possible, you can use MERGE for some of these upadtes and there are ways to relate values between the update and the subselect. I have done this in the past, but it's tricky and I don't have an existing example.
You can find several examples on this site, some for Oracle and some for other database that will awork with slight modifications.