sql case statement update based on other table - sql

I want to update a table (table1) based on the values of one or more fields in another table (table2). I believe this should be a case statement but I'm unsure how to incorporate a case statement and an update clause based on another table in one statement. Here's what I have so far which I know does not work:
update table1 i, table2 s
set i.sales = 'F'
where s.payment = 'Y'
and i.order_no = s.order_no;
I know how to do a select based on two tables but that's not very helpful since I don't want to create a new database object - I just want to update an existing object (table1):
create or replace view merge as
select
i.order_no
, case when s.payment = 'Y'
then 'F'
end as sales
from table1 i, table2 s
where i.order_no = s.order_no;
And I know how to update WITHIN a case statement:
UPDATE table1
SET sales = (
SELECT CASE
WHEN foo = 'X'
THEN 'F'
ELSE null
END
FROM table1
)
;
I considered a where clause instead of a case statement but it ends up selecting EVERY record and the 2nd table definitely has different values in the payment field:
update t1
set sales = 'F'
where exists (select table2.payment
from table2
where table2.order_no = table1.order_no
and table2.payment = 'Y');

try this:
update table1 i
set i.sales = (select case when x.payment = 'Y'
then 'F'
else i.sales end
from table2 x
where x.order_no = i.order_no);

I don't have an oracle running right now (so I cannot check the syntax propertly), but I think you can try something like this:
update table1 i
set i.sales = 'F'
where i.order_no IN (select s.order_no from table2 s where s.payment = 'Y')
Hope it helps!

Related

How to set SQL condition precedence for two different conditions

I'm having two different tables 'TABLE1' and 'TABLE2'. Both of these tables have same column name - 'IS_PDF'.
RE TABLE1.IS_PDF value, I retrieved the required details using select statement where I added where clause like below.
select * from TABLE1 where TABLE1.IS_PDF = 'Y';
Similarly, I can get the values for TABLE2 as well where TABLE2.IS_PDF = 'Y'
Now, my task is to have one select statement to get the details from both tables 'TABLE1' and 'TABLE2' by setting a precedence on below condition # 1.
If TABLE1.IS_PDF = 'Y', return records matching same condition.
If TABLE1.IS_PDF = 'N' but TABLE2.IS_PDF = 'Y' then return records matching same condition.
If both have IS_PDF = 'N', return nothing.
I used below Select statement but getting Above conditions # 1 and 2 at the same time only.
select * from TABLE1, TABLE2
where
(TABLE1.IS_PDF = 'Y') or (TABLE2.IS_PDF = 'Y' and TABLE1.IS_PDF = 'N' )
Please guide on the same.
Thanks
You seem to want something like this:
select t1.*
from table1 t1
where t1.is_pdf = 'Y'
union all
select t2.*
from table2 t2
where t2.is_pdf = 'Y' and
not exists (select 1 from table1 t1 where t1.is_pdf = 'Y' and t1.?? = t2.??);
The ?? represents the column(s) used for matching between the two tables.
Thanks for the quick response.
Sample code-
select TABLE1.IS_PDF, TABLE2.IS_PDF, TABLE1.ID, TABLE1.GLOBAL_ID, TABLE1.title,
from TABLE1, TABLE2
where TABLE1.USER_ID = 82340
and TABLE1.NAME = 'INDIA'
and (TABLE1.IS_PDF = 'Y') or (TABLE2.IS_PDF = 'Y' and TABLE1.IS_PDF = 'N' )
I need to set a precedence on below condition # 1. If condition # 1 meets, it's fine. Otherwise go for #2 then #3.
If TABLE1.IS_PDF = 'Y', return records matching same condition.
If TABLE1.IS_PDF = 'N' but TABLE2.IS_PDF = 'Y' then return records matching same condition.
If both have IS_PDF = 'N', return nothing.

How to write the update query to update target table column A with values 'Y' or 'N' based on if it exists or not in source table

I want to update column A of my target table with values 'Y' if the key_id_column exists in (SELECT ID_COLUMN FROM SOURCE_TBL) and with values 'N' if it does not exists in (SELECT ID_COLUMN FROM SOURCE_TBL)
update target_table
set target_column = case when target_column in (select column from source_table) then 'Y' else 'N' end;
hope this works
This is an example of how to manage an OUTER JOIN in an UPDATE statement on Teradata. You may need to tweak it a bit, but it should get you along down the road a bit further.
UPDATE target_table
SET target_column = DT.indicator_column
FROM (SELECT CASE WHEN tgt.key_id_column is not null
THEN 'Y'
ELSE 'N'
END as indicator_column
FROM source_table src
LEFT JOIN
target_table tgt
ON src.id_column = tgt.key_id_column) DT;

