简体   繁体   中英

SQL Search using case or if

Everyone has been a super help so far. My next question is what is the best way for me to approach this... If I have 7 fields that a user can search what is the best way to conduct this search, They can have any combination of the 7 fields so that is 7! or 5040 Combinations which is impossible to code that many. So how do I account for when the User selects field 1 and field 3 or they select field 1, field 2, and field 7? Is there any easy to do this with SQL? I dont know if I should approach this using an IF statement or go towards a CASE in the select statement. Or should I go a complete different direction? Well if anyone has any helpful pointers I would greatly appreciate it.

Thank You

You'll probably want to look into using dynamic SQL for this. See: Dynamic Search Conditions in T-SQL and Catch-all queries for good articles on this topic.

Select f1,f2  from table where f1 like '%val%' or f2 like '%val%'

You could write a stored procedure that accepts each parameter as null and then write your WHERE clause like:

WHERE (field1 = @param1 or @param1 is null) 
AND (field2 = @param2 or @param2 is null) etc...

But I wouldn't recommend it. It can definitely affect performance doing it this way depending on the number of parameters you have. I second Joe Stefanelli's answer with looking into dynamic SQL in this case.

Depends on:

  • how your data looks like,
  • how big they are,
  • how exact result is expected (all matching records or top 100 is enough),
  • how much resources has you database.

you can try something like:

CREATE PROC dbo.Search(
  @param1 INT = NULL,
  @param2 VARCHAR(3) = NULL
)
AS

BEGIN
  SET NOCOUNT ON

  -- create temporary table to keep keys (primary) of matching records from searched table     
  CREATE TABLE #results (k INT)

  INSERT INTO 
    #results(k)
  SELECT -- you can use TOP here to norrow results
    key
  FROM
    table
  -- you can use WHERE if there are some default conditions

  PRINT @@ROWCOUNT

  -- if @param1 is set filter #result    
  IF @param1 IS NOT NULL BEGIN
    PRINT '@param1'

    ;WITH d AS (
      SELECT
        key
      FROM
        table
      WHERE
        param1 <> @param1
    )
    DELETE FROM 
      #results
    WHERE
      k = key

    PRINT @@ROWCOUNT
  END

  -- if @param2 is set filter #result
  IF @param2 IS NOT NULL BEGIN
    PRINT '@param2'

    ;WITH d AS (
      SELECT
        key
      FROM
        table
      WHERE
        param2 <> @param2
    )
    DELETE FROM 
      #results
    WHERE
      k = key

    PRINT @@ROWCOUNT
  END

  -- returns what left in #results table
  SELECT
    table.* -- or better only columns you need
  FROM
    #results r
    JOIN
      table 
    ON
      table.key = r.k
END

I use this technique on large database (millions of records, but running on large server) to filter data from some predefined data. And it works pretty well.

However I don't need all matching records -- depends on query 10-3000 matching records is enough.

If you are using a stored procedure you can use this method:

CREATE PROCEDURE dbo.foo 
    @param1 VARCHAR(32) = NULL, 
    @param2 INT = NULL 
AS 
BEGIN 
    SET NOCOUNT ON 

SELECT * FROM MyTable as t
WHERE (@param1 IS NULL OR t.Column1 = @param1)
AND   (@param2 IS NULL OR t.COlumn2 = @param2)

END 
GO 

These are usually called optional parameters. The idea is that if you don't pass one in it gets the default value (null) and that section of your where clause always returns true.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM