|
|
Subject:
SQL Query that checks for multiple values in a list
Category: Computers > Programming Asked by: biohaz-ga List Price: $15.00 |
Posted:
15 Apr 2004 17:16 PDT
Expires: 16 Apr 2004 17:15 PDT Question ID: 330983 |
I'm searching a database and need to check a range of selected values against a field. For example, I'm searching for 1,2,3. My database looks something like this: entry1 - 1,2,3,4,5,6 entry2 - 1,5 entry3 - 5,6,7,8 entry4 - 3 What I would want to do, based on the SQL I know, would be... WHERE (('1','2','3') IN field) ...Or maybe this... WHERE (field LIKE '%1%2%3%') ...and recieve entry1, entry2, and entry4 as a result set. If I use WHERE (field IN ('1','2','3')) the only fields that are returned are those that have ONLY 1, or ONLY 2, or ONLY 3 in them, none that have a combo of those numbers and/or other numbers. My question is two part, though basic I believe. A) Is this possible? B) If it is, then how? (you knew this one was coming) |
|
There is no answer at this time. |
|
Subject:
Re: SQL Query that checks for multiple values in a list
From: pavlos-ga on 15 Apr 2004 18:25 PDT |
1. Yes it's possible 2. The fast and easy way to do it is: SELECT * FROM Table1 WHERE (field like '*1*') or (field like '*2*') or (field like '*3*') You should extend this query according to the requested values. Other examples: WHERE (field like '*1*') WHERE (field like '*1*') or (field like '*5*') You may also consider this: WHERE ((field like '*1*') or (field like '*3*')) and not (field like '*4*') |
Subject:
Re: SQL Query that checks for multiple values in a list
From: biohaz-ga on 15 Apr 2004 19:17 PDT |
Thanks for the response... The problem I'm having now with this solution is that if one of the fields has 21 in it, a search for LIKE '%1%' returns the field with 21 as well as the field with 1. Any idea how to deal with this occurance, or do I really need to do this loop through code? |
Subject:
Re: SQL Query that checks for multiple values in a list
From: nelson-ga on 15 Apr 2004 21:16 PDT |
Not knowing the specifics of your database, I'm guessing it is not properly noramlized. Normalization would greatly improve querying. |
Subject:
Re: SQL Query that checks for multiple values in a list
From: yeechern-ga on 15 Apr 2004 23:23 PDT |
How about this: WHERE (','+field+',' like '%,1,%') or (','+field+',' like '%,2,%') or (','+field+',' like '%,3,%') .. not an effective way but should be able to do what you need. |
Subject:
Re: SQL Query that checks for multiple values in a list
From: webdude99-ga on 16 Apr 2004 06:10 PDT |
WHERE (field=1) or (field=2) or (field=3) etc. |
Subject:
Re: SQL Query that checks for multiple values in a list
From: scubajim-ga on 16 Apr 2004 09:10 PDT |
Fix the database design. This is a terrible design. |
Subject:
Re: SQL Query that checks for multiple values in a list
From: biohaz-ga on 16 Apr 2004 09:45 PDT |
Okay I'm hearing from the masses that I've got a poorly designed database... well sadly folks, as with most things, it is out of my control... This is what it is... A user has five fields that hold a list of attributes within them... You mean to tell me that making a SEPERATE field for each individual attribute would have been a better design? That would just increase my DB size, not help my solve my problem... I'd still have toi use multiple WHERE statements... I believe I've gotten my answer, and that it is NOT possible to search for a list of values within a field... thanks to those that actually offered up some worthwhile assitance... |
Subject:
Re: SQL Query that checks for multiple values in a list
From: biohaz-ga on 16 Apr 2004 09:49 PDT |
Also mentioned is normalization... How would that help me here? I understand it will make everything faster but I'm not certain how it would help me in this instance... |
Subject:
Re: SQL Query that checks for multiple values in a list
From: scubajim-ga on 16 Apr 2004 12:11 PDT |
No, one would NOT make a field for each comma delimited entry. One would make a seperate table with two columns. One column would relate the original table and the other column would have an entry (eg 1). Then you would have multiple rows. other table would look like: Key_to_parent_table entry_values entry_1 1 entry_1 2 entry_1 3 entry_2 2 entry_3 1 entry_3 4 ... Then the SQL statement would be fairly simple.(and a much better design) |
Subject:
Re: SQL Query that checks for multiple values in a list
From: stephenvakil-ga on 16 Apr 2004 14:16 PDT |
But regardless you can do where (field like '1,%' or field like '%,1,%' or field like '%,1') I BELIEVE that will work, not sure. I will definitely agree that this is a terrible design. |
Subject:
Re: SQL Query that checks for multiple values in a list
From: biohaz-ga on 16 Apr 2004 14:41 PDT |
*little light bulb goes off* Okay, now I totally see what you mean scubajim... hrmmmmm... I might be able to get the design changed... Alright, thanks alot for the assitance :) |
Subject:
Re: SQL Query that checks for multiple values in a list
From: fischer_msft-ga on 16 Apr 2004 15:20 PDT |
Here's my $.05 As everyone has stated, this does appear to be very bad db design. If you'd like to learn more about the different degrees of database design here is a link that should help. http://www.4guysfromrolla.com/webtech/042699-1.shtml To answer your question, this is the approach I would use (if I were forced by a design that was out of my control). I'm assuming you're using SQL Server which supports table valued functions. First, here is a function that will take your list of numbers and expand them into rows using a delimiter of your choice(the results will have one row for each value in your list). Execute and understand what this function does prior to proceeding with my suggestion. IF ISNULL(OBJECTPROPERTY(OBJECT_ID('dbo.fn_Split'), 'IsTableFunction'), 0) = 1 DROP FUNCTION dbo.fn_Split GO CREATE FUNCTION dbo.fn_Split ( @vcrText varchar(8000) , @vcrDelim varchar(20) = ' ' ) RETURNS @retArray TABLE ( RowIndex smallint Primary Key , Value varchar(8000) ) AS BEGIN DECLARE @intIndex smallint , @vcrValue varchar(8000) , @intPlacement smallint , @intLastPlacement smallint , @intStrike smallint , @intTextLength tinyint , @intDelimLength tinyint IF @vcrDelim = 'Space' SET @vcrDelim = ' ' IF @vcrDelim = 'Empty' OR @vcrDelim = '' SET @vcrDelim = ' ' SELECT @intIndex = 1 , @intPlacement = 0 , @intLastPlacement = 0 , @vcrText = LTRIM(RTRIM(@vcrText)) , @intTextLength = DATALENGTH(@vcrText) , @intDelimLength = DATALENGTH(@vcrDelim) WHILE (@intPlacement < @intTextLength) BEGIN -- If you can find the delimiter in the text, retrieve the first element and -- insert it with its index into the return table. SET @intLastPlacement = @intPlacement + 1 IF @vcrDelim Is Null SET @intPlacement = @intLastPlacement + 1 ELSE BEGIN SET @intPlacement = CHARINDEX(@vcrDelim, @vcrText, @intLastPlacement) IF (@intPlacement = 0) SET @intPlacement = @intTextLength + 1 END SET @vcrValue = SUBSTRING(@vcrText, @intLastPlacement, @intPlacement - @intLastPlacement) INSERT @retArray VALUES (@intIndex, @vcrValue) SET @intIndex = @intIndex + 1 END RETURN END GO SELECT * FROM dbo.fn_Split('1,2,3', ',') GO Now that you understand the results of this functions lets tie it in with your question. You would like results from a table based on whether one or more delimited values in a list match one or more values in a varchar field within your table. I have provided a table valued function to enumerate a list of delimited values in a varchar out to rows. Now that we have rows for each value we can try to match those values against values within your field using a join and the Like operator as suggested by prior comments. Here is my test script that does exactly as I've described. You'll notice I have two select statements. The first select statement returns all rows with no aggregation. Now that we're joining our base table against the enumerated list of values we supplied to the table-valued function, we end up with multiple rows (one row for each list value that matches the fields). My second SELECT statement remedies this issue by performing a DISTINCT on the results (which could also be done with GROUP BY t.Entry). Note my INNNER JOIN methodolgy. One (t.Entry Like s.Value + ',%') tests whether the value matches the first value in the entry field and the second (t.Entry Like '%,' + s.Value + ',%') tests whether the value matches a value in the list and final (t.Entry Like '%,' + s.Value) test whether the value matches the last value in the entry field. CREATE TABLE #TestEntry ( Entry varchar(25) ) GO INSERT INTO #TestEntry VALUES('1,2,3,4,5,6') INSERT INTO #TestEntry VALUES('1,5') INSERT INTO #TestEntry VALUES('5,6,7,8') INSERT INTO #TestEntry VALUES('3') GO SELECT t.Entry, s.Value FROM #TestEntry t INNER JOIN dbo.fn_Split('1,2,6', ',') s ON t.Entry Like s.Value + ',%' OR t.Entry Like '%,' + s.Value + ',%' OR t.Entry Like '%,' + s.Value SELECT DISTINCT t.Entry FROM #TestEntry t INNER JOIN dbo.fn_Split('1,2,6', ',') s ON t.Entry Like s.Value + ',%' OR t.Entry Like '%,' + s.Value + ',%' OR t.Entry Like '%,' + s.Value GO DROP TABLE #TestEntry GO The reason I suggest using the table valued function is that the code will accomodate any number of values in your list to match as opposed to the prior suggestions which have a limit of 'hard coded' values. HTH Fischerman |
Subject:
Re: SQL Query that checks for multiple values in a list
From: fischer_msft-ga on 16 Apr 2004 15:23 PDT |
Typo- As everyone has stated, this does appear to be very bad db design. If you'd like to learn more about the different degrees of database design here is a link that should help. Revision: As everyone has stated, this does appear to be very bad db design. If you'd like to learn more about the different degrees of database NORMALIZATION here is a link that should help. |
Subject:
Re: SQL Query that checks for multiple values in a list
From: biohaz-ga on 16 Apr 2004 15:49 PDT |
*blinks* Wow... That rocks... I'll reply in depth once I've played with this a bit but that was exactly the type of functionality I was looking for... How do I make a comment the answer to a question? Cause you just nailed it... |
If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you. |
Search Google Answers for |
Google Home - Answers FAQ - Terms of Service - Privacy Policy |