doubleplusgood
doubleplusgood

Reputation: 2556

SQL Query to find matching values based on user input

I'm building a website for property agents and tenants. Tenants can sign up and fill in their desired locations for properties, including Street, Town and Postcode. Once they sign up, this automatically emails agents who have properties that match those search criteria.

At present I have the query set up as follows so that it matches on either the Street, Town or Postcode.

<%
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
%>

However, the client has asked that instead of just matching on one of the values, it needs to work in such a way that if say Street and Town match, then email that property agent or if Town and Postcode match, then email that property agent.

As you can imagine, I think the query would become quite complex, but i'm unsure how to best design a query like this.

I wondered if anyone might be able to help or point me in the right direction?

Upvotes: 1

Views: 3429

Answers (4)

Quassnoi
Quassnoi

Reputation: 425603

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

This will return you all records where at least 2 conditions match.

This solution is index friendly: unlike OR clauses, it will use indexes on ContentStreet, ContentTown and ContentPostCode.

See this entry in my blog for performance detail:

For best performance and security, replace substituted parameter values with bound parameters.

This will save you time on query parsing and will protect you against SQL injection.

Upvotes: 4

BBlake
BBlake

Reputation: 2398

An approach I've used in a similar situation is if you make use of LIKE, rather than column = value, then you can make use of any values in any combination of fields. For instance:

WHERE town LIKE ('%' + @town + '%') and zip LIKE ('%' + @zip '%') AND street LIKE ('%' + @street '%') AND etc

Then it wouldn't matter if they only filled out some of the fields, it would still return valid results. The main catches to this approach, is all the fields would need to be string values as LIKE doesn't work with numeric type columns. So you would have to do some casting on numeric fields, which could bog things down some depending on how much conversion needs to be done, so it's a give and take kind of situation.

I would also agree that this really should be done in a stored procedure passing in parameters for the fields to search on.

Upvotes: 0

David Andres
David Andres

Reputation: 31781

It would be a good idea to create a SQL Stored Procedure to handle the logic you've described. In ASP code, you can call into this procedure with the user-supplied parameters. This avoids issues with dynamically creating SQL and also make this problem a bit easier to tackle.

See http://authors.aspalliance.com/stevesmith/articles/sprocs.asp for a few examples of using ADODB with stored procedures.

Upvotes: 1

pero
pero

Reputation: 4259

Including SQL in your web site is bad practice IMO. But I am not familiar with asp-classic. Also the way you do this you are in danger from SQL injection. Don't mix UI and data access logic.

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

Upvotes: 3

Related Questions