问题
I have table A and table B . I have to compare this tables records and insert data to table C using SQL Server procedure in below format.
table A
name description
A desc A
B desc B
C desc C
D desc D
E desc E
F desc F
G desc G
H desc H
I desc I
J desc J
table B
name description
A desc A
B desc B
M desc M
N desc N
O desc O
C desc C
D desc D
E desc E
G desc G
H desc H
I desc I
J desc J
Table c should be like below. It has an extra field 'status' to mention record is added or removed.
name description status
A desc A
B desc B
M desc M newly added
N desc N newly added
O desc O newly added
C desc C
D desc D
E desc E
F desc F removed
G desc G
H desc H
I desc I
J desc J
I tried code like below
select
coalesce(a.name, b.name) name,
coalesce(a.description, b.description) description,
case
when a.name is null then 'newly added'
when b.name is null then 'removed'
end status
from tablea a
full join tableb b on b.name = a.name
But in output, newly added records M,N,O is coming in last position.. M,N,O should be under B as in input table. I am not getting output in order as mentioned in table C.
回答1:
Do you just need an order by
?
select coalesce(a.name, b.name) as name,
coalesce(a.description, b.description) as description,
(case when a.name is null then 'newly added'
when b.name is null then 'removed'
end) as status
from tablea a full join
tableb b
on b.name = a.name
order by coalesce(a.name, b.name)
回答2:
If the data is valid, why you are worried about how it is ordered when being inserted?
The relation in the relation theory is represented in the SQL with a table. And the relation is not ordered. So, you are not allowed to defined how rows are ordered when they are materialized - and you should not care about this.
Even you have a unique criteria on which you can order the results, there is no guarantee that the engine will insert the rows in that way. In all cases (except when you have identity column), the ORDER BY
is ignored during the INSERT
:
SELECT *
FROM
(
VALUES (1), (2), (3)
) DS ([col])
ORDER BY [col];
SELECT *
INTO #DS
FROM
(
VALUES (1), (2), (3)
) DS ([col])
ORDER BY [col];
So, ask yourself the following questions:
- Do I have a unique criteria by which to order the values?
- Can I perform this ordering when data is extracted?
回答3:
Maybe you should try it with a merge First insert the Data from Table A into Table C and then
Merge into TableC AS TRG
USING (Select Name
,Description
FROM TableB) AS SRC
ON TRG.Name=SRC.Name
WHEN NOT MATCHED BY TARGET
THEN INSERT (Name
,Description
,[Status]
)
VALUES (Name
,Description
,'newly added')
WHEN NOT MATCHED BY SOURCE
THEN UPDATE SET TRG.[Status]='removed';
Sorry about the formating, it is my first post here :)
回答4:
Data in the table is not ordered.
You have to have some identity column
to keep the order you want. Since you do not have any identity column in your table, you can use ROW_NUMBER
to create virtual identity column.
Below will work for your case. but it's an ugly way. Not sure about the performance.
WITH tablebrow
AS (SELECT *, Row_number() OVER ( ORDER BY (SELECT NULL)) rn
FROM #tableb),
tablearow
AS (SELECT *, Row_number() OVER ( ORDER BY (SELECT NULL)) rn
FROM #tablea)
SELECT COALESCE(a.NAME, b.NAME) NAME,
COALESCE(a.description, b.description) description,
CASE
WHEN a.NAME IS NULL THEN 'newly added'
WHEN b.NAME IS NULL THEN 'removed'
END status
FROM tablearow a
FULL JOIN tablebrow b
ON b.NAME = a.NAME
ORDER BY Isnull(b.rn, (SELECT tr.rn
FROM tablebrow tr
WHERE description = (SELECT TOP 1 description
FROM tablearow t
WHERE t.rn < a.rn
ORDER BY t.rn DESC)))
CHECK DEMO HERE
Note for DEMO example: I have removed I
row as well along with F
for testing
来源:https://stackoverflow.com/questions/60076543/compare-two-tables-and-insert-all-records-with-added-or-removed-status-in-anothe