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がnullのレコードとTimeEndがnullでないレコードがある場合は正常に機能しますが、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

あなたの質問に基づいて、2つの可能な答えがあります:

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 );

最初の選択は、TimeEnd IS NULL で TableB に一致するレコードが少なくとも 1 つ存在する TableA からすべてのレコードを返します。

2 番目の選択は、TableB fullfil TimeEnd IS NULL 内のすべての一致するレコードに対して、TableA からレコードを返します。

2 番目の select は、次のように書き換えることができます。

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 に最大 1 つのレコードを持つ場合、最初の select ステートメントを使用できます。

最後に、あなたのコードは記述テキストと一致しません。endtime が評価されているレコードを実際に探している場合は、上記のすべての select ステートメントで 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 に答える