获取多个子行满足不同条件的父行

问题描述 投票:1回答:2

在我的数据库中,我有两个表:T_INDEXT_INDEXCALLER。这是一对多的关系。每个索引记录可以有多个调用者(由IndexId引用)。

在我的应用程序的前端,我有两个搜索字段:名称和扩展名。这两个字段都引用了T_INDEXCALLER表。在我的搜索算法中,我需要能够“and”这两个领域。我需要返回具有一个或多个子记录的T_INDEX记录,其中“Name”匹配,并且具有一个或多个子记录,其中“Extension”匹配。

这是我目前使用的查询:

DECLARE @name varchar(100);
DECLARE @extension varchar(100);
SET @name = 'fox';
SET @extension = '9039';

SELECT *
FROM T_INDEX
WHERE T_INDEX.IndexId IN (SELECT IndexId FROM T_INDEXCALLER WHERE Name = @name)
AND T_INDEX.IndexId IN (SELECT IndexId FROM T_INDEXCALLER WHERE ExtensionNumber = @extension)

这有效,但效率不高。有大约1000万条索引记录,甚至更多的来电记录。有没有办法使用连接重写这​​个搜索查询,这将消除内部SELECT的需要(并且更有效)?

我遇到的问题是,当我用连接重新编写它时,我只获得具有子记录的T_INDEX记录,其中两个条件在同一子记录上匹配。我想获得具有与名称条件匹配的子记录的T_INDEX记录,以及与分机号码条件匹配的单独子记录。

sql sql-server
2个回答
1
投票

我可以先用exists写这个:

SELECT i.*
FROM T_INDEX i
WHERE EXISTS (SELECT 1
              FROM T_INDEXCALLER ic
              WHERE ic.Name = @name AND i.IndexId = ic.IndexId
             ) AND
      EXISTS (SELECT 1
              FROM T_INDEXCALLER ic
              WHERE ic.ExtensionNumber = @extension AND i.IndexId = ic.IndexId
             );

这可以利用索引T_INDEXCALLER(indexId, Name, ExtensionNmber)

这可以提供一些加速。另一种选择是:

SELECT i.*
FROM T_INDEX i JOIN
     (SELECT ic.indexId
      FROM ((SELECT ic.indexId, 1 as priority
             FROM T_INDEXCALLER
             WHERE ic.ExtensionNumber = @extension
            ) UNION ALL
            (SELECT ic.indexId, 2 as priority
             FROM T_INDEXCALLER
             WHERE ic.Name = @name
            )
           ) ic
      GROUP BY ic.indexId
      HAVING MIN(priority) = 1 AND MAX(priority) = 2
     ) ic
     ON ic.indexId = i.indexId;

这可以利用T_INDEXCALLER(name, indexId)T_INDEXCALLER(ExtensionNumber, indexId)和(非常重要的)T_INDEX(indexId)的索引。


0
投票

我不确定你是如何应用连接逻辑的,但根据你的要求,在ON子句中使用OR条件应该可以完成这项工作。

  SELECT *
  FROM
  T_INDEX A INNER JOIN T_INDEXCALLER B
  ON A.IndexId = B.IndexId
  AND (B.Name = @name OR B.ExtensionNumber = @extension);

我不能说出执行速度,但如果没有任何作用,你可以使用这个作为替代。

© www.soinside.com 2019 - 2024. All rights reserved.