2010-12-10 67 views
0

我正在寻找一种方法来使用Coldfusion在多个关键字的sql表中搜索多个列。我目前有以下代码,一半工作。SQL查询 - 多个关键字搜索多列

<cfquery name="rsSearchEmployees" datasource="#request.database#"> 
SELECT idn, firstname, lastname 
FROM Employees 
WHERE (<cfloop list="#arguments.nameSearchString#" delimiters=" " index="word">firstname LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#Trim(word)#%" /> OR </cfloop> (1 <> 1)) 
OR (<cfloop list="#arguments.nameSearchString#" delimiters=" " index="word">lastname LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#Trim(word)#%" /> OR </cfloop> (1 <> 1)) 
ORDER BY firstname ASC 

它搜索2列,名字和姓氏的关键字输入到一个文本框。关键字使用cfloop标签进行分解。

此代码确实会生成结果,但如果在一列或两列中未找到2个或更多关键字,则当前不会删除结果。

例如,假设我想搜索史蒂夫史密斯,当我输入史蒂夫时,它显示了史蒂夫的行。史密斯也是如此。如果我输入史蒂夫史密斯,它仍然显示正确的行。

当我输入类似史蒂夫乔布斯的东西时,它会出错。键入这个仍然显示史蒂夫史密斯什么时候不应该。有没有人有线索如何解决这个问题?

感谢您提前提供任何帮助。 Chris

+0

是否有理由不能在'WHERE'子句中将'OR'更改为'AND'? – JNK 2010-12-10 13:58:56

+0

你想要什么结果“史密斯史蒂夫”? – 2010-12-10 14:12:15

+0

我可以改变条件,尝试所有不同的变化,但都不提供正确的结果。史蒂夫史密斯,我希望它显示结果,我不希望它显示史蒂夫乔布斯的结果。谢谢 – Chris 2010-12-10 14:19:15

回答

2

克里斯,你可以运行一个另类“或” SQL,

我认为你的问题的核心是你的逻辑当前在说“显示所有记录中FirstName或LastName与搜索字符串中某个单词相匹配的记录”。您允许某人搜索“马修马克卢克约翰”作为一个字符串,将任何这些姓名的人拉进来,而不是将搜索词作为单一名称。

由于仅在firstName上匹配,这导致记录“Steve Jobs”出现搜索='Steve Smith'的事实。听起来像SQL逻辑太宽泛。

听起来像你想要一个搜索,而不是一个多重姓名列表匹配的字符串全名(名字+姓氏)。但是,如果提供了多个单词,则希望快速缩小与所有单词不匹配的记录的范围。

名字可能是复杂的事情,名字或姓氏是多个单词。这提出了一些小问题。

期望的结果:

  • 搜索“艾伦” - 弹出记录 以“阿伦”
  • 搜索“艾伦·史密斯”姓或名调出记录 与姓和名相匹配 反对“艾伦”和/或“史密斯”

这个查询将允许在搜索字符串的话,但只有每个字以某种方式(相匹配的节目记录的任何#允许搜索任何名字订单,例如。首先末尾或末尾首先)。这可能是你想要的。

SELECT idn, firstname, lastname 
FROM Employees 
WHERE 1=1 
<cfloop list="#arguments.nameSearchString#" delimiters=" " index="word"> 
    AND (firstname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#word#%" /> 
    OR lastname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#word#%" />) 
</cfloop> 
+0

感谢Mujimu,这工作完美,现在已经实现了! – Chris 2010-12-13 09:32:49

+0

很高兴协助... – mujimu 2011-05-05 16:33:54

+0

这很好,但为了别人的利益,我没有得到我的搜索“福特猎鹰”的回报,直到我在值的前面添加了“%”=“#字#%” “,即值=”%#word#%“ – user460114 2016-04-25 23:13:30

1

你用LIKE包装LIKE子句的两侧告诉我你真的想要一些模糊匹配。我会跳过SQL WHERE语句,而是使用全文解决方案。选项包括:

  1. 数据库全文索引:SQL Server,Oracle和MySQL都有解决方案。
  2. 搜索引擎:ColdFusion的9艘船既Verity的和SOLR

这些选项要么会让你的生活更容易,避免了复杂的和/或类似的逻辑,就需要在一个SQL引进WHERE子句达到一些类似的效果。

+0

感谢你们,我一直在使用Coldfusion很长一段时间,但只在初学者水平。我已经看到Verity的相关信息,但对于它的工作原理还没有太多的线索,或者我可以如何使用它。另一个问题是即时使用共享主机,所以这会受到影响?此外,这个查询是AJAX repsonse的一部分。 – Chris 2010-12-10 15:48:31

+1

共享主机可能是设置Verity/SOLR的一个问题,您需要与您的提供商讨论。可能更容易在数据库端获得全文索引设置。无论哪种情况,您都可以使用这些“模糊搜索”解决方案之一来获取employee表的主键列表,然后运行SQL语句以使用IN子句检索这些键。在这两种情况下,仍然可以通过AJAX格式从服务器发回响应。另外,你使用的是什么数据库? – orangepips 2010-12-10 17:00:06

+0

我们正在使用MySQL5 – Chris 2010-12-13 09:28:54

0

做出一些假设,就像你总是输入“姓氏”和“姓氏”一样,寻找并且你想在存根上进行模糊搜索,例如,史密斯......回报史密斯,史密斯等,这可能会做到这一点。你可以放回到你的领导%,如果你真的想匹配的铁匠,铁匠等

<cfquery name="rsSearchEmployees" datasource="#request.database#"> 
SELECT idn, firstname, lastname 
FROM Employees 
WHERE firstname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(word)#%" /> 
AND lastname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(word)#%" /> 
</cfquery> 

如果搜索只有一个字为