0
PID UID Req Res

1   101 C   to
2   101 A   from
3   101 B   to
4   102 A   from
5   102 B   from

我想编写一个查询来从满足以下条件的表中获取所有记录。

我想获取 Res='to' 的所有记录的 UID。对于这些特定的 UID,我想获取 Req='A' 的记录。我写了一个示例查询,它也有效。请在下面找到查询。

SELECT Res,
       UID,
       Req
FROM   TABLE
WHERE  Req = 'A'
       AND UID = (SELECT DISTINCT( UID )
                  FROM   TABLE
                  WHERE  Res = 'to') 

上述查询的问题在于,在 SQL Server 2008 中运行时,它仅获取 15-20 条记录就运行了一个多小时。记录总数很大,因为这是一个生产表。我想知道为什么查询运行时间很长,以及我是否可以获得相同的优化查询。

谢谢,普拉巴

4

4 回答 4

0

尝试使用 aJOIN而不是子查询:

SELECT a.Res,
       a.UID,
       a.Req
  FROM TABLE a
  JOIN (SELECT UID FROM TABLE WHERE Res = 'to' GROUP BY UID) b
       ON a.UID = b.UID
 WHERE a.Req = 'A'
于 2012-07-14T09:42:01.533 回答
0

我看到其他帖子表明以下内容可能更有效:

SELECT Res, UID, Req
FROM TABLE t
WHERE  Req = 'A' and
       exists (select * from table t2 where t2.res = 'to' and t.uid = t2.uid)

从逻辑上讲,它做同样的事情,但在这种情况下,相关子查询可能会产生更好的查询计划。

它还取决于选择性 Req 和 Res 是谁(涉及的行多还是只有几行)。如果表中的许多行满足条件,则有使用 windows 函数的替代公式。

于 2012-07-14T14:36:20.900 回答
0

您的查询如此缓慢的原因是您的引擎可能正在为它考虑的每一行运行该子查询,并且该查询可能是隐式聚合(因为它使用 DISTINCT)。每一行都需要做很多工作,而且当它稍后进入结果集时,它可能会做大量的交换来实现它。

此查询将表连接到自身,条件是连接的行具有相同的 UID并且Res = 'to'。根据两个因素过滤行:至少有一个匹配行具有相同的 UID 和 Res='to',以及 Req='A'。

这将是一个非常快速的解决方案,原因如下: 查询引擎经过优化,可以尽快从结果集中消除行。对于 PID=1、3、&5 的行,由于 Req != 'A',引擎将立即将它们从考虑中丢弃(甚至不执行连接)。对于 PID=2 行,连接将匹配第 1 行,然后通常甚至不会继续连接到第 3 行(因为它通过 DISTINCT 关键字(以及没有选择连接中的列的事实)知道与join 不会改变结果集)。对于 PID=4,它不会匹配任何东西。

SELECT DISTINCT main_row.Res,
       main_row.UID,
       main_row.Req
FROM   TABLE AS main_row
JOIN   TABLE AS res_join 
       ON main_row.UID = res_join.UID 
       AND res_join.Res = 'to'
WHERE  main_row.Req = 'A'
于 2012-07-14T15:16:40.930 回答
0

由于可能只是您对 DISTINCT 的使用导致了问题,因此这些值得探索。显然它们非常接近您的原始形式。

SELECT Res, UID, Req FROM TABLE
WHERE  Req = 'A'
    AND UID = (SELECT t2.UID FROM TABLE as t2 WHERE Res = 'to' GROUP BY t2.UID)

SELECT Res, UID, Req FROM TABLE
WHERE  Req = 'A'
    AND UID = (SELECT MIN(t2.UID) FROM TABLE as t2 WHERE Res = 'to') 
于 2012-07-14T15:45:53.097 回答