在查询中搜索多个列

时间:2013-04-22 11:49:18

标签: sql coldfusion group-by

我目前正致力于搜索功能,用户可以通过主持演出的乐队的名称或演出本身的位置来搜索演出。我遇到的问题是搜索的位置部分,我想搜索我存储的城镇,县和国家字段,以便说出演出位置是“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>

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

2 个答案:

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

  2. 添加cfqueryparam作为帮助反对sql注入的最佳实践

  3. 查询的逻辑是“无需启动”,然后如果定义了搜索,则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>