How to restore SQL data from one table to another - sql-server

I have a backup table with 15,000 rows. The data was directly copied from a main table. I need to perform an UPDATE statement on the main table, using the data from the backup table. Both tables are identical in structure and use a unique primary key called ID.
How do I loop through the backup table, find the matching record for each row in the main table, and then replace each record in main table with the matching record in the backup table?
Thanks
EDIT:
Proposed Solution based on Sean Lange's comment:
UPDATE a
SET a.col1 = b.col1
, a.col2 = b.col2
FROM table1 a
INNER JOIN table2 b
ON a.id = b.id

You can use a JOIN update to accomplish this. Assuming they have matching primary key ID's, it should be quick and painless.
UPDATE table1
SET a.col1 = b.col2
, a.col2 = b.col2
FROM table1 a
INNER JOIN table2 b
ON a.id = b.id

Related

Efficiently group query by one column, taking the maximum of another column and a third column that comes from the same row as the maximum column

I have a table of 100,000,000+ values, so efficiency is very important to me. I need to take information from table A, join it to an index table B, then join to table C using the index retrieved from table B. The problem is, there are multiple indexes for each value in table A, and I want to retrieve the one with the most recent date.
The query below creates duplicates:
SELECT ID_1, ID_2, Date
INTO #DEST_TABLE FROM Table_1 t1
INNER JOIN Table_2 t2 ON t1.ID_1=t2.ID_1
INNER JOIN Table_3 t3 ON t2.ID_2=t3.ID_2
This one does not, but when running with more than 35,000 vs 40,000 elements, the execution time goes from <5sec to >1min:
SELECT ID_1, ID_2, Date
INTO #DEST_TABLE FROM
(SELECT * FROM Table_1 l CROSS APPLY Table_2 t2 WHERE t1.ID_1=t2.ID_1) t_temp
LEFT JOIN Table_3 t3 ON t_temp.ID_2=t3.ID_2
How can I decrease my execution time as much as possible?
Here is an example table:
For this table, I would be trying to get the most recent location for each person.
None of the columns are indexed and I cannot create indexes on this table.
First of all, when you are working on 100 Million+ records and that
too joining to other tables, first thing I would ask is what is the
rationale behind not creating indexes which can cover your query. If
you are not the admin of that system, I would suggest that you
should bring this up to admin group and try to understand what is
the exact reason (if any) they do not want index on that huge table.
Specially because you mentioned "efficiency is very important to
me".
Remember that 'SQL Tuning' is only one of the steps of 'Database Performance Tuning' and you can tune only as much with writing a good SQL Query. When the data volume gets huge, a good SQL Query is never sufficient without taking other Performance Tuning Measures.
Apart from what Roger has already provided, here are a few solutions that you can try out:
Solution 1
SELECT T1.ID_1, OA.ID_2, OA.Location
FROM Table1 T1
OUTER APPLY (
SELECT TOP 1 T3.ID_2, T3.Location
FROM Table2 T2
INNER JOIN Table3 T3
ON T2.ID_2 = T3.ID_2
WHERE T2.ID_1 = T1.ID_1
ORDER BY T3.Date DESC
) OA;
Solution 2:
SELECT DISTINCT
T1.ID_1
,T2.ID_2
,Location = FIRST_VALUE(T3.Location) OVER (PARTITION BY T1.ID_1 ORDER BY T3.Date DESC)
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.ID_1 = T2.ID_1
INNER JOIN Table3 T3
ON T2.ID_2 = T3.ID_2;
Data Preparation:
DROP TABLE IF EXISTS Table1
DROP TABLE IF EXISTS Table2
DROP TABLE IF EXISTS Table3
SELECT TOP 10000 ID_1 = object_id, name
INTO Table1
FROM sys.all_objects
ORDER BY object_id
SELECT ID_1 = T1.ID_1, ID_2 = IDENTITY(INT, 1, 1)
INTO Table2
FROM Table1 T1
CROSS JOIN Table1 T2
SELECT ID_2, Location = 'City_'+ CAST(ID_2 AS VARCHAR(100)), Date = CAST(DATEADD(DAY, ID_2/10000, GETDATE()) AS DATE)
INTO Table3
FROM Table2
Indexes to cover the Solution 1:
CREATE NONCLUSTERED INDEX IX_TABLE1_ID_1 ON Table1 (ID_1)
CREATE NONCLUSTERED INDEX IX_TABLE2_ID_2 ON Table2 (ID_1, ID_2)
CREATE NONCLUSTERED INDEX IX_TABLE3_ID_2 ON Table3 (ID_2, Date DESC) INCLUDE (Location)
Execution Plan:
You can see that all are 'Index Seek' except for Table1 which is an legitimate 'Index Scan' because you are doing scans for each value of Table1's ID_1 value. If you put a where clause in the outer loop to search for a few specific ID_1 values, then that 'Index Scan' will turn to a 'Index Seek' as well.
I will leave the Index Strategy for the 2nd solution to you (as a homework :) ). Tips: You have to make the Location as a key as well. Or you can go with COLUMNSTORE index approach.
You can use something like this:
select top (1) with ties
a.A_Id, b.B_Id, b.Date
from dbo.TableA a
inner join dbo.TableB b on a.A_Id = it.A_Id
inner join dbo.TableC c on c.B_Id = b.B_Id
order by row_number() over(partition by a.A_Id order by b.Date desc);
Alternatively, you can try an olde fashioneth approache:
select a.A_Id, b.B_Id, b.Date
from dbo.TableA a
inner join dbo.TableB b on a.A_Id = b.A_Id
inner join dbo.TableC c on c.B_Id = b.B_Id
where not exists (
select 0 from dbo.TableB pb where pb.B_Id = b.B_Id and pb.Date > b.Date
);
However, as with all such situations, its performance will heavily depend on indices. SSMS can suggest you some, if you will look at the execution plan; off the top of my head, you will need all Id columns to be indexed, and you will need either a single (Date) or a composite (A_Id, Date, B_Id) on the TableB.
UPD: If you can't create or modify any indices, and performance is paramount, I would suggest copying the data in question into a separate schema or database, where you might have appropriate permissions. Apart from that... it's impossible to get something out of nothing.

