0

我目前正在开发一个搜索功能,用户可以通过主持演出的乐队的名称或演出本身的位置来搜索演出。我遇到的问题是搜索的位置部分,我想搜索我存储的城镇、县和国家字段,以便说明演出地点是否是“英格兰约克郡利兹”并且用户搜索“ Eng" 它会匹配,因为它在国家/地区字段中找到了它。如果他们因为在利兹的比赛而搜索“eds”,同样适用。

我知道这可以通过在查询中使用 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>

正如我在运行查询后发现的(应该事先知道)它返回许多重复项。但是,查看该查询,您可以看到我试图获取它的内容完全以错误的方式完成。任何有关如何改进这一点的知识或建议将不胜感激。

4

2 回答 2

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>
  1. 如果您担心重复的值,这个子查询将有助于在不分组的情况下解决这个问题。

  2. 添加了 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>

从显示所有开始。如果添加了搜索条件,它将开始过滤掉结果以包含您的搜索条件。

于 2013-04-22T12:37:14.250 回答
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 之后添加一个“(”和一个“)”。这会将这些标准组合在一起,以便针对所有三个标准使用 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>
于 2013-04-23T17:52:31.437 回答