在我的数据库中,我有两个表:T_INDEX
和T_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
条记录,以及与分机号条件匹配的单独子记录。
答案 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
我不能说出执行速度,但如果没有任何作用,你可以使用这个作为替代。