更快的方法来执行此选择查询

时间:2009-09-01 19:50:42

标签: sql nhibernate

Say Employee有三列 FirstName,LastName和ID。

查询首先应在名字中搜索名称,仅在未找到时搜索姓氏。

所以从员工中选择*,其中FirstName ='test%'或lastname ='test'%'。不会工作。

以下查询将有效。

select FirstName, LastName, ID
from EMPLOYEE
WHERE 
    LastName = 'Test%'
    AND
    (COUNT(SELECT FirstName, LastName, ID FROM EMPLOYEE WHERE FirstName = 'Test%')=0)
    OR
    SELECT FirstName, LastName, ID FROM EMPLOYEE WHERE FirstName = 'Test%'

我需要将此映射回NHibernate,是否有更快捷的方式来执行此操作而不是进行两次数据库调用?

5 个答案:

答案 0 :(得分:1)

FROM Employee
WHERE (FirstName LIKE 'Test%' AND LastName NOT LIKE 'Test%')
OR (LastName LIKE 'Test%' AND firstName NOT LIKE 'Test%')

当然,你不关心他们回来的顺序。如果记录必须带有第一个名字匹配的记录,然后是姓氏匹配的名字,那么这将不起作用。

答案 1 :(得分:1)

试试这个:

SELECT FirstName, LastName, ID FROM EMPLOYEE WHERE FirstName = 'Test%'
OR (FirstName <> 'Test%' AND LastName = 'Test%')

答案 2 :(得分:1)

“过早优化是万恶之源”。

为什么你会关心优化程序看到的搜索方式,而不是声明你想要的东西?
这一切都归结为一个布尔真值表:当FirstName匹配时,你想要记录(无论是LastName,匹配还是nomatch),如果FirstName不匹配,你需要LastName匹配时的记录:

F match,   L match   => yes
F match,   L nomatch => yes
F nomatch, L match   => yes
F nomatch, L nomatch => no

这正是OR条件:(FirstName matching) OR (LastName matching);唯一丢弃的记录是FirstName和LastName都不匹配时。

布尔值优化将确保在第一个条件为真时甚至不评估第二个条件。

所以你的查询是:

SELECT FirstName, LastName, ID
FROM Employee
WHERE (FirstName LIKE 'Test%')
   OR (LastName LIKE 'Test%')

更新:如果发现仅包含FirstName的记录,我可能误解了目标是否确实没有返回任何LastName匹配...
无论如何,过早优化的立场仍然有效......
您需要以某种方式获得2遍查询,因为在您确定FirstName上没有任何匹配之前,您无法判断是否要考虑LastName。但是使用适当的索引和统计信息,优化器将使其非常高效。

查询:

SELECT FirstName, LastName, ID
FROM   Employee 
WHERE  (FirstName LIKE 'Test%')
    OR (LastName LIKE 'Test%'
        AND (SELECT Count(ID)
             FROM   Employee
             WHERE  FirstName LIKE 'Test%') = 0) 

只比以前贵一点。

答案 3 :(得分:0)

Select * 
From Employee 
Where FirstName Like @Text + '%'

Union

Select * 
From Employee 
Where LastName Like @Text + '%';

答案 4 :(得分:0)

我认为这些查询都没有回答这个问题。我的理解是,搜索“John%”应该返回姓氏为John,Johnson等的员工,只要没有名字为John,Johnny等的员工。所有查询显示将返回John Adams和Lyndon Johnson如果表中包含两者,但只有John Adams应该出现,因为如果没有匹配的名字,则只应匹配姓氏。

以下是使用SQL Server语法的提案。应该可以用SQL的其他方言来写这个:

select top (1) with ties
  FirstName, LastName, ID
from (
  select
    0 as SearchLastNames,
    FirstName, LastName, ID
  from EMPLOYEE
  where FirstName like 'Test%'
  union all
  select
    1 as SearchLastNames,
    FirstName, LastName, ID
  from EMPLOYEE
  where LastName like 'Test%'
) as T
order by SearchLastNames;

如果有任何匹配的名字,最小的SearchLastNames值将为0,并且具有关系的TOP(1)...按SearchLastNames排序将仅返回名字匹配的信息(其中SearchLastNames为0)。

如果没有匹配的名字,则唯一的SearchLastNames值为1.在这种情况下,TOP将返回所有姓氏匹配的信息(其中SearchLastNames为1),如果有的话。

这是一个更笨拙但更便携的解决方案:

  select
    FirstName, LastName, ID
  from EMPLOYEE
  where FirstName like 'Test%'
  union all
  select
    FirstName, LastName, ID
  from EMPLOYEE
  where LastName like 'Test%'
  and not exists (
    select
    FirstName, LastName, ID
    from EMPLOYEE
    where FirstName like 'Test%'
  );