2009-09-10 5 views
1

Je suis en train de créer un site Web pour les agents immobiliers et les locataires. Les locataires peuvent s'inscrire et remplir leurs emplacements souhaités pour les propriétés, y compris la rue, la ville et le code postal. Une fois qu'ils se sont inscrits, cela envoie automatiquement des courriels aux agents dont les propriétés correspondent à ces critères de recherche.Requête SQL pour trouver les valeurs correspondantes en fonction de l'entrée de l'utilisateur

Actuellement, la requête est configurée comme suit pour qu'elle corresponde à la rue, à la ville ou au code postal.

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

Cependant, le client a demandé qu'au lieu de faire correspondre seulement sur l'une des valeurs, il a besoin de travailler de telle sorte que si par exemple Street et match de ville, courriel puis cet agent immobilier ou si Ville et code postal correspondre, puis envoyer un email à cet agent immobilier.

Comme vous pouvez l'imaginer, je pense que la requête deviendrait assez complexe, mais je ne sais pas comment concevoir au mieux une requête comme celle-ci.

Je me demandais si quelqu'un pouvait m'aider ou m'aider dans la bonne direction?

Répondre

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 

Cela vous ramènera tous les enregistrements où match au moins 2 conditions.

Cette solution est conviviale indice: contrairement à OR clauses, il utilisera des index sur ContentStreet, ContentTown et ContentPostCode.

Voir cette entrée dans mon blog pour les détails de la performance:

Pour obtenir de meilleures performances et la sécurité, remplacer les valeurs des paramètres substitués par des paramètres liés. Cela vous fera gagner du temps lors de l'analyse des requêtes et vous protègera contre les injections SQL.

+1

+1: Bonne solution - peut-être UNION ALL serait mieux dans ce cas, puisque vous groupez par ID de toute façon? – RedFilter

+0

Hey Quassnoi, Nous vous remercions de votre solution. J'ai essayé ceci juste dans une vue d'abord pour voir si elle s'exécute correctement. (J'ai également changé les identifiants à ContentID). Il s'exécute, mais ne renvoie aucun résultat. Cela pourrait être que j'ai autre chose qui interfère avec les résultats. Je sais qu'il y a certainement des données qui correspondent à 2 ou 3 des conditions. – doubleplusgood

+0

'@ OrbMan': à droite, merci. Non seulement c'est mieux, mais il est nécessaire que la requête fonctionne correctement. – Quassnoi

3

L'inclusion de SQL dans votre site Web est une mauvaise pratique IMO. Mais je ne suis pas familier avec asp-classic. Aussi la façon dont vous faites cela, vous êtes en danger de l'injection SQL. Ne mélangez pas l'interface utilisateur et la logique d'accès aux données.

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

+0

Il n'y a rien dans ASP classic qui empêche l'utilisation des meilleures pratiques comme la couche modèle séparée, les requêtes paramétrées, les jeux d'enregistrements déconnectés, le pooling de connexion, etc. – RedFilter

1

Ce serait une bonne idée de créer une procédure stockée SQL pour gérer la logique que vous avez décrit. En code ASP, vous pouvez appeler cette procédure avec les paramètres fournis par l'utilisateur. Cela évite les problèmes de création dynamique de SQL et rend également ce problème un peu plus facile à résoudre.

Voir http://authors.aspalliance.com/stevesmith/articles/sprocs.asp pour quelques exemples d'utilisation d'ADODB avec des procédures stockées.

+0

Notez qu'il n'est pas nécessaire d'utiliser une procédure stockée pour implémenter des requêtes paramétrées. – RedFilter

+0

Absolument vrai. Je préconise que les PS soient plus propres et plus ciblés pour atteindre les objectifs que le PO veut atteindre. –

0

Une approche que j'ai utilisée dans une situation similaire est si vous utilisez LIKE, plutôt que colonne = valeur, alors vous pouvez utiliser n'importe quelle valeur dans n'importe quelle combinaison de champs. Par exemple:

WHERE ville LIKE ('%' + @town + '%') et zip LIKE ('%' + @zip '%') ET rue LIKE ('%' + @street '%') ET etc

Ensuite, il ne serait pas important s'ils remplissaient seulement certains des champs, il renverrait toujours des résultats valides.Les principales captures à cette approche, est que tous les champs doivent être des valeurs de chaîne car LIKE ne fonctionne pas avec des colonnes de type numérique. Il faudrait donc faire du casting sur des champs numériques, ce qui pourrait ralentir les choses en fonction de la quantité de conversion à effectuer, donc c'est une sorte de «donner et prendre».

Je suis également d'accord que cela devrait vraiment être fait dans une procédure stockée passant dans les paramètres pour les champs à rechercher.

Questions connexes