Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 匹配所有行的In运算符_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

Sql 匹配所有行的In运算符

Sql 匹配所有行的In运算符,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我想返回匹配csv的所有值,因为传统的“in”运算符匹配csv中存在的任何项目: SELECT * FROM @MyTable WHERE [UserID] IN (1,2) 上面的查询不适用于我的目的,因为我想匹配一个组中同时包含两条记录的行。在我的案例中,组将按typeid进行设置 用于填充表的查询: DECLARE @MyTable TABLE ( [TypeID] INT , [UserID] INT ) INSERT INTO @MyTab

我想返回匹配csv的所有值,因为传统的“in”运算符匹配csv中存在的任何项目:

SELECT * FROM @MyTable
WHERE [UserID] IN (1,2)
上面的查询不适用于我的目的,因为我想匹配一个组中同时包含两条记录的行。在我的案例中,组将按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”时;我希望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

使用split函数,可以进行外部联接,并确保没有空行:

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中的所有值,为什么会出现这种情况?当存在多个匹配项时,确定返回哪一行的规则是什么?

使用拆分函数并执行联接,确保函数中的所有行在表中都有匹配项。我已添加了正在使用的拆分函数。你能帮我查询一下结果吗?我被困在这一部分“确保函数中的所有行在表中都有匹配项”中,因为拆分器运行时,while循环版本的速度非常慢。理想情况下,最好不要在t-sql中这样做,但如果您必须阅读本文,找到比while循环快光年的几个版本。哇!那篇文章看起来非常好。谢谢肖恩,我一定会经历的。