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

时间:2017-12-27 20:09:07

标签: sql sql-server

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

在我的应用程序的前端,我有两个搜索字段:Name和Extension。这两个字段都引用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条记录,以及与分机号条件匹配的单独子记录。

2 个答案:

答案 0 :(得分: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)上的索引。

答案 1 :(得分:0)

我不确定您是如何应用连接逻辑的,但根据您的要求,在package question import scalaz._ import Scalaz._ import effectful._ object DSL { type GotoLabel = Int type Expr[A] = ReaderWriterState[Unit, List[Action], GotoLabel, A] type Stmt = Expr[Unit] def runStmt(stmt: Stmt, startLabel: GotoLabel): (Action, GotoLabel) = { val (actions, _, updatedLabel) = stmt.run(Unit, startLabel) val action = actions match { case List(action) => action case _ => Seq(actions) } (action, updatedLabel) } def runStmt(stmt: Stmt): Action = runStmt(stmt, 0)._1 def getLabel(): Expr[GotoLabel] = ReaderWriterState((_, label) => (Nil, label, label)) def setLabel(label: GotoLabel): Stmt = ReaderWriterState((_, _) => (Nil, Unit, label)) implicit def actionStmt(action: Action): Stmt = ReaderWriterState((_, label) => (List(action), Unit, label)) } import DSL._ final case class Label(label: String) extends Action final case class Goto(label: String) extends Action final case class Seq(seq: List[Action]) extends Action sealed trait Action { def stmt(): Stmt = this } object Main { def freshLabel(): Expr[String] = effectfully { val label = getLabel.! + 1 setLabel(label).! s"ants-$label" } def passes0() = freshLabel() .flatMap(before => Label(before)) .flatMap(_ => freshLabel()) .flatMap(after => Label(after)); def passes1() = effectfully { unwrap(actionStmt(Label(unwrap(freshLabel())))) unwrap(actionStmt(Label(unwrap(freshLabel())))) } def fails1() = effectfully { unwrap(Label(unwrap(freshLabel()))) unwrap(Label(unwrap(freshLabel()))) } def pasess2() = effectfully { Label(freshLabel.!).stmt.! Label(freshLabel.!).stmt.! } def fails2() = effectfully { Label(freshLabel.!).! Label(freshLabel.!).! } def main(args: Array[String]): Unit = { runStmt(passes0()) } } 子句中使用OR条件可以完成这项工作。

ON

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