2009-09-10 29 views
1

我正在为房产中介和租户建立一个网站。租户可以注册并填写他们想要的物业位置,包括街道,城镇和邮政编码。一旦他们注册,这会自动向具有符合这些搜索条件的属性的代理发送电子邮件。SQL Query根据用户输入查找匹配值

目前我的查询设置如下,以便它匹配街道,城镇或邮政编码。

<% 
Dim rspropertyresults 
Dim rspropertyresults_numRows 

Set rspropertyresults = Server.CreateObject("ADODB.Recordset") 
rspropertyresults.ActiveConnection = MM_dbconn_STRING 
rspropertyresults.Source = "SELECT * FROM VWTenantPropertiesResults " 

'WHERE  (ContentStreet = 'Holderness Road') OR (ContentTown = 'Hull') OR (ContentPostCode = 'HU') 

rspropertyresults.Source = rspropertyresults.Source& "WHERE (ContentStreet = '" & Replace(rspropertyresults__varReqStreet, "'", "''") & "'" 

rspropertyresults.Source = rspropertyresults.Source& "OR ContentTown = '" & Replace(rspropertyresults__varReqTown, "'", "''") & "' " 
rspropertyresults.Source = rspropertyresults.Source& "OR ContentTrimmedPostCode = '" & Replace(varPostcode, "'", "''") & "') " 

rspropertyresults.Source = rspropertyresults.Source& "AND ((ContentBedRooms >= " & Replace(rspropertyresults__varBedroomsNoMin, "'", "''") & " " 
rspropertyresults.Source = rspropertyresults.Source& "AND ContentBedRooms <= " & Replace(rspropertyresults__varBedroomsNoMax, "'", "''") & ") " 

rspropertyresults.Source = rspropertyresults.Source& "AND (ContentPrice > = " & Replace(rspropertyresults__varPriceMin, "'", "''") & " " 
rspropertyresults.Source = rspropertyresults.Source& "AND ContentPrice <= " & Replace(rspropertyresults__varPriceMax, "'", "''") & ")) " & varSQL & " " 

rspropertyresults.Source = rspropertyresults.Source& "ORDER BY ContentPrice " & Replace(rspropertyresults__varSortWay, "'", "''") & " " 

rspropertyresults.CursorType = 0 
rspropertyresults.CursorLocation = 2 
rspropertyresults.LockType = 1 
rspropertyresults.Open() 

rspropertyresults_numRows = 0 
%> 

但是,客户端已要求,而不是只对其中一个值匹配,它需要以这样的方式来工作,如果说街道和镇的比赛,然后通过电子邮件发送一个房地产经纪人,或者城市和邮政编码匹配,然后发送该物业代理。如你所想,我认为查询会变得相当复杂,但我不确定如何最好地设计这样的查询。

我想知道是否有人能够帮助或指向正确的方向吗?

回答

4
SELECT * 
FROM (
     SELECT id 
     FROM (
       SELECT id 
       FROM VWTenantPropertiesResults 
       WHERE ContentStreet = 'Holderness Road' 
       UNION ALL 
       SELECT id 
       FROM VWTenantPropertiesResults 
       WHERE ContentTown = 'Hull' 
       UNION ALL 
       SELECT id 
       FROM VWTenantPropertiesResults 
       WHERE ContentPostCode = 'HU' 
       ) qi 
     GROUP BY 
       id 
     HAVING COUNT(*) >= 2 
     ) q 
JOIN VWTenantPropertiesResults r 
ON  r.id = q.id 
WHERE ContentBedrooms BETWEEN 1 AND 4 
     AND ContentPrice BETWEEN 50 AND 500 
ORDER BY 
     ContentPrice 

这会返回至少有2条件匹配的所有记录。

此解决方案适合索引:与OR子句不同,它将使用ContentStreet,ContentTownContentPostCode上的索引。

参见性能细节在我的博客此项:

为了获得最佳的性能和安全性,以及绑定参数替换取代的参数值。

这将节省您在查询分析上的时间,并会保护您免受SQL注入。

+1

+1:好的解决方案 - 也许在这种情况下UNION ALL会更好,因为无论如何你都是按ID分组的? – RedFilter 2009-09-10 13:59:01

+0

Hey Quassnoi, 谢谢你的解决方案。我已经在视图中试过这个,首先看它是否正确执行。 (我也改变了ID到ContentID)。它执行,但不返回任何结果。 这可能是我有其他干扰结果的东西。我知道肯定有一些数据会匹配2或3个条件。 – doubleplusgood 2009-09-10 13:59:21

+0

'@ OrbMan':对,谢谢。不仅更好,而且需要查询才能正常工作。 – Quassnoi 2009-09-10 14:03:42

3

在您的网站中包含SQL是不好的做法IMO。但我对asp-classic并不熟悉。此外,你这样做,你有可能从SQL注入危险。不要混用UI和数据访问逻辑。

http://en.wikipedia.org/wiki/SQL_injection

+0

ASP经典中没有任何内容阻止使用最佳实践,如独立模型层,参数化查询,断开连接的记录集,连接池等。 – RedFilter 2009-09-10 14:01:34

1

这是创建存储过程来处理你所描述的逻辑SQL是一个好主意。在ASP代码中,您可以使用用户提供的参数调用此过程。这可以避免动态创建SQL的问题,并且使这个问题更容易处理。

请参阅http://authors.aspalliance.com/stevesmith/articles/sprocs.asp了解使用ADODB和存储过程的几个示例。

+0

请注意,不需要使用存储过程来实现参数化查询。 – RedFilter 2009-09-10 14:03:07

+0

绝对如此。我在这里倡导SP作为一个更清洁,更集中的方式来影响OP想要实现的目标。 – 2009-09-10 14:25:12

0

我在类似情况下使用的一种方法是,如果您使用LIKE而不是column = value,那么您可以在任何字段组合中使用任何值。例如:

WHERE town LIKE('%'+ @town +'%')和zip LIKE('%'+ @zip'%')AND street like('%'+ @street'%') AND等

然后,如果他们只填写了一些字段,它仍然会返回有效结果。这种方法的主要特点是所有的字段都需要字符串值,因为LIKE不适用于数字类型的列。所以你必须对数字字段进行一些转换,这可能会让一些东西变得麻烦,这取决于需要完成多少转换,所以这是一种给予和采取的一种情况。

我也会同意,这确实应该在传递参数的存储过程中进行搜索。