4

Say if I have an array and I want to check if an element is a part of that array, I can go ahead and use in_array( needle, haystack ) to determine the results. I am trying to see the PHP equivalent of this for my purpose. Now you might have an instant answer for me and you might be tempted to say "Use IN". Yes, I can use IN, but that's not fetching the desired results. Let me explain with an example:

I have a column called "pets" in DB table. For a record, it has a value: Cat, dog, Camel (Yes, the column data is a comma separated value). Consider that this row has an id of 1.

Now I have a form where I can enter the value in the form input and use that value check against the value in the DB. So say I enter the following comma separated value in the form input: CAT, camel (yes, CAT is uppercase & intentional as some users tend to enter it that way).

Now when I enter the above info in the form input and submit, I can collect the POST'ed info and use the following query:

$search = $_POST['pets'];
$sql = "SELECT id FROM table WHERE pets IN ('$search') "; 
  1. The above query is not fetching me the row that already exists in the DB (remember the record which has Cat, dog, Camel as the value for the pets column?). I am trying to get the records to act as a superset and the values from the form input as subsets. So in this case I am expecting the id value to show up as the values exist in the column, but this is not happending.

  2. Now say if I enter just CAT as the form input and perform the search, it should show me the ID 1 row.

  3. Now say if I enter just camel, cAT as the form input and perform the search, it should show me the ID 1 row.

How can I achieve the above?

Thank you.

Devner
  • 6,825
  • 11
  • 63
  • 104

5 Answers5

6

The function you're looking for is find_in_set:

 select * from ... where find_in_set($word, pets)

for multi-word queries you'll need to test each word and AND (or OR) the tests:

  where find_in_set($word1, pets) AND find_in_set($word2, pets) etc 
user187291
  • 53,363
  • 19
  • 95
  • 127
  • Thank you for the reply. I tried out your solution & noticed that it worked, but unfortunately, only partially. The search results gets me the ID only if the $word value is the first value in the column. So if I have Cat, Dog, Camel and my query is like: find_in_set('Cat', pets), only then the ID is shown. If I use find_in_set('Dog', pets), the id does not show up and mysql incorrectly returns 0 records. I am glad to know that the find_in_set function exists but unable to get it to solve the issue completely. Can you please help? Thanks. – Devner Jun 06 '10 at 00:53
  • Thank you for the reply. I do have spaces in my current comma separated values in my table, so I guess I will have to trim the space before inserting into DB. That will work for me. Appreciate you for taking time to reply on this. Thanks. – Devner Jun 07 '10 at 01:35
4

IN() Check whether a value is within a set of values

mysql> SELECT 2 IN (0,3,5,7);
        -> 0
mysql> SELECT 'wefwf' IN ('wee','wefwf','weg');
        -> 1

SELECT val1 FROM tbl1 WHERE val1 IN (1,2,'a');

View: IN MySql

iSavaDev
  • 373
  • 3
  • 9
2

I've got several things for you in terms of feedback & in direct response to your questions:

First, I suggest you sanitize the input. Everybody is going to tell you that. For that, see What’s the best method for sanitizing user input with PHP?.

Second, normalize the input with UPPER() or LOWER() if you want to use MySQL and need to store user-formatted input, or use strtoupper() and strtolower() if you wanted to process the input before storing it.

You're still left with the order in the user query. E.g. "cat, dog" ought to yield the same result as "dog, cat". If you were to code that with a LIKE statement, performance issues are going to eat you alive. Not only would you have to create the query dynamically, you'd also end up with huge and unnecessarily complex queries. In short, forget it. You have to change the way you store your data.

One way to accomplish this is by creating a relationship table that references a table of unique user input and your record. This table would look similar to

user_id | pet_id

Every user could have more than one pet_id associated with them. I've set up a database a long time ago the same way you did and ran into the same issues. Performance-wise it never paid off and it's anything but good style. I ended up changing my structure because of that to the above-mentioned method.

Community
  • 1
  • 1
Jan K.
  • 1,607
  • 2
  • 13
  • 22
  • Thank you for the reply and for suggesting the best practices. The code that I posted above is just for testing. I actually sanitize all input in my actual live code. Also appreciate for indicating the real life performance issues with the current DB structure that I have. I guess I will have to fix it! – Devner Jun 05 '10 at 17:33
0

This mysql function search an INT value into a json array of INT:

-- EXAMPLES :

-- select is_into_json_array(18, '[25, 10, 15]'); -> -100
-- select is_into_json_array(25, '[25, 10, 15]'); -> 0
-- select is_into_json_array(15, '[25, 10, 15]'); -> 2

https://github.com/PietroLaGrotta/Json-in-mysql-text-type/blob/master/is_into_json_in_array.sql

-3

Yes, the column data is a comma separated value

Here is your fault.
No, it shouldn't be comma separated value
And your database structure should be normalized.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • Yup, this is true. The only chance of searching in a comma-separated list is using `LIKE` and wildcards, which is slow and error-prone (you can't have commas in your values then, for example). Every attribute should be properly normalized as a record in a separate table. – Pekka Jun 05 '10 at 17:18
  • @Pekka Thank you both for your replies. I agree that a normalized way would really be better. The comma separated value design was taking care of one of the most important functions of the website in a simple and easy way. The importance given to the search tool that I am mentioned about is secondary and only next to the main functionality (which is already successful). So is there no way at all to accomplish what I am trying to do above? – Devner Jun 05 '10 at 17:27
  • 2
    Thank you for your constructive criticism. – Devner Jun 05 '10 at 17:48