0

我有

TableA (TableAId int PK, Name varchar) 
TableB (OtherId, TableAId FK, TimeBegin timestamp ,TimeEnd timestamp)

我想从 TableB 中的 TimeEnd = NULL 的 TableA Name(s) 中进行选择。

尝试过这样的事情:

SELECT     TableAId, Name
FROM       TableA
WHERE      
(
TableAId NOT IN 
                (
                 SELECT TableAId FROM TableB WHERE TimeEnd is null
                )
);

它工作正常,当我有一些记录的 TimeEnd 为空而一些记录的 TimeEnd 不为空时,但当我没有设置 TimeEnd 的记录时它不起作用。

如何解决?

4

3 回答 3

1

试试这个

Select * from TableA a
Left Join TableB b ON a.TableAId = b.TableAId 
WHERE b.TimeEnd IS NULL

对于非空

Select * from TableA a
Left Join TableB b ON a.TableAId = b.TableAId 
WHERE b.TimeEnd IS NOT NULL
于 2012-10-14T00:33:05.353 回答
1

根据您的问题,有两种可能的答案:

IF OBJECT_ID('dbo.TableB') IS NOT NULL 
  DROP TABLE dbo.TableB;
IF OBJECT_ID('dbo.TableA') IS NOT NULL 
  DROP TABLE dbo.TableA;

CREATE TABLE dbo.TableA
  (
    TableAId INT PRIMARY KEY,
    Name VARCHAR(100)
  ); 
CREATE TABLE dbo.TableB
  (
    OtherId INT PRIMARY KEY,
    TableAId INT FOREIGN KEY REFERENCES TableA ( TableAId ),
    TimeBegin DATETIME,
    TimeEnd DATETIME
  );


INSERT  INTO dbo.TableA
        ( TableAId, Name )
VALUES  ( 1, 'aaa' ),
        ( 2, 'bbb' ),
        ( 3, 'ccc' ),
        ( 4, 'ddd' );

INSERT  INTO dbo.TableB
        ( OtherId, TableAId, TimeBegin, TimeEnd )
VALUES  ( 1, 1, GETDATE(), NULL ),
        ( 2, 2, GETDATE(), GETDATE() ),
        ( 3, 2, GETDATE(), NULL ),
        ( 4, 3, GETDATE(), GETDATE() );


SELECT  A.*
FROM    dbo.TableA A
WHERE   EXISTS ( SELECT 1
                 FROM   dbo.TableB B
                 WHERE  A.TableAId = B.TableAId
                        AND B.TimeEnd IS NULL );

SELECT  A.*
FROM    dbo.TableA A
WHERE   EXISTS ( SELECT 1
                 FROM   dbo.TableB B
                 WHERE  A.TableAId = B.TableAId
                        AND B.TimeEnd IS NULL )
        AND NOT EXISTS ( SELECT 1
                         FROM   dbo.TableB B
                         WHERE  A.TableAId = B.TableAId
                                AND B.TimeEnd IS NOT NULL );

第一个选择返回 TableA 中的所有记录,其中在 TableB 中存在至少一个匹配记录且 TimeEnd 为 NULL。

第二个选择返回 TableA 中所有匹配记录在 TableB fullfil TimeEnd 中为 NULL 的记录。

第二个选择可以重写为

SELECT  A.*
FROM    dbo.TableA A
LEFT JOIN ( SELECT  TableAId,
                    MIN(CASE WHEN TimeEnd IS NULL THEN 1
                             ELSE 0
                        END) AllAreNull
            FROM    dbo.TableB
            GROUP BY TableAId
          ) AS B
        ON A.TableAId = B.TableAId
WHERE   B.AllAreNull = 1;

这有点不太容易理解,但在大多数情况下应该执行得更快。但是您应该运行自己的性能测试以确保。

如果 TableA 中的每条记录在 TableB 中最多有一条记录,则可以使用第一个 select 语句。

最后,您的代码与描述文本不匹配。如果您实际上正在寻找具有 endtime 值的记录,则需要在上述所有选择语句中将 IS NULL 与 IS NOT NULL 切换出来,反之亦然。

于 2012-10-14T02:43:58.447 回答
0

我认为您可能需要先加入 2 个表,如以下示例所示:

SELECT     TableA.TableAId, TableA.Name
FROM       TableA
INNER JOIN TableB
ON TableA.TableAId = TableB.TableAId
WHERE      
(
TableA.TableAId NOT IN 
                (
                 SELECT TableAId FROM TableB WHERE TimeEnd is null
                )
);
于 2012-10-14T00:26:58.527 回答