views:

50

answers:

2

I need to implement a method that takes an address split up into individual parts and returns any matching items from an address table. If no matches are found, I want to be able to return a value indicating where it failed. Each input param has a corresponding field in the table.

The signature would look something like this:

List<Address> MatchAddress(string zipCode, string streetName, string houseNumber, string houseLetter, string floor, string appartmentNo, out int mismatchPosition)
{
  // return matching addresses
  // if none found, return the position where it stopped matching
  // zipCode is position 0, appartmentNo is position 5
  //
  // an empty param value indicates "don't check"
}

I know I can construct the method such that I start with all the parameters, execute the query and then remove param by param (from the right side) until either a match is found or I run out of parameters, but can I construct a query that is more effective than that, i.e minimizing the number of calls to the db, maybe even as a single call?

A: 

here a good link to checkout which will give you several purely SQL methods to do this, with PROs and CONs of each method: Dynamic Search Conditions in T-SQL by Erland Sommarskog

KM
Interesting link, but it doesn't address (no pun intended) my real issue: the need to return a value indicating which param made the query stop matching. Thanks anyway!
peter3
+1  A: 

I think you could get a solution in one query using case statements and some nested queries, but before I go there, I'm not sure I follow what you're trying to accomplish. Assume the following sample data set:

ID   House_Number    Street_Name   Zip_Code
=============================================
1            3012            Elm      10010
2             412            9th      10010
3             412           Main      90210
4             710           Main      60606

Also assume the following method call, passing in a zip, name and house number:

MatchAddress('10010', 'Main', '710')

What would you want to get back in this case? Your signature has a single out variable for the mismatch position, but this example would partially match all four of the records involved on at least one element. What would you want to return for record 1, for instance, where there's a match on zip code, but not on the house_number or street_name attributes?

======================================

OK, saw your comment. Here's a query that I think is on the right path for you. The WHERE clause is a series of ORs that return any record that matches on at least one of the criteria. Then the case statement looks to see where they're not equal to the passed in value. Obviously the least specific match is subjective, but you could re-order the case statement to put the desired match criteria in the order you want. I had this working on a MySQL db here.

SELECT address.*, CASE 
    WHEN zip_code <> '10010' THEN 'No match on Zip'
    WHEN street_name <> 'Elm' THEN 'No match on Street Name'
    WHEN house_number <> '29' THEN 'No match on House Number'
    ELSE 'Match on all elements'
  END AS zip_match
from address
where zip_code = '10010'
OR street_name = 'Elm'
OR house_number = '29'

I've made it return some pretty wordy statements for clarity here, but you could obviously have it return a number code or whatever makes sense for you. This also doesn't take into account issues like case sensitivity. As it's written, it's looking for precise case matching too. Depending on your db environment or how you're data is stored, you may need to address that if that's not what you want.

Greg P
Matching should be done in the order less specific to more specific (i.e Zip_Code, Street_Name, House_Number, etc). In your example, ID 1 and 2 would be returned with the mismatch position set to Street_Name. Here are some more examples:MatchAddress('10010','Elm','412') - returns ID 1 and mismatch set to House_Number. MatchAddress('99999','Elm','3012') - returns nothing and mismatch set to Zip_Code. MatchAddress('10010','','') - returns ID 1 and 2 and no mismatch (since Street_Name and Zip_Code wasn't specified they should be ignored). Hope that helps clarify it
peter3
I just updated my answer with a query. Try it out. Sorry for the delayed response. I'm new to SO and thought I'd get pinged with an email when you commented.
Greg P
Looks like just what I was looking for. Now, let's see if I can turn that into Linq2SQL...
peter3
Excellent. Good luck with the translation to L2S.
Greg P