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
Related
I would like to add the count result of a 2nd query to the result set which queries the 1st table and connect this subquery with the ID of the 1st Table result. This simplified code explains it:
Select
ID_Field_Table1,
(Select Count(x)
From Table2
Where ID_Field_Table2 = ID_Field_Table1) As mycount
From Table1
What is the correct syntax?
Thanks
This code is simplified but the construction is the same. In my DB the ID_Field_Table2 and ID_Field_Table1 have the same name (let's say ID_Field). If I use this same Name, the SubQuery goes like "...Where ID_Field = ID_Field.." and this always Returns a Reslut, because it is not connecting the queries ("Select a Where x = x" returns any record in the table 2).
Select
ID_Field AS ID1,
(Select Count(x)
From Table2
Where ID_Field = ID1) As mycount
From Table1
It just returns an error, saying that ID1 does not exist.
When I use the original name of the columns (which are the same), the result is wrong
When I us an alias, an error occurs
So I think the query is wrong at all.
Well, you can't use an alias defined in the select clause, but you can use the aliases defined in the from clause:
Select
ID_Field AS ID1,
(Select Count(x)
From Table2
Where ID_Field = t1.ID_Field) As mycount
From Table1 t1
You can also do it without an alias, since the sub query is for a different table:
Select
ID_Field AS ID1,
(Select Count(x)
From Table2
Where ID_Field = Table1.ID_Field) As mycount
From Table1
However, I suspect a query using left join to a derived table as suggested in esta's answer would have better performance.
Something like this?
Select
Table1.ID_Field_Table1,
T2.MYCOUNT
From Table1
LEFT JOIN (SELECT ID_Field_Table2, COUNT(x) AS MYCOUNT FROM TABLE2 GROUP BY ID_FIELD_TABLE2) T2 ON T2.ID_Field_Table2=Table1.ID_Field_Table1
Try This query once it may help you.
Select ID_Field_Table1,COUNT_NBR
cross apply
(
Select Count(x) as COUNT_NBR
From Table2
Where ID_Field_Table2 = ID_Field_Table1
group by ID_Field_Table1
) As mycount
From Table1
I searched in SO but couldn't find anything for my purpose. I need to insert unique rows ONLY from one table into another. I have:
table1
id name bookid bookname start_date end_date rel_date rel_id
1 horror 1221 rockys 04/01/2016 04/30/2016 05/01/2016 4545
2 horror 1331 elm 04/01/2016 04/30/2016 05/01/2016 5656
table2
id name bookid bookname start_date end_date rel_date rel_id
1 horror 1221 rockys 04/01/2016 04/30/2016 05/01/2016 4545
2 horror 1441 elm 04/01/2016 04/30/2016 05/01/2016 5656
I need to insert into table1 the row with id = 2 in table2 AND also delete the row with id = 2 from table1, because bookid is different even though the rest of the columns match.
I tried following:
insert into table1
select * from table2
where not exists (select * from table2 where table1.id = table2.id
and table1.name = table2.name and table1.bookid = table2.bookid and
table1.bookname = table2.bookname and table1.start_date = table2.start_date
and table1.end_date = table2.end_date and table1.rel_date = table2.rel_date
and table1.rel_id = table2.rel_id)
Any way I can do all of this in one sql block?
In theory the following merge statement should achieve what you are looking for.
MERGE table1 [Target]
USING table2 [Source]
ON ([Target].[name] = [Source].[name]
AND
[Target].[bookname] = [Source].[bookname]
AND
[Target].[start_date] = [Source].[start_date]
AND
[Target].[end_date] = [Source].[end_date]
AND
[Target].[rel_date] = [Source].[rel_date]
AND
[Target].[rel_id] = [Source].[rel_id]
)
WHEN MATCHED AND ([Target].[bookid] <> [Source].[bookid]) THEN
UPDATE
SET [Target].[name] = [Source].[name]
,[Target].[bookid] = [Source].[bookid]
,[Target].[bookname] = [Source].[bookname]
,[Target].[start_date] = [Source].[start_date]
,[Target].[end_date] = [Source].[end_date]
,[Target].[rel_date] = [Source].[rel_date]
,[Target].[rel_id] = [Source].[rel_id]
WHEN NOT MATCHED THEN
INSERT(
[name]
,[bookid]
,[bookname]
,[start_date]
,[end_date]
,[rel_date]
,[rel_id]
)
VALUES
(
[Source].[name]
,[Source].[bookid]
,[Source].[bookname]
,[Source].[start_date]
,[Source].[end_date]
,[Source].[rel_date]
,[Source].[rel_id]
);
Note that there are some risks and limitations to this approach. If your [id] column has a uniqueness constraint, then it should be set as an identity column otherwise you will run into uniqueness violation errors. Also if [id] column value in table1 is different to [id] column in table2 then merge statement will keep the original [id] value from table1.
Basically this query simply updates your existing record in table1 with the matching record in table2 and insert new records from table2 into table1 if they don’t already exists.
All you should need to achieve your objective is this:
UPDATE T1
SET T1.bookid = T2.bookid
FROM Table1 T1
JOIN Table2 T2
ON T1.ID = T2.ID
However, to answer the question exactly as it was asked:
DELETE T1
FROM Table1 T1
JOIN Table2 T2
ON T1.ID = T2.ID
AND T1.bookid <> T2.bookid
INSERT INTO Table1
SELECT id, name, bookid, bookname, start_date, end_date, rel_date, rel_id
FROM Table2 T2
LEFT OUTER JOIN Table1 T1
ON T1.ID = T2.ID
AND T1.bookid = T2.bookid
WHERE T1.id IS NULL
Note that if your ID fields aren't unique, you'll need to add other conditions to the ON clauses.
If you are just concerned about updating the bookid value from table2, you can change the value of bookid with the below query
UPDATE t1 SET t1.bookid = t2.bookid
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.id
If you think your id column is not unique in two tables, you might need to consider adding other matching columns in the JOIN.
I have written the below query. I do not think it is the optimum way.
The scenario is - given a child, I want to fetch all rows corresponding to its parent(root).
select * from TableA where column_root =
(select column_root from TableA where column_child = 123)
You can use JOIN:
select T1.* from
TableA T1 join
TableA T2 ON T1.column_root=T2.column_root
where T2.column_child = 123
Sample result in SQL Fiddle
I have an sql query like this
Select col1, (select abc from table2 where def=1) as col2
From Table1 inner join table3 on Table1.id = table3.id
Where col2 = 4
The problem is that the where condition doesn't work. I get an error saying
Invalid column name 'col2'
Kindly help me fix this sql query.
Thanks in advance
You can define it in a CROSS APPLY and then reference in the SELECT and WHERE
SELECT col1,
col2
FROM Table1
INNER JOIN table3
ON Table1.id = table3.id
CROSS APPLY (SELECT abc
FROM table2
WHERE def = 1) C(col2)
WHERE col2 = 4
Using a CTE (Common Table Expression):
WITH SubQuery AS (Col2) {
SELECT
ABC
FROM
table2
WHERE
def = 1
}
SELECT
T.Col1,
S.Col2
FROM
SubQuery S,
Table1 T
INNER JOIN table3 t3
ON T.id = t3.id
WHERE
S.Col2 = 4
Although I must say I agree with the first comment - this makes no sense since your subquery is not correlated (joined) to the rest of your query...
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. )