替代'除了'在SQL中具有性能

时间:2017-03-12 08:58:13

标签: sql sql-server sql-except

我在MS-Sql中使用TableA表

 TrId   Status
 2345   3
  567   3
  567   0
 2345   0
   99   3
  778   0

场景很少TrIds的状态为3和0,有些只有3只有0。我需要找到状态仅为3的TrIds 其中一种方法是:

Select TrnId From TableA Where flgStatus = 3
EXCEPT
Select TrnId From Tablea Where flgStatus = 0

有超过1亿条记录,我没有足够的时间窗口,除此之外,任何替代方案都是值得赞赏的。

5 个答案:

答案 0 :(得分:3)

您可以使用NOT EXISTS

SELECT *
FROM TableA a
WHERE flgStatus = 3
AND NOT EXISTS 
(SELECT TrnId From TableA b Where flgStatus = 0 AND a.TrnId = b.TrnId) 

这通常比NOT IN具有更好的性能。一个很好的替代方案是加入,请参阅@ThomasG的回答。

答案 1 :(得分:1)

EXCEPTMINUS在这里是正确的。在一张非常大的桌子上,它并不是最佳的。

另一种选择是

SELECT *
FROM TableA 
WHERE flgStatus = 3
AND TrnId  NOT IN
(SELECT TrnId From TableA Where flgStatus = 0) 

甚至更好,使用LEFT JOINIS NULL来避免NOT这是一个杀手杀手:

SELECT *
FROM TableA T3
LEFT JOIN TableA T0 ON T3.TrnId = T0.TrnId AND T0.flgStatus = 0
WHERE T3.flgStatus = 3
  AND T0.TrnId IS NULL

编辑:来自Igor的NOT EXISTS解决方案也是一个很好的方法

答案 2 :(得分:1)

组合(TrnId,flgStatus)是唯一的吗?

然后您可以切换到EXCEPT ALL,类似于UNION ALL,这可能比UNION更有效,因为它可以避免DISTINCT操作。

另一种只访问基表一次的解决方案:

Select TrnId 
From TableA Where flgStatus in (0,3)
group by TrnId
having MIN(flgStatus) = 3

答案 3 :(得分:1)

我会使用简单的group by

select trnid
from tablea
group by trnid
having min(status) = max(status) and min(status) = 3;

这是否更快取决于几件事。 。 。值得注意的是,您是否要删除重复数据以及您对数据的索引。如果您不关心重复项,NOT EXISTS可能会更快,但重复删除需要工作。

答案 4 :(得分:0)

对于像您这样的大型数据集,使用以下查询可能会为您的所需结果提供合理的性能 -

SELECT ta1.TrId AS TrId
FROM dbo.TableA AS ta1
LEFT JOIN dbo.TableA AS ta2 ON (ta2.TrId = ta1.TrId AND ta2.[Status] != 3)
WHERE ta2.TrId IS NULL;

首先,自连接通过在同一行中排列所有状态(3或0,1等)来创建表。过滤器

 ta2.[Status] != 3
如果Status为3,则join子句中的

为ta2.TrId(或ta2。*)设置NULL。

+------+--------+------+--------+
| TrId | Status | TrId | Status |
+------+--------+------+--------+
| 2345 |      3 | 2345 | 0      |
|  567 |      3 | 567  | 0      |
|  567 |      0 | 567  | 0      |
| 2345 |      0 | 2345 | 0      |
|   99 |      3 | NULL | NULL   |
|  778 |      0 | 778  | 0      |
+------+--------+------+--------+

然后使用以下过滤器来选择出现NULL的行。

WHERE ta2.TrId IS NULL

由于它是自我LEFT JOIN,左表包含所有行,但是对于连接条件不符合的右表值为NULL。