2009-09-01 81 views
0

说员工有三列 名字,姓氏和ID。更快的方法来做到这一点选择查询

该查询应首先搜索名字中的名字,仅当其未找到时搜索姓氏。

so select * from Employee where 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,有没有更快的有效的方式来做到这一点,而不是做两个数据库调用?

+1

我真的不认为你需要担心写两个数据库调用的开销。 – Juliet 2009-09-01 19:57:11

+0

只要FirstName和LastName都是索引的,几乎任何非愚蠢的查询都会非常有效(除非您的数据库拥有数百万条记录)。 – Brian 2009-09-01 19:57:16

+0

“so select * from Employee where FirstName ='test%'or Lastname ='test'%'。wont'work。” 如果您在FirstName匹配时始终需要记录(不管LastName是什么),那么这确实是查询。详情请参阅我的回答。 – 2009-09-02 01:07:02

回答

1

给这一个尝试:

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

名字<>'测试%'是不必要的。做真相表... – 2009-09-02 01:01:49

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

Union 

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

人们会解释他们为什么拒绝投票吗? – ChaosPandion 2009-09-01 19:55:38

+0

我没有downvote,但我不认为这回答了这个问题。 “查询应该首先搜索名字中的名字,但前提是找不到名字搜索。” – 2009-09-01 19:58:07

+0

这将用于没有程序的目的。 – ChaosPandion 2009-09-01 19:59:04

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

就算你不在乎他们来什么样的顺序回。如果记录必须与第一名称匹配的记录回来,其次是名称,其中姓氏匹配,那么这将无法工作。

+0

在4000个条目的数据集上,最终速度是前者的两倍,尽管您可能已经知道这一点。 – ChaosPandion 2009-09-01 20:13:41

+0

这是专门针对SQL Server的。 – ChaosPandion 2009-09-01 20:14:16

+0

此查询在HQL中。我已经做了几乎这完全在我的系统上,授予它是Hibernate,而不是NHibernate,它工作 – Zoidberg 2009-09-01 20:45:16

1

“过早的优化是所有罪恶的根源。”

为什么要关注如何在优化器看到它时完成搜索,而不是声明你想要的?
这一切都归结为一个布尔真值表:名字相匹配的时候,你想记录(无论是名字,比赛或NOMATCH),如果名字不匹配,你想要的记录时,名字相匹配:

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);唯一的丢弃记录是当名字和姓氏不匹配时。

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

所以您查询的是:

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

更新:我可能误解了目标,如果它确实不返回任何名字匹配如果记录被发现只用名字...
不管怎么说,过早优化的立场仍然有效...
你需要某种方式2传递查询,因为你不能分辨是否要考虑姓氏,直到你确定你没有在名字上的任何匹配。但是,通过适当的索引和统计数据,优化器将使其非常高效。

查询:

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) 

只是比以前稍微贵一些。

0

我不认为这些查询都可以回答这个问题。我的理解是,如果没有雇员名字叫约翰,约翰尼等,那么对'约翰%'的搜索应该返回名字为约翰,约翰逊等的雇员。所有查询显示将返回约翰亚当斯和林登约翰逊如果表包含两个,但只有约翰亚当斯应该出现,因为姓氏应匹配只有当没有匹配的名字。

这是一个使用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%' 
); 
相关问题