我目前正致力于搜索功能,用户可以通过主持演出的乐队的名称或演出本身的位置来搜索演出。我遇到的问题是搜索的位置部分,我想搜索我存储的城镇,县和国家字段,以便说出演出位置是“Leeds,Yorkshire,England”并且用户搜索“英语“它会匹配,因为它发现它在国家领域。如果由于利兹的匹配而搜索“编辑”,则同样适用。
我知道这可以通过在查询中使用Group By方法来实现,但是,我正在寻找有关最佳实践的建议以及如何应用它,因为我之前没有使用过Group By。
以下是我开始时的错误查询:
<cfquery datasource="#datasource#" name="findgigs">
Select artist_id, gig_id, gig_artistid, gig_town, gig_county, gig_country
From artists, gigs
Where artist_id = gig_artistid
<cfif IsDefined("URL.search")>
And gig_town LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%>
Or gig_county LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%>
Or gig_country LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%>
</cfif>
</cfquery>
正如我在运行查询后发现的那样(应该事先知道)它会返回许多重复项。但是,查看该查询,您可以看到我想要获取的内容完全以错误的方式完成。任何关于如何改进这方面的知识或建议都将不胜感激。
答案 0 :(得分:3)
<cfquery datasource="#datasource#" name="findgigs">
SELECT artist_id
FROM artists
WHERE artist_id IN
(
SELECT gig_artistid
FROM gigs
WHERE 1 = 0
<cfif structKeyExists(url,'search')>
OR gig_town LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#">
OR gig_county LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#">
OR gig_country LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#">
</cfif>
)
</cfquery>
如果您担心重复的值,此子查询将有助于在不进行分组的情况下解决此问题。
添加cfqueryparam作为帮助反对sql注入的最佳实践
查询的逻辑是“无需启动”,然后如果定义了搜索,则OR将启动,允许显示结果。
选项#2
<cfquery datasource="#datasource#" name="findgigs">
SELECT artist_id
FROM artists
<cfif structKeyExists(url,'search')>
WHERE artist_id IN
(
SELECT gig_artistid
FROM gigs
WHERE gig_town LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#">
OR gig_county LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#">
OR gig_country LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#">
)
</cfif>
</cfquery>
从显示全部开始。如果添加搜索条件,它将开始过滤掉结果以包含您的搜索条件。
答案 1 :(得分:2)
您的WHERE子句不包含OR周围的任何分组。这导致在检查县或国家时忽略初始标准。由于您使用ANSI 89语法来处理您的连接(不指定INNER JOIN),这将破坏您的连接。
有几种方法可以解决这个问题。如果您想继续使用ANSI 89:
<cfquery datasource="#datasource#" name="findgigs">
Select artist_id, gig_id, gig_artistid, gig_town, gig_county, gig_country
From artists, gigs
Where artist_id = gig_artistid
<cfif IsDefined("URL.search")>
And (gig_town LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%">
Or gig_county LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%">
Or gig_country LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%">)
</cfif>
</cfquery>
正如你所看到的,我在那里所做的就是在最后一个cfparam之后添加一个“(”之后的“And”和一个“)”。这会将这些标准组合在一起,因此artist_id标准将用于所有三个标准(防止额外结果)。
如果要更改SQL以显式定义连接(ANSI 92):
<cfquery datasource="#datasource#" name="findgigs">
Select artist_id, gig_id, gig_artistid, gig_town, gig_county, gig_country
From artists
Inner Join gigs ON artist_id = gig_artistid
<cfif IsDefined("URL.search")>
Where gig_town LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%">
Or gig_county LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%">
Or gig_country LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#URL.search#%">
</cfif>
</cfquery>