2014-09-26 54 views
0

我有一个函数可以得到两个ID列表,我想要返回差异计数。如果两个列表相等,则为0,否则为计数。T-SQL获得两个表之间差异的计数

这我会叫:

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的价值,所以我期望作为回报价值,但我得到

出了什么问题?

+0

如果要创建的2个逗号分隔字符串可能是更为有效的,以完全避免他们和解决这个问题以不同的方式 – 2014-09-26 09:07:29

+0

我不知道,但我认为你的函数参数没有很好地定义你已经设置了varchar,我认为它们应该有一个长度,即varchar(100) – 2014-09-26 09:08:09

回答

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 
+0

是的,我确定使用不同的数据类型。我现在改成'[dbo]。[Redline_compareBaseProjSuccessors](@projSuccessors nvarchar,@ baseSuccessors nvarchar)'和'SELECT base_assignment_id作为obj_id from base_assignment where base_assignment_id in('+ @ baseSuccessors +')'但现在它抛出一个'Error将varchar'+ @ baseSuccessors +'转换为int类型 – 2014-09-26 09:19:42

+0

@AlexanderDiedler:'varchar'和'nvarchar'之间的区别并不是问题,而是您尝试使用字符串作为SQL代码。您不能使用字符串连接来将字符串用作SQL代码。如果你想在代码中使用字符串,那么你必须把整个查询放在一个字符串中,然后执行该字符串。 – Guffa 2014-09-26 13:35:14

-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的列或用户definied功能或用户定义的聚合“dbo.fnStringList2Table”找不到,或者用户名不是唯一的/重复的。

+0

这应该很好地将字符串转换为值列表。从错误消息看来,该函数不存在。检查你是否创建了它,并确保它在正确的数据库中结束。 – Guffa 2014-09-26 13:39:49

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 
相关问题