比较两个表并将结果显示为单独的输出

时间:2017-10-09 08:44:34

标签: sql-server sql-server-2008

我有两个表,像这样的值,`

CREATE TABLE Location (ID int ,Location Varchar(500))
    INSERT INTO Location values (1,'Loc3'),(2,'Loc4'),(3,'Loc5'),(4,'Loc7')
    CREATE TABLE InputLocation (ID int ,Location Varchar(500))
    Insert into InputLocation values(1,'Loc1,Loc2,Loc3,Loc4,Loc5,Loc6')

我需要通过匹配表Location中的每个值和表InputLocation来获取输出,并且需要显示与第二个表不匹配的输出,即Loc1,Loc2,Loc6,我试过了像这样的一些代码,它工作但我需要更简单的代码,任何帮助将不胜感激

我的代码:

SELECT  STUFF((select ','+ Data.C1 
FROM   
(select 
  n.r.value('.', 'varchar(50)') AS C1
from InputLocation as T
cross apply (select cast('<r>'+replace(replace(Location,'&','&amp;'), ',', '</r><r>')+'</r>' as xml)) as S(XMLCol)
cross apply S.XMLCol.nodes('r') as n(r))  DATA
WHERE  data.C1 NOT IN (SELECT Location
                FROM   Location) for  xml path('')),1,1,'') As Output

2 个答案:

答案 0 :(得分:0)

使用递归来避免使用慢速XML Reader:

;with tmp(DataItem, Location) as (
select cast(LEFT(Location, CHARINDEX(',',Location+',')-1) as nvarchar(50)),
    cast(STUFF(Location, 1, CHARINDEX(',',Location+','), '') as nvarchar(50))
from [InputLocation]
union all
select cast(LEFT(Location, CHARINDEX(',',Location+',')-1) as nvarchar(50)),
    cast(STUFF(Location, 1, CHARINDEX(',',Location+','), '') as nvarchar(50))
from tmp
where Location > ''
)
select STUFF((SELECT ',' + x.Location
from (
select DataItem as Location from tmp
except Select Location from [Location]) x
FOR XML path('')), 1, 1, '') AS OUTPUT

答案 1 :(得分:0)

你的脚本没问题。

另一种方法是使用SPLIT String,如此处所述。 http://www.sqlservercentral.com/articles/Tally+Table/72993/

使用[dbo]。[DelimitedSplit8K]

假设我的逗号分隔字符串不会超过500,那么在我的自定义UDF中,我将其设为500 varchar而不是varchar(8000),以提高性能。

SELECT STUFF((
            SELECT ',' + Data.item
            FROM (
                SELECT il.ID
                    ,fn.item
                FROM @InputLocation IL
                CROSS APPLY (
                    SELECT *
                    FROM dbo.DelimitedSplit2K(il.Location, ',')
                    ) fn
                WHERE NOT EXISTS (
                        SELECT *
                        FROM @Location L
                        WHERE l.Location = fn.Item
                        )
                ) data
            FOR XML path('')
            ), 1, 1, '') AS
OUTPUT