What's the difference between these two update SQL statements in Oracle
First:
UPDATE t1
SET col1 = 'Y'
WHERE EXISTS (SELECT *
FROM t2
WHERE t1.p1 = t2.p1
AND t1.p2 = t2.p2
AND t2.col3 = 'a'
AND t1.p1 = 'b'
AND t1.p2 = 'c')
Second:
UPDATE t1
SET col1 = 'Y'
WHERE EXISTS (SELECT *
FROM t2
WHERE t1.p1 = t2.p1
AND t1.p2 = t2.p2
AND t2.col3 = 'a')
AND t1.p1 = 'b'
AND t1.p2 = 'c'
there is no difference at all - they have the same meaning
Related
I have this SQL in DB2 and want to avoid repeating the conditions in the EXISTS clause in the second UNION, as the conditions can be fairly large. How do I do that? Any help is greatly appreciated.
select id from table t where t.given_name = 'good' and t.time = 1 and exists
(select 1 from table t1 where t1.id = t.id and t1.surname = 'OK') union
select id from table t where t.given_name = 'good' and t.time = 2 and not exists
(select 1 from table t1 where t1.id = t.id and t1.surname = 'OK')
I think this could be also achieve via where clause only
where given_name = 'good' and
(times = 1 and surname = 'OK') or
(times = 2 and surname <> 'OK')
Why are you using union? How about just doing this?
select id
from table t
where t.given_name = 'good' and
t.time in (1, 2) and
exists (select 1 from table t1 where t1.id = t.id and t1.surname = 'OK');
If id could have duplicates, use select distinct in the outer query.'
EDIT:
I think I misread the original query. The logic would be:
select id
from table t
where t.given_name = 'good' and
( (t.time = 1 and exists (select 1 from table t1 where t1.id = t.id and t1.surname = 'OK')
) or
(t.time = 2 and not exists (select 1 from table t1 where t1.id = t.id and t1.surname = 'OK')
)
)
Use a WITH clause to remove redundancy
with t2 as (select * from t1 where surname = 'OK')
select id from table t where t.given_name = 'good' and t.time = 1 and exists
(select 1 from table t2 where t2.id = t.id) union
select id from table t where t.given_name = 'good' and t.time = 2 and not exists
(select 1 from table t2 where t2.id = t.id)
;
and you can do the same for the other table too if needed
with t2 as (select * from t1 where surname = 'OK')
, tt as (select * from t where given_name = 'good')
select id from table tt where tt.time = 1 and exists
(select 1 from table t2 where t2.id = tt.id) union
select id from table tt where tt.time = 2 and not exists
(select 1 from table t2 where t2.id = tt.id)
;
I have two looK up tables, and need is to fetch value by correlating the both tables.
As of now I am doing this with multiple sub queries and trying to find a easiest way.
SELECT
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'A') AND T1.ID = 'AA')as A,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'B') AND T1.ID = 'BB')AS B,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'C') AND T1.ID = 'CC')AS C,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'D') AND T1.ID = 'DD')AS D,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'E') AND T1.ID = 'EE')AS E,
(SELECT TYPE_NAME FROM T1 where FK_T2 = (SELECT PK FROM T2 WHERE T2.ID = 'F') AND T1.ID = 'FF')AS F
FROM MYTABLE;
I assume you need something like this.
SELECT MAX ( CASE WHEN T1.ID = 'AA' AND T2.ID = 'A' THEN TYPE_NAME END ) as A,
MAX ( CASE WHEN T1.ID = 'BB' AND T2.ID = 'B' THEN TYPE_NAME END ) as B,
MAX ( CASE WHEN T1.ID = 'CC' AND T2.ID = 'C' THEN TYPE_NAME END ) as C,
..
FROM T1 t1
INNER JOIN T2 t2
ON t1.FK_T2 = t2.PK
I'll try something like:
SELECT
T1.TYPE_NAME,
T1.ID
FROM T1 t1
INNER JOIN T2 t2
ON t1.FK_T2 = t2.PK
WHERE
T1.ID||T1.ID = T2.ID
You could try rephrasing these queries as a single query consisting of a join between the two tables:
SELECT
T1.TYPE_NAME,
T1.ID
FROM T1 t1
INNER JOIN T2 t2
ON t1.FK_T2 = t2.PK
WHERE
(T1.ID = 'AA' AND T2.ID = 'A') OR
(T1.ID = 'BB' AND T2.ID = 'B') OR
(T1.ID = 'CC' AND T2.ID = 'C') OR
(T1.ID = 'DD' AND T2.ID = 'D') OR
(T1.ID = 'EE' AND T2.ID = 'E') OR
(T1.ID = 'FF' AND T2.ID = 'F');
You can keep track of to which subquery each returned record corresponds by checking the value of the ID column in the first table. This would serve as a marker for the source subquery.
I have 2 tables like this:
For example in first row from table 2 col value is 3661 and its equal to 'med' from table 1 I want to update class from table 1 with 'MED' and ...
This is the code I wrote but something is wrong :(
UPDATE table1 SET
class = ( CASE
WHEN table2.col = table1.med
THEN 'MED'
--------------------------------
WHEN table2.col = table1.mgl
THEN 'MGL'
--------------------------------
WHEN table2.col = table1.rhp
THEN 'RHP'
--------------------------------
WHEN table2.col = table1.epd
THEN 'EPD'
--------------------------------
WHEN table2.col = table1.jpa
THEN 'JPA'
--------------------------------
ELSE 'NULL'
FROM
table1 LEFT outer JOIN table2
)
I edited your code. you did not mention which database you use,
Anyway try this:
UPDATE table1
SET class = ( CASE
WHEN table2.col = table1.med
THEN 'MED'
--------------------------------
WHEN table2.col = table1.mgl
THEN 'MGL'
--------------------------------
WHEN table2.col = table1.rhp
THEN 'RHP'
--------------------------------
WHEN table2.col = table1.epd
THEN 'EPD'
--------------------------------
WHEN table2.col = table1.jpa
THEN 'JPA'
--------------------------------
ELSE 'NULL'
END)
from table1 left join table2 on table1.number=table2.number
You want something like this:
UPDATE table1
SET class = COALESCE((SELECT MIN(CASE WHEN table2.col = table1.med THEN 'MED'
WHEN table2.col = table1.mgl THEN 'MGL'
. . .
END) as newval
FROM table2
), 'NULL')
This is a bit tricky. You need to decide which row you want if there are multiple matches. The above chooses an arbitrary value among the matches.
The coalesce() is to handle the case where there are no matches. The subquery will return NULL in that case.
This is standard SQL and should work in any database. Specific databases might have other ways of writing this query.
Tried it in MySQL, this is working
UPDATE Table1
INNER JOIN Table1 T1
LEFT JOIN Table2 T2
ON T1.number = T2.number
set T1.class =
( CASE
WHEN T2.col = T1.med
THEN 'MED'
WHEN T2.col = T1.mgl
THEN 'MGL'
WHEN T2.col = T1.rhp
THEN 'RHP'
WHEN T2.col = T1.epd
THEN 'EPD'
WHEN T2.col = T1.jpa
THEN 'JPA'
ELSE 'NULL'
END
)
EDIT:
In case of MS SQL SERVER, you can use this
UPDATE Table1
set class =
( CASE
WHEN T2.col = T1.med
THEN 'MED'
WHEN T2.col = T1.mgl
THEN 'MGL'
WHEN T2.col = T1.rhp
THEN 'RHP'
WHEN T2.col = T1.epd
THEN 'EPD'
WHEN T2.col = T1.jpa
THEN 'JPA'
ELSE 'NULL'
END
)
FROM Table1 T1
LEFT JOIN Table2 T2
ON T1.number = T2.number
I am stuck in a situation and I need your help.
I have a stored procedure with a select statement which has some joins and many where condition foreach product settings. The structure looks like below.
SELECT *
FROM TABLE1 T1
INNER JOIN T2 ON T1.ID = T2.ID
INNER JOIN T3 ON T1.ID = T3.ID
WHERE T1.STATUS = 'UnResolved'
AND
(
T1.COL1 NOT IN ('X', 'Y', 'Z')
AND (T1.Product != 'TEST1' OR T2.COL2 = 'V2' OR T3.COL3 = 'V3')
AND (T1.Product != 'TEST2' OR T2.COL2 = 'V2' OR T3.COL3 = 'V3')
AND (T1.Product != 'TEST3' OR T2.COL4 = 'V4' OR T3.COL5 = 'V5')
AND (T1.Product != 'TEST4' OR T2.COL4 = 'V4' OR T3.COL5 = 'V5')
)
There are only two fixed possible settings for any product.
Setting 1 : OR T2.COL2 = 'V2' OR T3.COL3 = 'V3'
Setting 2 : OR T2.COL4 = 'V4' OR T3.COL5 = 'V5'
Every time a new product comes in we need to add a new where condition with its respective setting.
Now for the new requirement, we need to automate this process by using any config table.
Can someone please suggest below things
#. structure of table
#. modify select query such that we do not need to modify the existing conditions
#. we also need to take care that existing logic does not break
Many thanks in advance!!
Create table product_config with columns product, type, col1, col2. product should be
foreign key to T1.product.
For every product create row in it. type specifies which of col2, col3 or col4, col5 is used.
product type
TEST1 1
TEST2 1
TEST3 2
TEST4 2
Then query will look like this:
SELECT *
FROM TABLE1 T1
INNER JOIN PRODUCT_CONFIG C ON (T1.PRODUCT = C.PRODUCT)
INNER JOIN T2 ON T1.ID = T2.ID
INNER JOIN T3 ON T1.ID = T3.ID
WHERE T1.STATUS = 'UnResolved'
AND
(
T1.COL1 NOT IN ('X', 'Y', 'Z')
AND (C.TYPE != 1 OR T2.COL2 = 'V2' OR T3.COL3 = 'V3')
AND (C.TYPE != 2 OR T2.COL4 = 'V4' OR T3.COL5 = 'V5')
)
1 solution I have used before is to create a lookup table having your input parameters and the where condition used. For example you could create a table with the following columns:
PRODUCT_NAME
PRODUCT_TYPE
PRODUCT_PRICE
WHERE_CLAUSE
Using this fire a lookup query, say you have the name, type & price:
SELECT WHERE_CLAUSE FROM PRODUCT_CRITERIA WHERE PRODUCT_NAME = :PRODUCT_NAME AND PRODUCT_TYPE = :PRODUCT_TYPE AND PRODUCT_PRICE = :PRODUCT_PRICE
In oracle the WHERE_CLAUSE can be used to execute a dynamic query using 'EXECUTE IMMEDIATE'
I have two SQL SELECT COUNT statements:
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = false AND t2.flag2 = true;
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = true AND t2.flag2 = false;
As can be seen the only difference of these two statements are the flipped condition.
But what I want to do is to combine the two statements into one so that the output becomes one table with two columns, the first column contains the result of the first statement and the second column contains the result of the second statement. Something like:
count1 | count 2
-------------------------
3456 | 9864
I use PostgreSQL by the way. Can someone let me know how to do this?
Many thanks
This should do it for you. I'm not to familiar with PostgreSql but I think it will work.
SELECT
SUM(CASE WHEN t1.Flag1 = false AND t2.flag2 = true THEN 1 ELSE 0 END) Count1,
SUM(CASE WHEN t1.Flag1 = true AND t2.flag2 = false THEN 1 ELSE 0 END) Count2
FROM
table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
If you really need it this way (use two sql queries and combine them) then:
select * from
(SELECT COUNT(*) FROM table1 t1 INNER JOIN table2 t2 ON t2.id = t1.rowid WHERE t1.flag1 = false AND t2.flag2 = true) a,
(SELECT COUNT(*) FROM table1 t1 INNER JOIN table2 t2 ON t2.id = t1.rowid WHERE t1.flag1 = true AND t2.flag2 = false) b
Based on your SQL, this would be better solution:
select
sum (case when not t1.flag1 and t2.flag2 then 1 else 0 end) as count1,
sum (case when t1.flag1 and not t2.flag2 then 1 else 0 end) as count2
FROM
table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
You can also cast boolean type to integer and shorten the sql (true::int = 1, false::int = 0):
select
sum((flag1::int<flag2::int)::int) count1,
sum((flag1::int>flag2::int)::int) count2
from
table1 t1
join table2 t2 ON t2.id = t1.rowid
And because true > false and false < true (at least in PostgreSQL) you can write:
select
sum((flag1 < flag2)::int) count1,
sum((flag1 > flag2)::int) count2
from
table1 t1
join table2 t2 ON t2.id = t1.rowid
Select * from
(
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = false AND t2.flag2 = true) tab1,
(
SELECT COUNT(*) FROM table1 t1
INNER JOIN table2 t2 ON t2.id = t1.rowid
WHERE t1.flag1 = true AND t2.flag2 = false) tab2