2009-09-10 64 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不適用於數字類型的列。所以你必須對數字字段進行一些轉換,這可能會讓一些東西變得麻煩,這取決於需要完成多少轉換,所以這是一種給予和採取的一種情況。

我也會同意,這確實應該在傳遞參數的存儲過程中進行搜索。