Update Multiple ID's based on field value

I want to find all lines of data that have a value, say 'N/A'
I want to then update ALL the lines of data where they have the same CommonID into the NewDataHere Column so in the example below ID 1 and 2 would be affected
I am doing this in a stored procedure
Code for far:
DECLARE #sqlPRatingChange NVARCHAR(MAX)
SET #sqlPRatingChange = 'UPDATE TblAsbestos SET NewDataHere= ''NA''
WHERE (SELECT ID FROM TBLASBESTOS WHERE VALUE= ''N/A'')'''
EXEC (#sqlPRatingChange)
Example of Database as it should look after code
ID-VALUE-NewDataHere
1-N/A-N/A
2-C-N/A
2-N/A-N/A
1-A-N/A
3-B-''
Why are you using dynamic SQL? Your query seems close enough. It just needs a correlation clause:
UPDATE TblAsbestos
SET NewDataHere = 'NA'
WHERE (SELECT ID FROM TBLASBESTOS a2 WHERE VALUE = 'N/A' AND TblAsbestos.id = a2.id);
In SQL Server, I might be inclined to do this using a CTE and window functions:
with toupdate as (
select a.*,
sum(case when value = 'N/A' then 1 else 0 end) over (partition by id) as numNAs
from TblAsbestos a
)
update toupdate
set NewDataHere = 'NA'
where numNAs > 0;
This should possibly be a comment on Gordon's answer, but it got too long and the formatting that an answer affords helps...
The incorrect syntax error is because in SQL Server you cannot alias the target of an update statement (not to be confused with using an alias as the target which is allowed). The where clause is also incorrect, it appears to be mix between an EXISTS clause and an IN clause, but has ended up as neither. I think you need:
UPDATE TblAsbestos
SET NewDataHere = 'NA'
WHERE EXISTS
( SELECT 1
FROM TblAsbestos AS a
WHERE a.Value = 'N/A'
AND a.id = TblAsbestos.id
);
Or
UPDATE TblAsbestos
SET NewDataHere = 'NA'
WHERE ID IN (SELECT a.ID FROM TblAsbestos AS a WHERE a.Value = 'N/A');
Try this. Just replace table1 with your table name :
update a
set NewDataHere = 'N/A'
from table1 as a
where exists(select 1 from table1 as b where a.id = b.id and b.value = 'N/A')
Try this:
UPDATE TblAsbestos a
SET NewDataHere = 'NA'
WHERE Exists (SELECT Top 1 ID
FROM TBLASBESTOS a2
WHERE Upper(value) = 'N/A'
AND a.id = a2.id);

Postgresql Update using Inner Join set

I have two tables that they share two fields (myfield1, myfield2) and one of the two tables has 2 other fields of interest.
Here is what I want to do:
1. Inner Join the two tables
2. Update a column (field1) in Table2 with either fields (afield or anotherfield) from the other table depending on afield is null or not.
The code below runs fine but the targeted set field (field1) doesn't get updated with anything.
Update Table2
Set field1 = (
CASE
WHEN os.afield is not null
THEN (os.afield)
Else os.anotherfield
End
)
from Table1 os
inner join Table2 fd
ON fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2;
Update Table2 fd
Set fd.field1 =
(select CASE WHEN os.afield is not null THEN (os.afield) Else os.anotherfield End
from Table1 os
where fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2);
It's called a correlated subquery which is executed for each row in Table2. But you must be sure that subquery returns single or zero rows.
This query will update all rows in Table2 if you want to update only those rows which exist in Table1 you need a WHERE
Update Table2 fd
Set fd.field1 =
(select CASE WHEN os.afield is not null THEN (os.afield) Else os.anotherfield End
from Table1 os
where fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2)
where exists (
select 1 from Table1 os
where fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2);

SQL Statement Performance Issue on Informix

I have this Informix SQL statement which takes ages to run. Does anybody see any way to optimize it so it wouldn't take so long?
SELECT * FROM OriginalTable WHERE type = 'S' AND flag <> 'S' INTO TEMP TempTableA;
SELECT * FROM OriginalTable WHERE type = 'Z' AND flag <> 'S' INTO TEMP TempTableB;
UPDATE OriginalTable SET flag = 'D' WHERE Serialnumber in
(
select Serialnumber from TempTableA
WHERE NOT EXISTS(SELECT * FROM TempTableB
WHERE TempTableB.Col1 = TempTableA.Col1
AND TempTableB.Col2 = TempTableA.Col2)
)
I have in my OriginalTable around 300 million rows, TempTableA 93K rows, and TempTableB 58K rows.
Update OriginalTable
Set flag = 'D'
Where Type = 'S'
And Flag <> 'S'
And Not Exists (
Select 1
From OriginalTable As T1
Where T1.Type = 'Z'
And T1.flag <> 'S'
And T1.Col1 = OriginalTable.Col1
And T1.Col2 = OriginalTable.Col2
)
In a similar approach as #tombom stated. Pre-query only the columns you care about to keep the temp table smaller. If you are dealing with a table of 60 columns, you are filling a whole lot more than just 3-4 columns where your primary consideration are valid serial numbers. Pre-test the query to make sure it gives you the correct set you are expecting, then apply that to your SQL-update.
So here, the inner query are the ones you DO NOT WANT... Since you were comparing against only column 1 and column 2 from this table, that's all I'm pre-querying. I'm then doing a LEFT JOIN to this inner result set on COL1 and COL2. I know, you want to EXCLUDE THOSE FOUND IN THIS result set... That's why, in the OUTER WHERE clause, I've added "AND ExcludeThese.Col1 IS NULL". So, any instances from OT1 that never existed in the subquery are good to go (via left join), and those that WERE FOUND, WILL have a match on col1 and col2, but THOSE will be excluded via the "and" clause I've described.
SELECT OT1.SerialNumber
FROM OriginalTable OT1
LEFT JOIN ( select OT2.Col1,
OT2.Col2
FROM OriginalTable OT2
where OT2.type = 'Z'
AND OT2.flag <> 'S' ) ExcludeThese
ON OT1.Col1 = ExcludeThese.Col1
AND OT1.Col2 = ExcludeThese.Col2
WHERE OT1.type = 'S'
AND OT1.flag <> 'S'
AND ExcludeThese.Col1 IS NULL
ORDER BY
OT1.SerialNumber
INTO
TEMP TempTableA;
Again, test this query by itself to make sure you ARE getting the records you expect. To help clarify the records returned, change the above select to include more columns for a mental / sanity check, such as
SELECT OT1.SerialNumber,
OT1.Col1,
OT1.Col2,
ExcludeThese.Col1 JoinedCol1,
ExcludeThese.Col2 JoinedCol2
from <keep rest of query intact>
Now, you'll be able to see the serial number and instances of those columns that would or not be joined to the "excludeThese" resultset... Try again, but remove only the
"AND ExcludeThese.Col1 IS NULL" clause, and you'll see the other lines and WHY they are being excluded -- that is if you DID have any questions to the content.
Once you are satisfied with the pre-query... which will only return the single column of SerialNumber, that can be index/optimized since you are pulling into a temp table, build an index, then apply your update.
UPDATE OriginalTable
SET flag = 'D'
WHERE Serialnumber in ( select Serialnumber from TempTableA );
I was too lazy to test with test data, but maybe this can do?
SELECT col1, col2,
CASE WHEN type = 'S' THEN 1
ELSE WHEN type = 'Z' THEN 2 END AS filteredType
FROM OriginalTable WHERE (type = 'S' OR type = 'Z') AND flag <> 'S' INTO TempTable;
UPDATE OriginalTable SET flag = 'D' WHERE Serialnumber IN
(
SELECT t1.Serialnumber FROM TempTable t1
LEFT JOIN TempTable t2 ON (t1.col1 = t2.col2 AND t1.col2 = t2.col2)
WHERE t1.filteredType = 1
AND t2.filteredType = 2
AND t2.Serialnumber IS NULL
)
That way you can omit one loading into temp table. On the other hand there will be no index on the new column filteredType.
Also I have no idea of informix. Hope it helps anyway.