I need to update a table based on multiple conditions and the update needs to be done in one update statement. In addition, the restriction is that I CANNOT use the following construct due to performance issues since there are about 18 CASE expressions in my update:
UPDATE A
SET A.col1 = CASE WHEN B.col = someValue THEN B.Col2 END,
B.Col2 = CASE WHEN b.col = someOtherValue THEN B.Col2 END,
.
.
--18th CASE stmt
B.Col18 = CASE WHEN b.col = YetAnotherValue THEN B.Col2 END
FROM
tableA A
INNER JOIN
tableB B ON A.someColumn = B.someColumn
Any suggestions will be appreciated .
I suspect that you actually want to aggregate before updating:
UPDATE A
SET A.col1 = B.col1,
B.Col2 = B.col2,
. . .
FROM tableA A JOIN
(SELECT B.someColumn,
MAX(CASE WHEN B.col = someValue THEN B.Col2 END) as col1,
MAX(CASE WHEN b.col = someOtherValue THEN B.Col2 END) as col2,
. . .
FROM tableB B
GROUP BY B.someColumn
) B
ON A.someColumn = B.someColumn
Related
I'm dealing with an issue; I need to join two tables, group by their ID's and use CASE statement to compare values from those 2 tables. I have been trying to use a temp table and then SELECT from it.
Purpose is to test if values in CORE correspond to values in MART.
Ideally I want to have one query, where I will see column CORE_X_MART and can use where statement on it.
Group by is essential because otherwise I have ID duplicates in the temporary table.
My code:
drop table if exists #tNDWH_4034
select a.ID, b.ID, a.col2 as MART_Value, b.col2 as CORE_Value,
case when a.col2 = b.col2 then 'Match' else 'Mismatch' end as CORE_X_MART
into #tNDWH_4034
from tab1 as a
inner join tab2 as b on a.ID = b.ID
where a.CurrentFlag = 1
group by a.ID, b.ID;
select * from #tNDWH_4034
where CORE_X_MART = 'Mismatch';
I'm using SQL server.
You don't need temp table. You can go for derived table to achieve the purpose, to have them in a single query.
SELECT * FROM
(select a.ID, b.ID, a.col2 as MART_Value, b.col2 as CORE_Value,
case when a.col2 = b.col2 then 'Match' else 'Mismatch' end as CORE_X_MART
from tab1 as a
inner join tab2 as b
on a.ID = b.ID
where a.CurrentFlag = 1
group by a.ID, b.ID) as t
WHERE t.CORE_X_MART = 'Mismatch'
maybe:
select a.ID, b.ID, a.col2 as MART_Value, b.col2 as CORE_Value,
case when a.col2 = b.col2 then 'Match' else 'Mismatch' end as CORE_X_MART
into #tNDWH_4034
from tab1 as a
inner join tab2 as b on (a.ID = b.ID)
where a.CurrentFlag = 1
group by a.ID, b.ID, a.col2, b.col2
,case when a.col2 = b.col2 then 'Match' else 'Mismatch' end --this line is probably not required
You don't need the temp table, group by, or the case either. You are looking for mismatches only so just use the not equal to operator <> to filter your results.
select distinct a.ID, a.col2 as MART_Value, b.col2 as CORE_Value
from tab1 as a
inner join tab2 as b on a.ID = b.ID
where a.CurrentFlag = 1
and a.col2 <> b.col2
I have tablea and tableb, that I need to join.
It can happen that in b.col2, b.col3 can be value '%', which should be something like wildcard, meaninng, that in this case we can join value of b.col2 on any value of a.col2 or value b.col3 on any value a.col3.
One solution would look like this:
select a.*, b.col4, b.col5
from tablea a
left join (select col1, col2, col3, col4, col5 tableb) b
on b.col1=a.col1 and
(b.col2 = a.col2 or b.col2 = '%') and
(b.col3 = a.col3 or b.col3 = '%')
qualify 1 = row_number() over (partition by a.id order by (case when b.col2 = '%' then 2 else 1 end), (case when b.col3 = '%' then 2, else 1 end))
My problem is that because of later use in different app, I can only use simple join conditions like:
b.col1 = a.col1 and
b.col2 = a.col2 and
b.col3 = a.col3
My question is, if there is a way, how to achieve the same result as in the first solution, but using 'simple' join conditions (a.col2=b.col2) and just making changes in selection of tableb?
I have joined tables like bellow:
select a.*, b.col4, b.col5 from table a
inner join table b
on a.col2=b.col2
and a.col3=b.col3
It can happen that in b.col2, b.col3 can be value '*', which should be something like wildcard, meaninng, that in this case we can join value of b.col2 on any value of a.col2 or value b.col3 on any value a.col3.
Would you please help me define it?
It sounds like you have a default. One method is multiple comparison:
select a.*,
coalesce(b.col4, bdef3.col4, bdef2.col4, bdef.col4) as col4, b.col5
coalesce(b.col5, bdef3.col5, bdef2.col5, bdef.col5) as col5
from tablea a left join
tableb b
on b.col2 = a.col2 and b.col3 = a.col3 left join
tableb bdef3
on b.col2 = a.col2 and b.col3 = '*' left join
tableb bdef2
on b.col2 = '*' and b.col3 = a.col3 left join
tableb bdef
on b.col2 = '*' and b.col3 = '*';
You may want a where clause if you want to guarantee some match:
where (b.col2 is not null or bdef3.col2 is not null or bdef2.col2 is not null or bdef.col2 is not null)
I think the above is more efficient, but you can express this more succinctly as:
select a.*, b.col4, b.col5
from tablea a left join
tableb b
on (b.col2 = a.col2 or b.col2 = '*') and
(b.col3 = a.col3 or b.col3 = '*')
qualify 1 = row_number() over (partition by a.id order by (case when b.col2 = '*' then 2 else 1 end), (case when b.col3 = '*' then 2, else 1 end))
My delete statement returns a 933 error in Oracle, I'm not sure what is wrong-
DELETE b
from temp a
JOIN
fact_tab b
on a.col1 = b.col1
and a.col2 = b.col2
and a.col3 = b.col3;
Both tables dont have a primary key. select statement on the same thing works-
select *
from temp a
JOIN
fact_tab b
on a.col1 = b.col1
and a.col2 = b.col2
and a.col3 = b.col3;
try this
DELETE FROM
fact_tab
WHERE
EXISTS
(
SELECT
1
FROM
temp
WHERE
temp.col1 = fact_tab.col1 AND
temp.col2 = fact_tab.col2 AND
temp.col2 = fact_tab.col2
)
Oracle doesn't allow JOIN in a DELETE statement directly like that.
You could do the delete in the following way:
DELETE
FROM fact_tab
WHERE ROWID IN
(SELECT b.rowid
FROM temp a
JOIN fact_tab b
ON a.col1 = b.col1
AND A.col2 = b.col2
AND A.col3 = b.col3
);
You could also use WHERE EXISTS clause.
UPDATE
TABLE1 a,
TABLE2 b
SET
a.COL1 = 'VALUE'
WHERE
a.FK = b.PK
AND b.COL2 IN ('A subquery')
If I am using this update statement and the subquery in the IN clause does not return any rows, I get an error. How do I avoid that? (Oracle 10g)
You likely can rewrite this to an EXISTS query, depending on the exact details of your subquery:
UPDATE TABLE1 a, TABLE2 b SET a.COL1 = 'VALUE'
WHERE a.FK = b.PK AND EXISTS (select 1 from OTHERTABLE O where B.COL2=O.COL2)
UPDATE
TABLE1 a
SET
a.COL1 = 'VALUE'
WHERE
a.FK IN (SELECT b.PK FROM b WHERE b.COL2 in ....)
Is your subquery in quotes?
UPDATE
TABLE1 a,
TABLE2 b
SET
a.COL1 = value
WHERE
a.FK = b.PK
AND b.COL2 IN (
SELECT col2
FROM ...
WHERE ...
)