我有一个包含列ID
, TYPE
, DATE
, ... 的表,我需要所有数据集TYPE <> 'A'
(案例 1),TYPE = A
如果没有TYPE = B
相同的数据集ID
(案例 2)。第一种情况很容易,所以我想UNION
用来结合第一种和第二种情况。但我不知道如何选择第二种情况。我正在尝试自我连接,例如:
SELECT *
FROM MY_TABLE TAB1
JOIN MY_TABLE TAB2
ON
TAB1.ID = TAB2.ID
AND TAB1.TYPE = 'A'
AND TAB2.TYPE = 'B'
Run Code Online (Sandbox Code Playgroud)
这样我就得到了我不想要的集合。我想我需要一个子查询,但我不知道我应该朝哪个方向工作。
也许是这样的:
SELECT *
FROM MY_TABLE TAB1
WHERE TAB1.TYPE <>'A'
UNION
SELECT *
FROM MY_TABLE TAB1
NOT IN
(SELECT *
FROM MY_TABLE TAB1
JOIN MY_TABLE TAB2
ON
TAB1.ID = TAB2.ID
AND TAB1.TYPE = 'A'
AND TAB2.TYPE = 'B')
Run Code Online (Sandbox Code Playgroud)
例子:
ID | TYPE | ...
---------------
1 | B | ...
2 | A | ...
2 | B | ...
3 | A | ...
Run Code Online (Sandbox Code Playgroud)
我需要第 1 行(TYPE <> 'A')、第 3 行(TYPE <> 'A')和第 4 行(没有相同 ID 和 TYPE = 'B' 的集合)。我不想要第 2 行,因为 TYPE = 'A' 并且有一个具有相同 ID 和 TYPE = 'B' 的数据集。所以结果应该是:
ID | TYPE | ...
---------------
1 | B | ...
2 | B | ...
3 | A | ...
Run Code Online (Sandbox Code Playgroud)
使用NOT EXISTS
:
Declare @T table (id int, [type] varchar(5))
insert into @t(id,[type]) values(1,'B'),(2,'A'),(2,'B'),(3,'A')
SELECT *
FROM @T TAB1
WHERE [TYPE] <> 'A'
UNION ALL
SELECT *
FROM @t TAB1
WHERE [type] = 'A'
AND NOT EXISTS (
SELECT *
FROM @t
WHERE id = TAB1.id
AND [type] = 'B'
)
Run Code Online (Sandbox Code Playgroud)
以上使用UNION ALL
(简单串联),这通常比重复删除更有效UNION [DISTINCT]
。两个集合,一个 withtype = A
另一个 withtype <> A
不可能重叠,所以连接在这里是安全的。
您也可以将逻辑表达为WHERE [TYPE] <> 'A' OR ([TYPE] = 'A' AND NOT EXISTS ...)
但检查哪种方法可以为您提供更好的性能(复杂的析取并不总是优化得很好)。
归档时间: |
|
查看次数: |
284 次 |
最近记录: |