Update select for specific cases - sql

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.

Related

SQL how to return '0' if no row is found

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'

How to join a table with another one and then with itself on SQL Server 2017?

I have 2 tables where Table1 (t1) has the main data and Table2 (t2) has the relations between data.
I need a query to get data from table (t1) where condition is like
WHERE t1.row = 1 AND t1.code = s1
But this query started with (t1 left join t2 on t1.row = t2.row) and then produced answer will join on t1 again on t2.trow = t1.row.
Then answer must have some columns and rows which is shown in bottom.
Can you help me with this query?
I wrote this query :
SELECT
t1.code, t1_1.bed, t1_1.bes,
t2.t1row, t2.t2row
FROM
dbo.t1
LEFT OUTER JOIN
dbo.t2 ON t1.row = t2.t1row
LEFT OUTER JOIN
dbo.t1 t1_1 ON t2.t2row = t1_1.row
WHERE
t1.code = s1 And t1.row = '1'
But this query returns 2 rows where I need 5 rows!
I'm not sure why you want to link back to t1, since simply joining t1 with t2 produces the desired result. If you SELECT DISTINCT then two similar rows are replaced by one
SELECT DISTINCT
t1.row,
CASE WHEN trow=1 THEN 'OK' ELSE null END AS t2_row,
t1.bed, t1.bes, t1.code
FROM
t1
LEFT JOIN t2
ON t1.row = t2.frow
WHERE t1.code='s1'
ORDER BY t1.row;
Result:
row t2_row bed bes code
1 10000 s1
2 OK 7500 s1
3 OK 2500 s1
4 20000 s1
5 20000 s1
Use a CASE for t2.trow column and DISTINCT to remove duplicates
SELECT DISTINCT row,
CASE WHEN trow = 1 THEN 'OK'
ELSE ''
END as t2_row,
bed, bes, code
FROM t1
LEFT JOIN t2 ON t1.row = frow
AND code = 's1'
I am thinking that this does what you want:
select t1.*,
(case when exists (select 1
from t2
where t2.frow = t1.row and
t2.frow <> 1
)
then 'OK'
end)
from t1
where t1.code = 's1';

How can I join 3 columns on one table with 1 columns from another table?

I have a table (Table1) with 5 columns, each result shows an ID for a timezone (TZID). In a seperate table (Table2) is a list of these IDs, with the corresponding name for them. I need to join them so as that for each column result, it shows the corresponding name for them. But I can only seem to figure out how to join for the result of 1 column. For example:
Table1 joined with Table2
Here I have joined Column3 with TZID from table 2. But if Column3 is equal to zero, and Column 1 or 2 is not, I need TZID from table2 to return that corresponding name from Table2.
Currently I have the following:
SELECT
Column1
,Column2
,Column3
,Table2.TZID as 'TZID from Table2'
,Table2.[DESCRIPT] as 'Name from Table2'
FROM Table1
left outer join Table2 on Table2.TZID=Table1.Column3
I have tried using REPLACE, is it possible to replace with the reult from another table? Something like
REPLACE(Column1, Table2.TZID, Table2.[DESCRIPT]) AS 'Column1 Mask'
Is there any way to actually do this?
I think you want to join with priorities, first join with Column3 if it is not 0. If Column3 is 0 then join with Column1. And if column 1 is also 0 then join with Column2, right?
If this is correct, then you need a sql query like this:
SELECT
Column1
,Column2
,Column3
,Table2.TZID as 'TZID from Table2'
,Table2.NAME as 'Name from Table2'
FROM Table1
LEFT OUTER join Table2 on Table2.TZID =
CASE
WHEN Table1.Column3 <> 0
THEN Table1.Column3
WHEN Table1.Column1 <> 0
THEN Table1.Column1
WHEN Table1.Column2 <> 0
THEN Table1.Column2
END
If you need to join all tree columns in one query, you can join one table multiple times and rename it.
> SELECT
> Column1
> ,Column2
> ,Column3
> ,t2c1.TZID as 'TZID Column1'
> ,t2c1.NAME as 'Name Column1'
> ,t2c2.TZID as 'TZID Column2'
> ,t2c2.NAME as 'Name Column2'
> ,t2c3.TZID as 'TZID Column3'
> ,t2c3.NAME as 'Name Column3'
>
> FROM Table1 LEFT OUTER join Table2 t2c1 on t2c1.TZID = Table1.Column1
> LEFT OUTER join Table2 t2c2 on t2c2.TZID = Table1.Column2
> LEFT OUTER join Table2 t2c3 on t2c3.TZID = Table1.Column3

Update A table with Join and Computed Column

i have 2 tables of the following structure
Table1
Id(long), Name(nvarchar), ValuesExist(bit)
Table2
Id(long), Table1Id(long), Value(int)
with foreign key constraint on Table.Id and Table2.Table1Id
Now i want to update Table1 according to the following logic
if (there are values in Table2 corresponding to a row Table1 AND Atleast one the values is > 0 )
then Table1.ValuesExist = 1
else Table1.ValuesExist = 0
i have looked and tried many examples given on SO abt how to update a column using join but cudnt find any example in which updation is being done through logic or some ComputedColumn
UPDATE T1
SET ValuesExist =
CASE
WHEN T2.Value > 0 THEN 1
ELSE 0
END
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.Id = T2.Table1Id
Here is one method. It uses a correlated subquery in the update and is very close to how you stated the problem:
update table1 t1
set ValuesExist = (case when exists (select 1
from Table2 t2
where t2.Table1Id = t1.Id and t2.Value > 0
)
then 1 else 0
end);
This will perform best if you have an index on Table2(Table1Id, Value).

How do I add a column derived from a select statement within a select statement?

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'