SQL Server differences between same table on different databases

I have the same table in two different databases. It has the same columns, primary keys, etc. but data in this table may differ from one database to another. So I am trying to get the differences. For example:
Database A Database B
Table_A Table_B
Table_A and Table_B have Id1 and Id2 fields as primary key.
Table_A and Table_B is exactly the same but may contain different data. So I would like to obtain the differences, I mean, obtain the data that is in Table_A but not in Table_B, and insert them in Table_B, or if it is not possible to automatically insert them in Table_B to generate a list of inserts.
To obtain the data that is in Table_A and not in Table_B and vice versa, I do the following:
SELECT a.*, b.*
FROM Table_A a
FULL JOIN Table_B b ON (a.Id1=b.Id1 and a.Id2=b.Id2)
WHERE a.Id1 IS NULL OR b.Id1 IS NULL or a.Id2 IS NULL OR b.Id2 IS NULL
Then I use excel to generate my inserts to be inserted on table Table_B.
Is that correct? or is there any better way to do this?
For your scenario I would go with the MERGE statement
MERGE INTO Table_B AS Trg
USING (SELECT ID1, ID2, YourDataColumn FROM Table_A) AS Src
ON Trg.ID1 = Src.ID1 AND Trg.ID2 = Src.ID2
WHEN NOT MATCHED BY TARGET THEN
INSERT (ID1, ID2, YourDataColumn )
VALUES (Src.ID1, Src.ID2, Src.YourDataColumn );
Would be great to know what database you're on.
Oracle SQL Developer got tooling for this. http://www.thatjeffsmith.com/archive/2012/09/sql-developer-database-diff-compare-objects-from-multiple-schemas/

Convert Access delete statement to SQL Server

I am converting Access to SQL and I got stuck at this Delete Statement because I am not sure what it does exactly.
DELETE TableA.cID, TableB.*
FROM TableA RIGHT JOIN TableB ON TableA.cID = TableB.CID2
WHERE (((TableA.cID) Is Null));
I am guessing it is something like this:
Delete
from TableA right join TableB ON TableA.cID = TableB.CID2
Where TableA.cID is null
I am not really sure if it should delete from 1 table or 2 or..
You want:
Delete TableB
from TableA right join TableB ON TableA.cID = TableB.CID2
Where TableA.cID is null
Personally, I always avoid right joins because the same thing can be stated by switching the order of the tables. I would re-write the statement like this:
DELETE B
FROM TableB AS B LEFT JOIN TableA AS A ON B.CID2 = A.cID
WHERE A.cID IS NULL
See T-SQL: Selecting rows to delete via joins for further information.
As for what that query is actually doing, here is a brief description:
Delete all rows in TableB where no matching record exists in TableA (TableA.cID IS NULL) for the condition TableB.CID2 = TableA.cID

most efficient way to quickly delete records using a join?

What is the fastest way to delete records from a SQL Server database for a large year-end purge, when the query has to join to another table? I understand cursors are slow. Do I do
DELETE FROM table1 WHERE table1_id in (SELECT table1_id FROM table2 WHERE whatever)
Seems like it might be faster to join to the table inside the query using a different technique, something like
DELETE FROM table1 WHERE table1_id = table2
A join would be the best way to go.
I assume you have a foreign key association from table2 to table1, so you're going to want to delete from the second table before the primary table.
Example:
DELETE T2
FROM table1 T1
JOIN table2 T2 ON -- JOIN CRITERIA HERE
WHERE -- FILTER CRITERIA HERE
DELETE T1
FROM table1 T1
JOIN table2 T2 ON -- JOIN CRITERIA HERE
WHERE -- FILTER CRITERIA HERE
If you attempt to delete from the primary table first, you will likely encounter a foreign key constraint violation.
Could you add a cascade delete relationship on the foreign key then get SQL server to cascade the delete for you?
Maybe something like this would be faster.
delete from (select * FROM table1 WHERE table1_id in (SELECT table1_id FROM table2 WHERE whatever))
You can try this (should be faster than IN statement, because query stops than find first value in subquery and search next value):
DELETE t1
FROM table1 t1
WHERE EXISTS (SELECT 0
FROM table2 t2
WHERE t1.table1_id = t2.table1_id
AND whatever)
Or you can do JOIN:
DELETE t1
FROM table1 t1
JOIN table2 t2 ON t1.table1_id = t2.table1_id
WHERE whatever

Delete Data from One Table using multiple tables in SQL Server

I am trying to delete some data from one table using multiple table. The problem i am having with this query is that it is deleting data that is not suppose to delete. I want to delete only the Data where ID's in both tables are DIFFERENT. In other words, i want to keep when the ID's in both tables are the same. Here is my query:
delete Tabel1
from Table1 r join
Table2 w on r.ID <> w.ID
and w.Date_Assigned is not null
You probably want to do:
delete Tabel1 where Id not in (select Id from Table2)
Your statement will probably delete all records from Tabel1, because for every record it will find at least one in Tabel2 with a different ID.
To test this, just run
select r.ID
from Table1 r join
Table2 w on r.ID <> w.ID
and w.Date_Assigned is not null
and you'll understand what the problem is.

Resources