-2

IDのリストを持つ変数が1つあります(例:121,131,142,145)。この中から、テーブルに存在しないIDのリストを見つけたいです。このクエリの出力は、存在しないIDのリストである必要があります。単一のmsssqlクエリを使用して達成します。ID142&145がテーブルに存在しない場合、クエリはこれら2つの値を返す必要があります。IN句で可能ですか。

4

2 に答える 2

3

以下のように、区切られた文字列からテーブルへの変換udfが必要になります。

CREATE FUNCTION [dbo].[fnc_List2Table] (
    @list      varchar(8000),
    @delimiter varchar(16) = ','
) RETURNS @result TABLE (
    ListIndex int,
    Value varchar(8000)
)
AS
BEGIN
    SET @list = LTRIM(RTRIM(ISNULL(@list, SPACE(0))))
    DECLARE @n int, @i int, @delimiterIndex int, @nextItem varchar(8000)
    SET @n = LEN('#' + @delimiter + '#') - 2
    SET @i = 0
    WHILE @list <> SPACE(0)
    BEGIN
        SET @i = @i + 1
        SET @delimiterIndex = CHARINDEX(@delimiter, @list)
        IF @delimiterIndex = 0
        BEGIN
            SET @nextItem = LTRIM(RTRIM(@list))
            SET @list = SPACE(0)
        END
        ELSE
        BEGIN
            SET @nextItem = LTRIM(RTRIM(LEFT(@list, @delimiterIndex-1)))
            SET @list = RIGHT(@list, LEN(@list)-(@delimiterIndex+(@n-1)))
        END
        INSERT INTO @result (ListIndex, Value)
        VALUES (@i, @nextItem)
    END
    RETURN
END

次に、左結合を使用してIDを簡単に確認できます。

declare @ids varchar(50)
set @ids = '121,131,142,145'

select F.Value
from fnc_List2Table(@ids,',') F 
left join YourTable A on F.Value = A.ID
where A.ID is null
于 2012-04-23T07:17:11.930 に答える
0

これは、 http://www.sqlservercentral.com/articles/Tally+Table/72993/からの実装の修正バージョンである別の実装です。

    CREATE FUNCTION dbo.DelimitedSplit8K
    --===== Define I/O parameters
        (@pString VARCHAR(8000), @pDelimiter CHAR(1))
    RETURNS TABLE WITH SCHEMABINDING AS
    RETURN
    --===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
        -- enough to cover VARCHAR(8000)
    WITH E1(N) AS (
                    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          --10E+1 or 10 rows
        E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
        E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS (--==== This provides the "zero base" and limits the number of rows right up front
                        -- for both a performance gain and prevention of accidental "overruns"
                    SELECT 0 UNION ALL
                    SELECT TOP (DATALENGTH(ISNULL(@pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
    cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                    SELECT t.N+1
                    FROM cteTally t
                    WHERE (SUBSTRING(@pString,t.N,1) = @pDelimiter OR t.N = 0) 
                )
    --===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
    SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1),
        Item = SUBSTRING(@pString,s.N1,ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000))
    FROM cteStart s;

udfは、sqlservercentralの記事からそのまま保持されます

select a.id from
 (-- simulate the id table using union queries
  select 1 id union all
  select 2 id union all
  select 3 id union all
  select 4 id union all
  select 5 id union all
  select 6 id union all
  select 7 id union all
  select 8 id union all
  select 9 id union all
  select 10 id union all
  select 11 id 
)a 
 LEFT JOIN -- Do the magic
 (SELECT item id FROM DelimitedSplit8K(  '1,2,4,5',','))b on a.id = b.Id
  WHERE b.Id is null;

INステートメントの代わりに左結合を使用してnull値をフィルター処理しました

于 2012-04-23T08:28:31.540 に答える