T-SQL得到两个表之间的差异计数

时间:2014-09-26 08:47:59

标签: sql sql-server

我有一个函数可以得到两个ID列表,我想要找回差异的数量。如果两个列表相等,则为0,否则为计数。

我将致电:

SELECT [dbo].[Redline_compareBaseProjSuccessors]
( '2498,2502,2510,2521,2841',
  '2498,2502,2510,2521,2532,2820,2841') as isDifferent

我的职能是:

ALTER FUNCTION [dbo].[Redline_compareBaseProjSuccessors] (@projSuccessors varchar,@baseSuccessors varchar)
RETURNS int
AS
BEGIN
    DECLARE @proj_assignment_ids TABLE (obj_id int)
    DECLARE @base_assignment_ids TABLE (obj_id int)
    DECLARE @is_different int

    INSERT INTO @base_assignment_ids
       SELECT base_assignment_id as obj_id 
       FROM base_assignment 
       WHERE base_assignment_id IN (@baseSuccessors)

    INSERT INTO @proj_assignment_ids
       SELECT base_assignment_id AS obj_id 
       FROM proj_assignment 
       WHERE proj_assignment_id IN (@projSuccessors)

    SELECT @is_different = Count(obj_id)
    FROM @base_assignment_ids
    WHERE obj_id NOT IN (SELECT obj_id FROM @proj_assignment_ids)   

    RETURN @is_different
END

@base_assignment_ids的值是:2498,2502,2510,2521,2841,2532,2820@proj_assignment_ids = 2498,2502,2510,2521,2841的值,所以我希望 2 作为返回值,但是我得到 0

出了什么问题?

3 个答案:

答案 0 :(得分:0)

您无法在in运算符中使用字符串而不是值列表。即:

... in ('1, 2, 3')

与:

不同
... in (1, 2, 3)

您必须将该字符串转换为值列表,或者在字符串中查找id的字符串表示形式。

第二种很容易做到,但效率不高:

insert into @base_assignment_ids
select base_assignment_id as obj_id
from base_assignment
where
  CHARINDEX(
    ',' + cast(base_assignment_id as varchar) + ',',
    ',' + @baseSuccessors + ','
  ) <> 0

答案 1 :(得分:0)

您需要稍微修改插入脚本

ALTER FUNCTION [dbo].[Redline_compareBaseProjSuccessors] (@projSuccessors varchar,@baseSuccessors varchar)
RETURNS int
AS
BEGIN
    DECLARE @proj_assignment_ids TABLE (obj_id int)
    DECLARE @base_assignment_ids TABLE (obj_id int)
    DECLARE @is_different int

    INSERT INTO @base_assignment_ids
       SELECT base_assignment_id as obj_id 
       FROM base_assignment 
       WHERE base_assignment_id IN (
         SELECT  
     Split.a.value('.', 'int') AS String  
     FROM  (SELECT   
     CAST ('<M>' + REPLACE(@baseSuccessors, ',', '</M><M>') + '</M>' AS XML) AS String  
     ) AS A CROSS APPLY String.nodes ('/M') AS Split(a))

    INSERT INTO @proj_assignment_ids
       SELECT base_assignment_id AS obj_id 
       FROM proj_assignment 
       WHERE proj_assignment_id IN ( SELECT  
     Split.a.value('.', 'int') AS String  
     FROM  (SELECT   
     CAST ('<M>' + REPLACE(@projSuccessors, ',', '</M><M>') + '</M>' AS XML) AS String  
     ) AS A CROSS APPLY String.nodes ('/M') AS Split(a))

    SELECT @is_different = Count(obj_id)
    FROM @base_assignment_ids
    WHERE obj_id NOT IN (SELECT obj_id FROM @proj_assignment_ids)   

    RETURN @is_different
END

答案 2 :(得分:-1)

我发现了这个Convert String to Int List,但它对我的情况不起作用。

ALTER FUNCTION [dbo].[Redline_compareBaseProjSuccessors] (@projSuccessors nvarchar(max),@baseSuccessors nvarchar(max))
RETURNS int
AS
BEGIN           
    DECLARE @proj_assignment_ids TABLE (obj_id int)
    DECLARE @base_assignment_ids TABLE (obj_id int)
    DECLARE @is_different int

    INSERT INTO @base_assignment_ids
    SELECT base_assignment_id as obj_id from base_assignment where base_assignment_id in (dbo.fnStringList2Table(@base_assignment_ids))


    INSERT INTO @proj_assignment_ids
    select base_assignment_id as obj_id from proj_assignment where proj_assignment_id in (dbo.fnStringList2Table(@proj_assignment_ids))

    SELECT @is_different=Count(obj_id)
    FROM @base_assignment_ids
    WHERE obj_id NOT IN (SELECT obj_id FROM @proj_assignment_ids)   
    RETURN @is_different
END

,函数fnStringListToTable如下所示:

ALTER FUNCTION [dbo].[fnStringList2Table]
(
@List varchar(MAX)
)
RETURNS 
@ParsedList table
(
item int
)
AS
BEGIN
DECLARE @item varchar(800), @Pos int

SET @List = LTRIM(RTRIM(@List))+ ','
SET @Pos = CHARINDEX(',', @List, 1)

WHILE @Pos > 0
BEGIN
    SET @item = LTRIM(RTRIM(LEFT(@List, @Pos - 1)))
    IF @item <> ''
    BEGIN
        INSERT INTO @ParsedList (item) 
        VALUES (CAST(@item AS int))
    END
    SET @List = RIGHT(@List, LEN(@List) - @Pos)
    SET @Pos = CHARINDEX(',', @List, 1)
END

RETURN
END

但它抛出(翻译自德语) 未找到dbo-column或用户定义的函数或用户定义的聚合'dbo.fnStringList2Table',或者用户名不是唯一/重复的。