返回表中不存在但在IN列表中存在的值?

时间:2016-12-19 14:38:34

标签: sql-server tsql azure-sql-database

环境

我有一个名为DEVICE的表,其中包含3行:

DeviceID | Number
1          1111111111111111111
2          2222222222222222222
3          4444444444444444444 

使用SSMS我使用IN列表查询Azure SQL表3行:

select number from device 
where number in
(
'1111111111111111111',
'2222222222222222222',
'3333333333333333333',
)

结果:

NUMBER
1111111111111111111
2222222222222222222

伟大的按预期工作:

  • 表格中的3行。
  • 从我的IN列表中返回2行
  • 未返回的1行不在我的IN列表中。

问题

如何查询返回表中不存在但在我的IN列表中存在的NUMBERS? (如果可能,最好使用IN。)

预期结果:

NUMBER
3333333333333333333

重要的是要注意我的生产环境中的IN列表包含:

  • IN列表中的8366行。
  • 表中存在8366的生产数据库7225中返回的行。
  • 因此缺少1141。我需要它的这些价值。
  • 生产表总共包含80,000行。

测试

    尝试
  1. NOT EXISTS,但结果集中根本没有返回任何行。

    select number from device 
    where NOT EXISTS
    (
    SELECT number FROM DEVICE WHERE number IN
    (
    '1111111111111111111',
    '2222222222222222222',
    '3333333333333333333',
    --(etc followed by 8366 unique values)    
    )
    )
    

    结果:

    NUMBER
    (null)
    

    预计会看到值3333333333333333333,因为我的表中不存在。

  2. LEFT JOIN没有帮助,因为没有其他表可以加入。

  3. NOT IN返回了数据库表中但不在我的IN源列表中的值。

    结果:

    NUMBER
    4444444444444444444
    
  4. 我还考虑过创建一个TEMP表,插入我的IN列表值并在NUMBER上运行LEFT连接。作为一个生产环境,我需要谨慎行事。

  5. 从另一个堆叠帖子中尝试这个但是很挣扎:

    select column_value as missing_num
    from   table (sys.odcinumberlist (123,345,555,777))
    where  column_value not in (select accnt from my_table);
    
  6. 参考

    A)

    CREATE TABLE [dbo].[Device](
    [DeviceID] [int] IDENTITY(1,1) NOT NULL,
    [Number] [varchar](20) NULL,
    
    CONSTRAINT [Device_PK] PRIMARY KEY CLUSTERED 
    (
    [DeviceID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,     
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    )
    
    GO    
    

    B) Find values that do not exist in a table

    谢谢。

1 个答案:

答案 0 :(得分:1)

使用8,366个不同的值构造IN语句有效。这实际上会在您的查询中生成8,366个不同的OR语句。

对于这样的事情,我建议使用临时表并将值插入其中,然后使用JOIN。在这种特定情况下,您应该对该表使用LEFT JOIN,并仅采用那些未找到的值。

例如:

Declare @Numbers Table (Number Varchar (20));

Insert  @Numbers
Values  ('1111111111111111111'),
        ('2222222222222222222'),
        ('3333333333333333333'),
        ...

Select      N.Number
From        @Numbers    N
Left Join   Device      D   On  N.Number = D.Number 
Where       D.Number Is Null

您还可以使用CTE来构建您的数字列表:

;With Numbers (Number) As
(
    Select  '1111111111111111111' Union All
    Select  '2222222222222222222' Union All
    Select  '3333333333333333333' Union All
    ...
)
Select      N.Number
From        Numbers     N
Left Join   Device      D   On  N.Number = D.Number 
Where       D.Number Is Null