あなたの質問に基づいて、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 に切り替える必要があり、その逆も同様です。