开发者

SQL Search Query

I'm currently working on a query to search a specific table. The requirements say that I need to grab all records where any of a group of fields are like the input value. As such I have a query that looks similar to

SELECT * FROM MyTable
WHERE Col1 like @input
    or Col2 like @input
    or Col3 like @input

There could be any number of columns in the where clause. One particular customer is going to have 50 columns. As such, this where clause is going to get fairly expensive.

Is there another syntax or method that can be开发者_JAVA技巧 used so that I could say "does the input value exist in any of x columns?"

Would you write the query differently?


Depending on which and where wildcards are allowed these queries could be expensive indeed, because the optimizer will have trouble using indexes on many of them to speed them up.

If you are running this on MS SQL Server you might consider using the Fulltext searching features and the CONTAINS keyword to implement this.

SELECT *
FROM MyTable
WHERE CONTAINS
((col1,col2,col3) ,@input)

Or to search all text-indexed columns

SELECT *
FROM MyTable
WHERE CONTAINS
(* ,@input)


I'd structure the data differently. Are the types of these 50 columns all going to be the same? Since you're using "like", I'm going to assume they are all varchar columns. Why not have 3 tables, 'MyTable', a table with the string data (whatever it may be), and a join table with references to both.

At this point, your query becomes:

select mt.*
from MyTable mt
    inner join JoinTable jt
        on jt.MyTableId = mt.Id
    inner join DataTable dt
        on dt.Id = jt.DataTableId
where dt.Data like @Input

Obviously, on SO, we see a lot of answers that are simply, "Your data is structured wrong. Redo it." This is not always the most helpful. If for some reason (bureaucracy around database structure, legacy dependencies on this structure, etc.) you cannot restructure it, you need to realize you're pivoting these columns. At this point you'll need to look at options for pivoting this, which will vary based on how analytical/transactional (read/write heavy) this db is. If you are very read heavy, you might be ok duplicating the data into a pivot table that you update each time you update 'MyTable'. If you're more transactional, a function or view will at least abstract this pivoted structure but the query will be expensive. MS SQL full text search capabilities would work similarly to duplicating the data and updating on inserts and depending on the nature of your "like" queries, may read faster.


If you don't need live data, you can opt for a data-warehouse scenario.

  • every day, drop and reload a table containing only an ID and VALUE column
  • use a SELECT INTO like
   SELECT ID, Col1 FROM MyTable  
   UNION ALL SELECT ID, Col2 FROM MyTable  
   UNION ALL SELECT ID, Col3 FROM MyTable
  • Index the table from front to back, left to right, ...

This allows you to simplify your original select and keep performance on par

SELECT mt.*
FROM   MyTable mt
       INNER JOIN MyDWTable mdwt ON mdwt.ID = mt.ID
WHERE  mdwt.Value LIKE @Input
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