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,是否有更快捷的方式来执行此操作而不是进行两次数据库调用?
答案 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%'
);