views:

32

answers:

4

Hi,

I have a table say, ITEM, in MySQL that stores data as follows:

ID    FEATURES
--------------------
1     AB,CD,EF,XY
2     PQ,AC,A3,B3
3     AB,CDE
4     AB1,BC3
--------------------

As an input, I will get a CSV string, something like "AB,PQ". I want to get the records that contain AB or PQ. I realized that we've to write a MySQL function to achieve this. So, if we have this magical function MATCH_ANY defined in MySQL that does this, I would then simply execute an SQL as follows:

select * from ITEM where MATCH_ANY(FEAURES, "AB,PQ") = 0

The above query would return the records 1, 2 and 3.

But I'm running into all sorts of problems while implementing this function as I realized that MySQL doesn't support arrays and there's no simple way to split strings based on a delimiter.

Remodeling the table is the last option for me as it involves lot of issues.

I might also want to execute queries containing multiple MATCH_ANY functions such as:

select * from ITEM where MATCH_ANY(FEATURES, "AB,PQ") = 0 and MATCH_ANY(FEATURES, "CDE")

In the above case, we would get an intersection of records (1, 2, 3) and (3) which would be just 3.

Any help is deeply appreciated.

Thanks

A: 

Just a thought:

Does it have to be done in SQL? This is the kind of thing you might normally expect to write in PHP or Python or whatever language you're using to interface with the database.

This approach means you can build your query string using whatever complex logic you need and then just submit a vanilla SQL query, rather than trying to build a procedure in SQL.

Ben

Ben
Well, what I'm really trying to do is to get a prediction of the number of records that match the given criteria. This query would be fired using AJAX through PHP. So, the quicker the result returned, the better it is for me. This leaves me with just one choice - make a single database hit.That's where I'm getting stuck I feel!Yes, I can construct the complex query string using PHP. But I'm not able to comprehend what this query string would look like then.
Adarsh R
+1  A: 
select * 
  from ITEM where 
 where CONCAT(',',FEAURES,',') LIKE '%,AB,%'
    or CONCAT(',',FEAURES,',') LIKE '%,PQ,%'

or create a custom function to do your MATCH_ANY

Mark Baker
A: 

First of all, the database should of course not contain comma separated values, but you are hopefully aware of this already. If the table was normalised, you could easily get the items using a query like:

select distinct i.Itemid
from Item i
inner join ItemFeature f on f.ItemId = i.ItemId
where f.Feature in ('AB', 'PQ')

You can match the strings in the comma separated values, but it's not very efficient:

select Id
from Item
where
  instr(concat(',', Features, ','), ',AB,') <> 0 or
  instr(concat(',', Features, ','), ',PQ,') <> 0
Guffa
You nailed it! Thank you Guffa!I was concerned about using LIKE or RLIKE as both have been known to be inherently slower. At least slower compared to a simple INSTR.I wrote my dynamic query generator based on this logic and it works like a charm.I do understand that this kind of a table model isn't very right in terms of normalization. But this is the best I can offer at this point in time.
Adarsh R
@Adarsh: Yes, it's slightly faster than a `like`, but it still can't use any index on the field, so it won't ever be fast.
Guffa
A: 

Alternatively, consider using RLIKE()

    select * 
      from ITEM
     where ','+FEATURES+',' RLIKE ',AB,|,PQ,'; 
Mark Baker