Compare two tables and insert all records with added or removed status in another table using SQL Server procedure [duplicate]

徘徊边缘 提交于 2020-03-28 06:48:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!