I'm trying write a routine in SQL Server that, when run, would traverse specified tables and, if a specific column contains a value, update another value. In pseudo code:
select * from table1
if column1 = true
{
update table2.column1 with value where table2.column2.value = table1.column2.value
}
Basically, traverse table1 and if the value in a specific column is true, update the value of another table's column1 where that row's column2 matches table1's column2
Thanks
You don't need the IF, just use a WHERE clause:
UPDATE T2
SET t2.Column1 = 'blah'
FROM Table2 t2
INNER JOIN Table1 t1
ON t1.value = t2.value
WHERE t1.column1 = 'True'
Not sure I fully understand your requirement, but if you want update all the values using a single update statement this might do:
update table2 set column1 =
(select column1 from table1 t1
where t1.column2 = table2.column2
)
where exists
(select * from table1 t1
where t1.column2 = table2.column2 and t1.column1 = true
)
It could be written to avoid having the 2nd subselect (the EXISTS clause) but the solution is rather dialect-specific. This one is, I believe, more likely to be accepted in an unknown dialect. (Except for the word "true" ... substitute the value you want, there. )
Related
I have a piece of code on plpgsql like that:
UPDATE table1
SET column1 = value1
FROM table1 tbl
INNER JOIN table2 tbl2 ON tbl2.id = tbl.id
WHERE table2.code = 200
AND table1.id = tbl.id;
Here table1 and alias tbl are two different table due to postgress specification.
Now I want to write the same procedure for SQL Server, but this code fails with error
[S0001][4104] The multi-part identifier "table1.id" could not be bound.
How should I rewrite this code for SQL Server?
This is simpler in SQL Server, because the UPDATE can reference an alias in the FROM. There is no need to JOIN back to the original table.
So:
UPDATE tbl
SET column1 = value1
FROM table1 tbl JOIN
table2 tbl2
ON tbl2.id = tbl.id
WHERE tbl2.code = 200;
This assumes that id is the primary key of table1 (a reasonable assumption).
You could use common table expression:
WITH cte AS (
SELECT tbl.column1
FROM table1 tbl
JOIN table2 tbl2 ON tbl2.id = tbl.id
WHERE tbl2.code = 200
)
UPDATE cte SET column1 = value1;
-- SELECT * FROM cte
By highlighting and running only select statement inside cte you could check the result before doing actual update.
db<>fiddle demo
I need to update values in a table from another table and if they don't exist it must be inserted. So I saw this example in here
UPDATE Table1 SET (...) WHERE Column1='SomeValue'
IF ##ROWCOUNT=0
INSERT INTO Table1 VALUES (...)
Now I would like to do this but instead of a where clause with a value i need to check if columns match on another table.
Something like
UPDATE t1
SET
t1.status = t2.status
FROM
table1 t1, table2 t2
WHERE t1.reference = t2.reference and t1.section = t2.section
I assume this is very bad in terms of performance and i would like to hear some other suggestions.
EDIT
Also please, if you can, i would like to hear why the approach you give is better than using a merge or a join for example. Much appreciated.
RESULT
Here is the approach i went for after checking how bad merge performance is compared to an update then insert and trying to test everyones approach this is what i decided for, basically uses a bit of everyone's answer
UPDATE C
SET
C.ConsumoWeek01 = M.ConsumoWeek01
FROM
Consumos AS C
INNER JOIN #tempTable M
ON C.Referencia = M.Referencia
AND C.UAP = M.UAP
INSERT INTO
Consumos
SELECT *
FROM #tempTable M
WHERE NOT EXISTS
(
SELECT 1 FROM Consumos C
WHERE C.Referencia = M.Referencia
AND C.UAP = M.UAP
)
Try this
UPDATE t1
SET
t1.status = t2.status
FROM
table1 t1
WHERE NOT EXISTS (SELECT 1 FROM table2 t2
WHERE t1.reference = t2.reference
and t1.section = t2.section )
use not exists
UPDATE t1
SET
t1.status = t2.status
FROM
table1 t1 where not exists( select 1 from table2 t2 where t1.=ref=t2.ref and t1.section=t2.secction)
Use merge statement:
MERGE INTO Table1 T1
USING
(
SELECT * FROM Table2
) T2
ON
(
T1.reference = T2.reference AND
T1.section = T2.section
)
WHEN MATCHED THEN
--UPDATE STATEMENT
WHEN NOT MATCHED THEN
--INSERT STATEMENT
Your method is fine just use standard explicit join syntax instead of old style with comma separate :
update t1
set . . .
from table t1 inner join
table t2
on t1.reference = t2.reference and t1.section = t2.section;
My data looks like this: same PolicyNumber can have different ClassCode. So how to eliminate all rows that contain PolicyNumber PACA1000101-00 if at least one ClassCode choosen to be NOT IN
So if I say WHERE ClassCode <> 01183 I want all those records not showing up in a result set.
Use a not exists and a correlated subquery?
Select *
from table T1
where not exists (Select 1
from table T2
where T1.PolicyNumber = T2.PolicyNumber
and classCode = 01183)
Another way to do this if you had to join to a 2nd table with different values and you needed values from that table....
SELECT T1.*, T2.*
FROM table T1
LEFT JOIN (Select *
from table T2
classCode = 01183)
on T1.PolicyNumber = T2.PolicyNumber
WHERE T2.PolicyNumber is null
This says join the table to itself, but only include records on the right side which have a class code of 01183. Then the where clause says exclude all policy numbers which have at least 1 occurrence of class code 01183.
First of all, I don't know if the title is right but let me show you what I want and I will correct it as suggested.
So, I have 2 tables:
table1
ID, subid, name
table2
ID
What I want is to delete any element from table2 that has ID equal to subid in table1, where table1.name is equal to a specified value.
If I have these elements in table1
ID subid name
1 ... 1 ...... name1
2 ... 3 ...... name2
3 ... 2 ...... name1
4 ... 1 ...... name2
and these rows in table2
ID
1
2
3
4
I would like to remove those elements in table2 with ID = subid, when name = name1, which means elements 1 and 2.
Something like:
DELETE FROM table2
WHERE ID = (SELECT subid
FROM table1
WHERE NAME = "name1")
Is this possible?
You were very close.
You just need = ANY rather than = as the subquery can return more than one row SQL Fiddle.
DELETE
FROM table2
WHERE ID = ANY (SELECT t1.subid
FROM table1 t1
WHERE t1.name = 'name1')
Though this is more commonly expressed using IN
DELETE
FROM table2
WHERE ID IN (SELECT t1.subid
FROM table1 t1
WHERE t1.name = 'name1')
A couple of other changes I made to your posted query...
I always ensure that column references in subqueries use two part names to avoid unfortunate surprises.
You should use single quotes to delimit string literals so it works under default QUOTED_IDENTIFIER settings and is not interpreted as referencing a column called name1.
You can delete using joins as well, so yup very possible.
You can identify the (to be) deleted records first with:
select t2.*
from table2 t2
inner join table1 t1 on t2.id = t1.subId
and t1.name = 'whatever'
then perform the delete as such:
delete t2
from table2 t2
inner join table1 t1 on t2.id = t1.subId
and t1.name = 'whatever'
#eckes see my fiddle with the syntax that I'm using to see it works: http://sqlfiddle.com/#!6/260a5
I'm wondering if there's any way to optimize the following SELECT query. (Note: I typed this when writing my question for nonexistent tables and I might not have the correct syntax.)
The goal is, if Table2 contains any related rows I want to set the value of the third column to the number of related rows in Table2. Otherwise, if Table3 contains any related rows I want to set the column to the number of related rows in Table3. Otherwise, I want to set the column value to 0.
SELECT Id, Title,
CASE
WHEN EXISTS (SELECT * FROM Table2 t2 WHERE t2.RelatedId = Table1.Id) THEN
(SELECT COUNT(1) FROM Table2 t2 WHERE t2.RelatedId = Table1.Id)
WHEN EXISTS (SELECT * FROM Table3 t3 WHERE t3.RelatedId = Table1.Id) THEN
(SELECT COUNT(1) FROM Table3 t3 WHERE t3.RelatedId = Table1.Id)
ELSE 0
END AS RelatedCount
FROM Table1
I don't like the fact that I'm basically performing the same query twice (in two cases). Is there any way to do what I want while only performing the query once?
Note that this is part of a much larger query with multiple JOINs and UNIONs so it's not easy to take a completely different approach.
This query should perform much better. You are not just performing the same query twice; since they are correlated subqueries, they will run once per row.
SELECT Id, Title,
coalesce(t2.Count, t3.Count, 0) AS RelatedCount
FROM Table1 t
left outer join (
SELECT RelatedId, count(*) as Count
FROM Table2
group by RelatedId
) t2 on t1.Id = t2.RelatedId
left outer join (
SELECT RelatedId, count(*) as Count
FROM Table3
group by RelatedId
) t3 on t1.Id = t3.RelatedId