how can I update a column of my table1 with this query?
update table1
set table1.column5 = (
select count(*)
from table2, table1
where table1.column1 = table2.column4
group by table1.column1)
table1 has these columns (column1, column2, column3, column4, column5)
table2 has these columns (column1, column2, column3, column4)
and table2.column4 is foreign key of table1.column1
Use This
UPDATE T1
SET
column5 = COUNT(1)
FROM table2 T2
INNER JOIN table1 T1
ON T1.column1 = T2.column4
GROUP BY T2.column4
Or This
;WITH CNT
AS
(
SELECT
column4,
Cnt = COUNT(1)
FROM table2 T2
GROUP BY T2.column4
)
update t1
SET
column5 = CNT.Cnt
FROM CNT
INNER JOIN table1 T1
ON CNT.column4 = T1.column1
Try this query
with cte as (
select column4, cnt = count(*)
from table2
group by column4
)
update a
a.column5 = b.cnt
from
table1 a
join cte b on a.column1 = b.column4
Related
I have 3 tables
Table1:
emp_id, code_1, code_2
Table2:
code_1, code_2
Table3:
emp_id, emp_ind
Table2 is a lookup table. I need to update Table3 checking code_1 and code_2 of Table1 present in Table2.
If code_2 in Table2 is null, then check if code_1 in Table1 and Table2 match, if yes update emp_ind in Table3 as Y.
If code_1 in Table2 is null, then check if code_2 in Table1 and Table2 match, if yes update emp_ind in Table3 as Y.
If code_1 and code_2 both are valued in Table2, check if both code1 and code2 in Table1 match with that of Table2, if yes update emp_ind in Table3.
Is there a way to do it simply instead of checking like below:
Update table_3 t3
Set t3.emp_ind = 'Y'
Where exists (
Select 1 from table1 t1
Inner Join table2 t2
on t1.code_1 = t2.code_1
Where t2.code_2 is null
And t2.emp_id= t3.emp_id
Union
Select 1 from table1 t1
Inner Join table2 t2
on t1.code_2 = t2.code_2
Where t2.code_1 is null
And t2.emp_id= t3.emp_id
Union
Select 1 from table1 t1
Inner Join table2 t2
on t1.code_1 = t2.code_1
And t1.code_2 = t2.code_2
Where t2.emp_id= t3.emp_id
)
You can combine the conditional joins using OR operator like this:
Update table_3 t3
Set t3.emp_ind = 'Y'
Where exists (
Select 1 from table1 t1
Inner Join table2 t2
on
(t1.code_1 = t2.code_1 AND t2.code_2 is null)
OR (t1.code_2 = t2.code_2 AND t2.code_1 is null)
OR (t1.code_1 = t2.code_1 AND t1.code_2 = t2.code_2)
Where t2.emp_id= t3.emp_id
)
Example:
Table 1:
Column1 Column2
----------- -------------
A 1
B 2
D 3
E 4
Table 2:
Column3 Column4
----------- -------------
A 7
E 9
Z 5
Expected output:
Column1 Column2 Column3 Column4
----------- ------------- ------------- -------------
A 1 A 7
B 2 E 9
D 3 Z 5
E 4 NULL NULL
I want the output as shown in the picture.
If there are two tables with the columns Column1, Coumn2 and Column3, Column4,
then the expected output should be Column1, Column2, Column3, Column4, without any joins. It should have Table2's columns to the right hand side of the Table1's columns. NULL values will consume the empty rows if the number of rows in each table don't match.
You can use ROW_NUMBER window function to create a calculated field that can be used to join the two tables together:
SELECT t1.Column1, t1.Column2, t2.Column3, t2.Column4
FROM (
SELECT Column1, Column2,
ROW_NUMBER() OVER (ORDER BY Column1) AS rn
FROM Table1) AS t1
FULL OUTER JOIN (
SELECT Column3, Column4,
ROW_NUMBER() OVER (ORDER BY Column3) AS rn
FROM Table2) AS t2
ON t1.rn = t2.rn
A FULL OUTER JOIN is necessary in case either Table1 or Table2 has more rows.
This would work:-
SELECT Column1, Column2, Column3, Column4 FROM
(SELECT ROW_NUMBER() OVER(ORDER BY Column1) row, Table1.*
FROM Table1) t1
FULL OUTER JOIN (SELECT ROW_NUMBER() OVER(ORDER BY Column3) row, Table2.*
FROM Table2) t2
ON t1.row = t2.row
SQLFIDDLE
Alternatively, you could also do a left join instead of full outer join:
SELECT Column1
,Column2
,t.Column3
,t.Column4
FROM (
SELECT ROW_NUMBER() OVER (
ORDER BY Column1
) rn
,Table1.*
FROM Table1
) t1
LEFT JOIN (
SELECT ROW_NUMBER() OVER (
ORDER BY Column3
) AS rn
,t2.*
FROM Table2 t2
) t ON t1.rn = t.rn;
SQL Fiddle Demo
Note: Ofcourse, this is only going to work if you have more records in TableA.
The simplest way is using CROSS JOIN
SELECT t1.FIELD_A, t2.FIELD_B, t1.FIELD_C, t2.FIELD_D, t2.FIELD_E
FROM tbl01 t1
CROSS JOIN
tbl02 t2
Having 2 tables with the same structure, like this SQLFiddle, is it possible to build a SQL statement that compares the values of the columns of both tables (where id is the unique key), and return a list of the change columns in the format:
columnname, oldvalue, newvalue
Where oldvalue is the value in Table1 and newvalue is the value in Table2.
You can do something like this:
SELECT T1.Id
,'Name' AS ColumnName
,CAST(T1.name AS VARCHAR(MAX)) AS OldValue
,CAST(T2.name AS VARCHAR(MAX)) AS NewValue
FROM Table1 AS T1
FULL OUTER JOIN Table2 AS T2
ON T1.id = T2.id
UNION
SELECT T1.Id
,'Amount'
,CAST(T1.amount AS VARCHAR(MAX))
,CAST(T2.amount AS VARCHAR(MAX))
FROM Table1 AS T1
FULL OUTER JOIN Table2 AS T2
ON T1.id = T2.id
You need to use a MERGE statement , please note it is only available from SQL 2008 onwards
here is an example
MERGE Production.ProductInventory AS target
USING (SELECT ProductID, SUM(OrderQty) FROM Sales.SalesOrderDetail AS sod
JOIN Sales.SalesOrderHeader AS soh
ON sod.SalesOrderID = soh.SalesOrderID
AND soh.OrderDate = #OrderDate
GROUP BY ProductID) AS source (ProductID, OrderQty)
ON (target.ProductID = source.ProductID)
WHEN MATCHED AND target.Quantity - source.OrderQty <= 0
THEN DELETE
WHEN MATCHED
THEN UPDATE SET target.Quantity = target.Quantity - source.OrderQty,
target.ModifiedDate = GETDATE()
OUTPUT $action, Inserted.ProductID, Inserted.Quantity, Inserted.ModifiedDate, Deleted.ProductID,
Deleted.Quantity, Deleted.ModifiedDate;
GO
you can learn more about merge's here SQL merge
if you only want rows with differences:
SELECT COALESCE(T1.Id, T2.Id) Id
,'Name' AS ColumnName
,CAST(T1.name AS VARCHAR(MAX)) AS OldValue
,CAST(T2.name AS VARCHAR(MAX)) AS NewValue
FROM Table1 AS T1
FULL OUTER JOIN Table2 AS T2
ON T1.id = T2.id
WHERE COALESCE(T1.name,'**') != COALESCE(T2.name ,'**')
UNION ALL
SELECT COALESCE(T1.Id, T2.Id) Id
,'Amount' AS ColumnName
,CAST(T1.Amount AS VARCHAR(MAX)) AS OldValue
,CAST(T2.Amount AS VARCHAR(MAX)) AS NewValue
FROM Table1 AS T1
FULL OUTER JOIN Table2 AS T2
ON T1.id = T2.id
WHERE COALESCE(T1.Amount,0) != COALESCE(T2.Amount,0)
I'm wondering whether I can use EXISTS (or something similar) in column like this:
SELECT Column1,
Column2,
EXISTS (SELECT 1 FROM Table2 T2 WHERE T2.Column = T1.Column) AS IsFlag
FROM Table1
I know I can do something similar with Count()
SELECT Column1,
Column2,
(SELECT Count(*) FROM Table2 T2 WHERE T2.Column = T1.Column) AS IsFlag
FROM Table1
But that might not be very efficient when Table2 is large
Try this
SELECT Column1,
Column2,
CASE WHEN EXISTS (SELECT 1 FROM Table2 T2
WHERE T2.Column = T1.Column) then 1 ELSE 0 END AS IsFlag
FROM Table1
CASE
WHEN
EXISTS (SELECT 1 FROM Table2 T2 WHERE T2.Column = T1.Column)
THEN 1
ELSE 0
END AS IsFlag
I need to build an SQL statement to delete from certain table the records that match another select statement.
In Teradata we use
delete from table1
where (col1, col2) in (
select col1,col2
from table2
)
While in SQL Server it's not allowed to have more than 1 column in the WHERE..IN clause. I thought I can use the WITH clause:
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete from table1
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
How to use WITH..DELETE clause? Is there another way?
This should do it:
DELETE Table1
from Table1 t1
inner join tempTable t2
on t2.Col1 = t1.Col1
and t2.Col2 = t1.Col2
First build a query that selects the rows you need:
SELECT t1.*
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col2]=t2.[Col2]
Test it to make sure it returns exactly the rows you want to delete. Then turn it into a delete statement by changing the "SELECT" to "DELETE" and removing the column list:
DELETE t1
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col
delete from table1 t1 where exists
(
select 1 from table2 t2 where t1.col1 = t2.col1 and t1.col2 > t2.col2
)
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete table1 from tempTable
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
This works for me
WITH CTE AS
(
SELECT TOP 50000 *
from v020101hist order by data
)
DELETE FROM CTE