T-SQL:有条件地去除 NULL

T-SQL: Conditional NULL removal

我只需要 select Room_IDs 没有 Status 为 NULL 的实例。

例如这里:

TABLE_A

  Room_Id   Status    Inspection_Date
  -----------------------------------
    1        NULL        5/15/2015
    2        occupied    5/21/2015
    2        NULL        1/19/2016
    1        occupied   12/16/2015
    4        NULL        3/25/2016
    3        vacant      8/27/2015
    1        vacant      4/17/2016
    3        vacant     12/12/2015
    3        vacant      3/22/2016
    4        vacant       2/2/2015
    4        vacant      3/24/2015

我的结果应该是这样的:

  Room_Id  Status  Inspection_Date
  -----------------------------------
    3       vacant      8/27/2015
    3       vacant     12/12/2015
    3       vacant      3/22/2016

因为 Room_ID '3' 没有 Status 为 NULL

的实例

您可以像下面的代码一样使用 CTE 和 NOT EXIST

WITH    bt
      AS ( SELECT   RoomId ,
                    Status,
                    Inspection_Date
           FROM     dbo.Table_1
         )
SELECT  *
FROM    bt AS a
WHERE   NOT EXISTS ( SELECT 1
                     FROM   bt
                     WHERE  bt.RoomId = a.RoomId
                            AND bt.Status IS NULL );

试试这个:

 SELECT *
 FROM Table1 
 WHERE Room_ID NOT IN 
 (
   SELECT DISTINCT Room_ID
   FROM Table1
   WHERE Status IS NULL
   )

子查询 returns 一个唯一房间 ID 的列表,这些房间 ID 曾一度处于 NULL 状态。外部查询查看该列表,并说“Return * 其中 room_ID 不是子查询中的一个。

如果您想在 SQL Fiddle 中尝试,这里是架构:

CREATE TABLE Table1
    (Room_ID int, Status varchar(8), Inspection_Date datetime)
;

INSERT INTO Table1
    (Room_ID, Status, Inspection_Date)
VALUES
    (1, NULL, '2015-05-15 00:00:00'),
    (2, 'occupied', '2015-05-21 00:00:00'),
    (2, NULL, '2016-01-19 00:00:00'),
    (1, 'occupied', '2015-12-16 00:00:00'),
    (4, NULL, '2016-03-25 00:00:00'),
    (4, 'vacant', '2015-08-27 00:00:00'),
    (1, 'vacant', '2016-04-17 00:00:00'),
    (3, 'vacant', '2015-12-12 00:00:00'),
    (3, 'vacant', '2016-03-22 00:00:00'),
    (4, 'vacant', '2015-02-02 00:00:00'),
    (4, 'vacant', '2015-03-24 00:00:00'),
    (2, NULL, '2015-05-22 00:00:00')
;

如何操作的快速示例:

DECLARE @tTable TABLE(
Room_Id INT,
Status VARCHAR(20),
Inspection_Date DATETIME)

INSERT INTO @tTable VALUES 
 (1, NULL, '5/15/2015'),
 (1,NULL,        '5/15/2015'),
 (2,'occupied',  '5/21/2015'),
 (2,NULL,        '1/19/2016'),
 (1,'occupied',  '12/16/2015'),
 (4,NULL,        '3/25/2016'),
 (3,'vacant',    '8/27/2015'),
 (1,'vacant',    '4/17/2016'),
 (3,'vacant',    '12/12/2015'),
 (3,'vacant',    '3/22/2016'),
 (4,'vacant',    '2/2/2015'),
 (4,'vacant',    '3/24/2015')

 SELECT * FROM @tTable T1
  WHERE Room_Id NOT IN (SELECT Room_ID FROM @tTable WHERE Status IS NULL)

给出:

Room_Id |   Status |    Inspection_Date         |
-------------------------------------------------
3       |   vacant |    2015-08-27 00:00:00.000
3       |   vacant |    2015-12-12 00:00:00.000
3       |   vacant |    2016-03-22 00:00:00.000

作为 Hashman 的替代品,对于这些类型的查询,我更喜欢使用 not exists 而不是 not in

正在创建一些测试数据

请注意,我只是为所有内容保留了相同的日期,因为这对问题来说不是必须的。

create table #table_a (
    Room_Id int,
    Status varchar(32),
    Inspection_Date date);

insert #table_a (Room_Id, Status, Inspection_Date)
    values
        (1, null, getdate()),
        (2, 'occupied', getdate()),
        (2, null, getdate()),
        (1, 'occupied', getdate()),
        (4, null, getdate()),
        (3, 'vacant', getdate()),
        (1, 'vacant', getdate()),
        (3, 'vacant', getdate()),
        (3, 'vacant', getdate()),
        (4, 'vacant', getdate()),
        (4, 'vacant', getdate());

查询

select *
from #table_a t1
where not exists (
    select *
    from #table_a t2
    where t1.Room_Id = t2.Room_Id
        and Status is null);

结果

Room_Id     Status                           Inspection_Date
----------- -------------------------------- ---------------
3           vacant                           2016-06-17
3           vacant                           2016-06-17
3           vacant                           2016-06-17