I would modify JamesK's approach as follows (no need for the multiplication that I can see?)
SELECT
.....,
CASE WHEN @FirstName = FirstName THEN 10 ELSE 0 +
CASE WHEN @LastName = LastName THEN 10 ELSE 0 +
CASE WHEN @DOB = DOB THEN 20 ELSE 0 +
CASE WHEN @SSN = SSN THEN 100 ELSE 0 +
CASE WHEN @Address = [Address] THEN 30 ELSE 0 END AS
CombinedWeight
FROM YourTable
WHERE FirstName = @FirstName
OR LastName = @LastName
OR DOB = @DOB
OR SSN = @SSN
OR [Address] = @Address
ORDER BY
CombinedWeight DESC;
the problem is that the WHERE clause is very inefficient.
An alternative, which might be faster, would be:
CREATE TABLE #TEMP
(
T_ID int, -- Whatever is the PKey for your table
PRIMARY KEY
(
T_ID
)
)
--
DECLARE @intTotalResults int = 0,
@MaxResultsRequired int = 500 -- Number of results required
--
-- Highest weighting queries first
IF @SSN IS NOT NULL
BEGIN
INSERT INTO #TEMP
SELECT YourPKey
FROM YourTable
WHERE SSN = @SSN
SELECT @intTotalResults = @intTotalResults + @@ROWCOUNT
--
IF @intTotalResults > @MaxResultsRequired GOTO DisplayResults
END
--
IF @Address IS NOT NULL
BEGIN
INSERT INTO #TEMP
SELECT YourPKey
FROM YourTable
WHERE [Address] = @Address
AND YourPKey NOT IN (SELECT T_ID FROM #TEMP)
SELECT @intTotalResults = @intTotalResults + @@ROWCOUNT
--
IF @intTotalResults > @MaxResultsRequired GOTO DisplayResults
END
--
etc.
--
DisplayResults:
--
SELECT
.....,
CASE WHEN @FirstName = FirstName THEN 10 ELSE 0 +
CASE WHEN @LastName = LastName THEN 10 ELSE 0 +
CASE WHEN @DOB = DOB THEN 20 ELSE 0 +
CASE WHEN @SSN = SSN THEN 100 ELSE 0 +
CASE WHEN @Address = [Address] THEN 30 ELSE 0 END AS
CombinedWeight
FROM YourTable
WHERE YourPKey IN (SELECT T_ID FROM #TEMP)
ORDER BY
CombinedWeight DESC
this would require that the various search columns are indexed.
In practice, when we do this type of thing, we also match on "Near misses" so if you search for "John" for the first name then anything which is "John" gets a Weight=10, but variations like "Jon" get 5 and anything matching the SOUNDEX for John gets, say, 2.
We store all this "searchable field data" in a table and we refresh that using a TRIGGER whenever a record is modified. i.e. we store the SSN, DOB, Address etc. into that table - one row per item, including the SOUNDEX.
We then search that "searchable field data" table instead of the actual table. Its all indexed, and includes a SOUNDEX value for the data too. We also have an Alias table for word substitutions, that includes a dictionary of all root words (English only for us
) and aliases that the Client can add - e.g. if they have a product name and users may search for alternative spellings or competitors equivalent words, or a part number where a competitor's part numbering system is widely used in the industry. We split things like address into individual words and store those in the "searchable field data" so that search for YORK matches York Road, York Street as well as the town/city of York ... or New York. If the user searches for multiple words, e.g. "New" and "York" then that will give a higher weighting for "New York" because it matches two words in the address, rather than just one, but lower down the results list the user will see "York Street" and "York Road" and then anything matching the SOUNDEX of York etc.