3

Is it possible somehow to return all the rows in a mysql table where one field has duplicate values in a comma separated string?

EG if we had fields

ID    VALUE
'1', '123,123,678'
'2', '23,24,25'

I only want to return row 1 in this instance?

Shankar Narayana Damodaran
  • 68,075
  • 43
  • 96
  • 126
Matthew
  • 596
  • 1
  • 8
  • 29
  • 7
    This is where database normalization makes your life much easier – John Conde Mar 19 '14 at 14:57
  • This isn't possible without a custom function in mysql. – Rob W Mar 19 '14 at 14:59
  • This schema is not a very good fit for your use case and violates a lot of rules of [proper database normalization](http://en.wikipedia.org/wiki/Database_normalization). Serialized values are almost impossible to work with inside of MySQL, it's necessary to work with these in application code. Is it practical to split that up into a one-to-many association? – tadman Mar 19 '14 at 15:08
  • you always have 3 values separated by comma ? – echo_Me Mar 19 '14 at 15:18
  • This is Magento's database structure for product attributes, so its not really possible to normalise the structure in this instance. – Matthew Mar 19 '14 at 15:20
  • @Matthew take a look at my answer , if this what you want. – echo_Me Mar 19 '14 at 15:51

2 Answers2

2

There is no way to do this from within SQL that's both practical and efficient. As indicated by John Conde, you should normalize your database so that it looks like this:

ID  VALUE
1   123
1   123
1   678
2   23
2   24
2   25

Then you can easily prevent the situation from arising by disallowing duplicate rows (eg., by defining a UNIQUE index on the ID and VALUE columns). And if you can't / don't want to prevent it from happening, you can at least detect it much easier in pure SQL.

As it currently stands, I would get all rows into a PHP array and detect duplicate values from there. This isn't really efficient either, but at least it'll be more practical than trying to reach this in pure SQL.

$result = mysql_result('select ID, VALUE from table');
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
     $values_array = explode( ',' , $row['VALUE'] );
     if(count($values_array) != count(array_unique($values_array)))
     {
          // There must be duplicate values in the array
          echo 'Row with id ' .$row['ID'] .' has duplicate values';
     }
}

You can do it like this, but normalizing your database would be much better. (Oh, and don't use these mysql_... functions; you should use mysqli or PDO. This is just to show you how it works).

Community
  • 1
  • 1
Wilbo Baggins
  • 2,701
  • 3
  • 26
  • 39
  • Normalising the DB would be ideal yes but this is a Magento EAV database so not possible. Thanks anyway! – Matthew Mar 19 '14 at 15:19
0

Assuming you just have just 3 values comma separated . then you can use this via mysql and get rid of php:

  select a.id,a.v1 , a.v2,a.v3,a.value from (
       SELECT id,value,SUBSTRING_INDEX(value, ',', 1)as v1,
              SUBSTRING_INDEX(SUBSTRING_INDEX(value, ',', 2), ',', -1) as v2,
              SUBSTRING_INDEX(value, ',', -1) as v3
       FROM table1 )a
 where v1 = v2 or v1 = v3 or v2 = v3

DEMO HERE

OTHER DEMO with extra values

OBS: have make extra v1 ,v2,v3 separated ,so you may use them in your work

echo_Me
  • 37,078
  • 5
  • 58
  • 78
  • Nice, but only useful in very specific scenarios. This only works if *all* entries have either 2 or 3 comma separated values. Entries with 0 or 1 values in the VALUE column will also be returned, since SUBSTRING_INDEX returns the full column if the specified index is higher than the number of delimiter occurences so v2 = v3 will be true in those cases: http://sqlfiddle.com/#!2/c4263c/1/0 – Wilbo Baggins Mar 19 '14 at 17:25
  • @WilboBaggins Dear ! first thanks for downvote , second I clearly said that this for 3 values comma separated. its not for 1 value as you said. since he didnt answer how many values are there in this field when i asked [here](http://stackoverflow.com/questions/22509742/detect-duplicate-values-in-a-comma-separated-field-in-mysql/22511296#comment34249059_22509742). – echo_Me Mar 19 '14 at 17:37
  • Others could easily interpret your answer to mean 'no more than 3 values', so I felt it was a risky answer and commented and downvoted. In any case, the question you answered is narrower than the question asked; no need to get defensive. – Wilbo Baggins Mar 20 '14 at 11:31