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

Sql 执行此选择查询的更快方法,sql,nhibernate,Sql,Nhibernate,假设Employee有三列 名字、姓氏和ID 查询应首先在firstname中搜索名称,仅当未找到该名称时搜索姓氏 因此,请从名为“test%”或名为“test%”的员工中选择*。他不会工作的 下面的查询将起作用 select FirstName, LastName, ID from EMPLOYEE WHERE LastName = 'Test%' AND (COUNT(SELECT FirstName, LastName, ID FROM EMPLOYEE WHER

假设Employee有三列 名字、姓氏和ID

查询应首先在firstname中搜索名称,仅当未找到该名称时搜索姓氏


因此,请从名为“test%”或名为“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,有没有一种更快更有效的方法来代替两次数据库调用

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

Union

Select * 
From Employee 
Where LastName Like @Text + '%';
就算你不在乎他们回来的顺序。如果记录必须返回与名字匹配的记录,然后是与姓氏匹配的名称,那么这将不起作用

就算你不在乎他们回来的顺序。如果返回的记录必须是名字匹配的记录,然后是姓氏匹配的记录,那么这将不起作用。

尝试一下:

SELECT FirstName, LastName, ID FROM EMPLOYEE WHERE FirstName = 'Test%'
OR (FirstName <> 'Test%' AND LastName = 'Test%')
从员工中选择FirstName、LastName、ID,其中FirstName='Test%'
或(FirstName'Test%'和LastName='Test%')
试试这个:

SELECT FirstName, LastName, ID FROM EMPLOYEE WHERE FirstName = 'Test%'
OR (FirstName <> 'Test%' AND LastName = 'Test%')
从员工中选择FirstName、LastName、ID,其中FirstName='Test%'
或(FirstName'Test%'和LastName='Test%')
“过早优化是万恶之源”

为什么您会关心优化器所看到的搜索是如何完成的,而不是声明您想要什么?
这一切归结为一个布尔真值表:当FirstName匹配时,需要记录(LastName、match或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和LastName不匹配时才会丢弃记录

布尔优化将确保当第一个条件为真时,第二个条件甚至不会被计算

所以你的问题是:

SELECT FirstName, LastName, ID
FROM Employee
WHERE (FirstName LIKE 'Test%')
   OR (LastName LIKE 'Test%')
更新:如果确实不返回任何与姓氏匹配的记录(如果只找到姓氏的记录),我可能误解了目标…
无论如何,关于过早优化的立场仍然有效…
不知何故,您需要一个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) 
只比之前的价格稍微贵一点。

“过早优化是万恶之源”

为什么您会关心优化器所看到的搜索是如何完成的,而不是声明您想要什么?
这一切归结为一个布尔真值表:当FirstName匹配时,需要记录(LastName、match或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和LastName不匹配时才会丢弃记录

布尔优化将确保当第一个条件为真时,第二个条件甚至不会被计算

所以你的问题是:

SELECT FirstName, LastName, ID
FROM Employee
WHERE (FirstName LIKE 'Test%')
   OR (LastName LIKE 'Test%')
更新:如果确实不返回任何与姓氏匹配的记录(如果只找到姓氏的记录),我可能误解了目标…
无论如何,关于过早优化的立场仍然有效…
不知何故,您需要一个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) 

只比前一个稍微贵一点。

我认为这些问题都不能回答这个问题。我的理解是,搜索“John%”时应返回姓氏为John、Johnson等的员工。只有当没有姓氏为John、Johnny等的员工时,才会返回。如果表中同时包含John Adams和Lyndon Johnson,则显示的所有查询都将返回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,顶部(1)的值将为ties。。order by 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%'
  );

我认为这些问题都不能回答这个问题。我的理解是,搜索“John%”时应返回姓氏为John、Johnson等的员工。只有当没有姓氏为John、Johnny等的员工时,才会返回。如果表中同时包含John Adams和Lyndon Johnson,则显示的所有查询都将返回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,顶部(1)的值将为ties。。order by 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%'
  );

我真的不认为您需要担心编写两个数据库调用的开销