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
Related
This is my sql:
select
a.column1,
b.column2
from table1 a inner join table2 b
on a.column8 = b.column9
where b.column5 = '2018'
and b.column6 = 'G1';
Problem: a.column1/table1 holds 250000 rows, and b.column2/table2 holds only 153000 rows.
How can this sql be changed to reply 250000 rows, and print '0' in b.column2/table2 when row is not found?
You want a left join:
select t1.column1, coalesce(t2.column2, 0) column2
from table1 t1
left join table2 t2
on t2.column9 = t2.column1
and t1.column5 = '2018'
and t1.column6 = 'G1';
This selects all rows from table1, even if there is no match in table2 - in which case output column t2.column2 will be null, which we we turn to '0' with coalesce().
PS: if t2.column2 is not a number but a string, then use coalesce(t2.column2, '0') instead (note the single quotes).
select
a.column1,
COALESCE ( b.column2, 0)
from table1 a LEFT join table2 b
on a.column8 = b.column9
where b.column5 = '2018'
and b.column6 = 'G1';
You need to use LEFT JOIN
coalesce will replace NULL values with 0
Use LEFT JOIN :
SELECT T1.COL1, COALESCE(T2.COL2, 0)
FROM T1 LEFT JOIN
T2
ON T1.COL8 = T2.COL9 AND T2.COL5 = 2018 AND T2.COL6 = 'G1'
I have a big database with hundreds of tables. So I made a select that gives me the data I need. I now want to update a value from one column for all the rows depending on the circumstances.
I know it's something to do with UPDATE and SET for the cases and stuff but I don't grasp the exact syntax. I have a problem accessing the specific column.
SELECT *
FROM Table1
LEFT JOIN Table2 on Table1.ID=Table2.ID
LEFT JOIN Table3 on Table2.Item = Table3.Item
WHERE Table3.Item in (SELECT ChildItem
FROM Table4
WHERE Item=1000)
So this is the select Statment for all the columns. Now in one of the tables there is a column named columnA.
When ColumnB=0 and ColumnC<> 0 then ColumnA should be 1
When ColumnB<>0 and ColumnC=0 then ColumnA Should be 0
Else Column A Should not be changed.
To prevent unnecessary updates put the condition Else Column A Should not be changed in the WHERE clause:
UPDATE Table1
SET ColumnA = CASE
WHEN ColumnB = 0 and ColumnC <> 0 THEN 1
WHEN ColumnB <> 0 and ColumnC = 0 THEN 0
END
FROM Table1
LEFT JOIN Table2 ON Table1.ID = Table2.ID
LEFT JOIN Table3 ON Table2.Item = Table3.Item
WHERE Table3.Item IN (
SELECT TABLE4.ChildItem
FROM Table4
WHERE TABLE4.Item = 1000
)
AND ((ColumnB = 0 and ColumnC <> 0) OR (ColumnB <> 0 and ColumnC = 0))
You must qualify the columns ColumnA, ColumnB and ColumnC with the table's name.
I think you want something like this:
UPDATE Table1
SET COLUMNA = (CASE WHEN ColumnB=0 and ColumC <> 0 THEN 1 ELSE 0 END)
FROM Table1 LEFT JOIN
Table2
ON Table1.ID = Table2.ID LEFT JOIN
Table3
ON Table2.Item = Table3.Item
WHERE Table3.Item IN (SELECT TABLE4.ChildItem
FROM Table4)
WHERE TABLE4.Item = 1000
);
I am guessing that TABLE1 is the table to be updated.
Your description of the value for COLUMNA does not cover all possibilities. You also LEFT JOIN to TABLE3, but the WHERE clause turns this into an INNER JOIN.
I have two tables that I want to join.
The case is in table 1 the default value is 1 then in table 2 the default value is 0
Table 1 Table 2
-------- ---------
1 0
1232342 1232342
1241232 1231231
I want to join table 1 and table 2 with condition that if table 2 is 0 then it will be replaced to 1.
SELECT T1.ID
FROM TABLE1 T1, TABLE2 T2
WHERE T1.ID = REPLACE(CASE WHEN T2 = 0 THEN 1 ELSE T2.ID END, 'X', 'E')
with this statement it does not return the other id's that are not 0 or 1
expected output
Table 1
--------
1
1232342
Use a join with a CASE. replace() is for string values:
select t1.*
from table1 t1
join table2 t2 on t1.id = case when t2.id = 0 then 1 else t2.id end;
use case when and sub-query
select t1.* from table1 t1 join
(
select case when t2.id=0 then 1 else t2.id end as id from table2 t2
) as t3 on t1.id=t3.id
Try using case when :
SELECT *
FROM TABLE1 T1 inner join TABLE2 T2
on T1.ID = (CASE WHEN T2.ID =0 THEN 1 ELSE T2.ID END)
Switch to modern, explicit JOIN syntax. Skip the case expression, simply use AND/OR instead:
SELECT T1.ID
FROM TABLE1 T1
JOIN TABLE2 T2
ON T1.ID = T2.ID OR (T1.ID = 1 and T2.ID = 0)
Or use INTERSECT:
SELECT ID FROM TABLE1
INTERSECT
SELECT case when ID = 0 then 1 else id end from TABLE2
Using SQL Server 2008
Objective: Select a series of columns from table1 to insert into table2
Issue: In table2 there is one additional column that needs to be inserted that can be derived from a join between table1 and table 3
Current Code
SELECT
table1.name,
table1.email,
table1.phone,
CASE WHEN table1.status = 'active' THEN 1 ELSE 0 END AS Active,
CASE WHEN table1.group_id = 3 THEN 5 ELSE table1.group_id END AS RoleId,
(SELECT
table3.UserID AS ParentID
FROM
table3
INNER JOIN
table1 ON
table3.ID = table1.table3_ID)
FROM
table1
WHERE
table1.group_id = 3 AND
table1.status = 'active'
Currently this code does not work and returns "Subquery returned more than 1 value" error.
I am aware this may not be the correct way to use a nested select, what would be the correct way to do this?
Additional data can be provided if necessary.
Thank you in advance.
The problem is that you want a correlated subquery. That means that you need to remove table1 from the subquery:
SELECT table1.name, table1.email, table1.phone,
(CASE WHEN table1.status = 'active' THEN 1 ELSE 0 END) AS Active,
(CASE WHEN table1.group_id = 3 THEN 5 ELSE table1.group_id END) AS RoleId,
(SELECT table3.UserID
FROM table3
WHERE table3.ID = table1.table3_ID
) as ParentID
FROM table1
WHERE table1.group_id = 3 AND table1.status = 'active';
If there is more than one possible match in table3, then you will need something like select top 1 table3.UserId or select max(table3.UserId).
You could probably solve the more than 1 value error by adding a TOP 1 to the 'select .. from table ' part of the select. But it may be easier to just inner join them.
SELECT
table1.name,
table1.email,
table1.phone,
CASE WHEN table1.status = 'active' THEN 1 ELSE 0 END AS Active,
CASE WHEN table1.group_id = 3 THEN 5 ELSE table1.group_id END AS RoleId,
table3.UserID
FROM table1
INNER JOIN table3 ON
table3.ID = table1.table3_ID
WHERE
table1.group_id = 3 AND
table1.status = 'active'
If you really (really really really) want to use subquery instead of join your code is quite well. You should change your subquery's join as below.
SELECT
table1.name,
table1.email,
table1.phone,
CASE WHEN table1.status = 'active' THEN 1 ELSE 0 END AS Active,
CASE WHEN table1.group_id = 3 THEN 5 ELSE table1.group_id END AS RoleId,
(SELECT
table3.UserID
FROM
table3
WHERE
table3.ID = table1.table3_ID) AS ParentID
FROM
table1
WHERE
table1.group_id = 3 AND
table1.status = 'active'
Apart from this I put an alias ParentID outside the subquery.
Please consider below code with table aliases. It's good practice to use it because the code is more readable.
SELECT
t1.name,
t1.email,
t1.phone,
CASE WHEN t1.status = 'active' THEN 1 ELSE 0 END AS Active,
CASE WHEN t1.group_id = 3 THEN 5 ELSE t1.group_id END AS RoleId,
(SELECT
table3.UserID
FROM
table3 t3
WHERE
t3.ID = t1.table3_ID) AS ParentID
FROM
table1 t1
WHERE
t1.group_id = 3 AND
t1.status = 'active'
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