在匹配所有行的运算符中

时间:2015-04-13 17:00:41

标签: sql sql-server sql-server-2008

我想返回匹配csv的所有值作为传统" in"运算符匹配csv中的任何项目:

SELECT * FROM @MyTable
WHERE [UserID] IN (1,2)

上述查询不能满足我的目的,因为我想匹配具有组记录的行。在我的情况下,group by typeid。

查询填充表格:

DECLARE @MyTable TABLE
    (
      [TypeID] INT ,
      [UserID] INT
    )

INSERT  INTO @MyTable
        SELECT  1 ,
                1
        UNION
        SELECT  1 ,
                2
        UNION
        SELECT  2 ,
                1
        UNION
        SELECT  2 ,
                2
        UNION
        SELECT  2 ,
                3
        UNION
        SELECT  3 ,
                1
        UNION
        SELECT  3 ,
                2
        UNION
        SELECT  3 ,
                3
        UNION
        SELECT  3 ,
                4 

要查询上表,我输入了userid

字符串
DECLARE @UserIDString VARCHAR(256)

这是我的要求:

当输入为' 1,2&#39 ;;我希望typeid 1作为输出,因为该组具有csv中的所有记录。

如果输入是' 1,2,3' ;应该返回2个typeid,因为该组具有csv中的所有值。

如果输入是' 1,2,3,4' ;应该返回3个typeid,因为该组具有csv中的所有值。

编辑:

这是拆分csv的分割函数:

CREATE FUNCTION [dbo].[Split_String]
    (
      @inputString NVARCHAR(2000) ,
      @delimiter NVARCHAR(20) = ' '
    )
RETURNS @Strings TABLE
    (
      [position] INT IDENTITY
                     PRIMARY KEY ,
      [value] NVARCHAR(2000)
    )
AS 
    BEGIN  
        DECLARE @index INT  

        SET @index = -1  

        WHILE ( LEN(@inputString) > 0 ) 
            BEGIN-- Find the first delimiter  

                SET @index = CHARINDEX(@delimiter, @inputString)  
-- No delimiter left?  

-- Insert the remaining @inputString and break the loop  

                IF ( @index = 0 )
                    AND ( LEN(@inputString) > 0 ) 
                    BEGIN  

                        INSERT  INTO @Strings
                        VALUES  ( RTRIM(LTRIM(CAST(@inputString AS NVARCHAR(2000))) ))  

                        BREAK  

                    END  

-- Found a delimiter  

-- Insert left of the delimiter and truncate the @inputString  

                IF ( @index > 1 ) 
                    BEGIN  

                        INSERT  INTO @Strings
                        VALUES  ( RTRIM(LTRIM(CAST(LEFT(@inputString, @index - 1) AS NVARCHAR(2000)) )  ))

                        SET @inputString = RIGHT(@inputString,
                                                 ( LEN(@inputString) - @index ))  
                    END -- Delimiter is 1st position = no @inputString to insert  

                ELSE 
                    SET @inputString = CAST(RIGHT(@inputString,
                                                  ( LEN(@inputString) - @index )) AS NVARCHAR(2000))  
            END
        RETURN  

    END
GO

编辑:

感谢@Tab,经过进一步修改,我已经解决了问题:

DECLARE @InputString VARCHAR(256)
DECLARE @Count VARCHAR(256)

--SET @InputString = '1,2'

DECLARE @DummyTable TABLE
    (
      [position] INT ,
      [value] INT
    )
INSERT  INTO @DummyTable
        ( [position] ,
          [value]
        )
        SELECT  [position] ,
                [value]
        FROM    [dbo].[Split_String](@InputString, ',')

SELECT  @Count = COUNT(1)
FROM    @DummyTable

SELECT  TypeID
FROM    @MyTable
WHERE   TypeID NOT IN (
        SELECT  TypeID
        FROM    @MyTable T
                LEFT OUTER JOIN @DummyTable ss ON t.UserId = ss.Value
        WHERE   ss.Position IS NULL )
GROUP BY TypeID
HAVING  COUNT(TypeID) = @Count

1 个答案:

答案 0 :(得分:2)

使用split函数,可以执行OUTER JOIN并确保没有NULL行:

SELECT TypeID 
FROM @MyTable
WHERE TypeID NOT IN (
  SELECT TypeID
  FROM @MyTable t
  LEFT OUTER JOIN [dbo].[Split_String] (@InputString,',') ss
    ON t.UserId=ss.Value
  WHERE ss.Position IS NULL
) x

未经测试,但我认为应该这样做。

但是,这应该返回满足以下要求的所有类型:

  

该组包含csv中的所有记录。

在您的问题中,您似乎暗示只应返回一行,但如果多行与csv中的所有值匹配,为什么会出现这种情况呢?当有多个匹配时,确定返回哪一行的规则是什么?