Compare comma separated values in mysql and get the matched output in countcolumn
Example:
id values
1 1,2,3
2 3
3 1,3
By comparing id 1 and 2 the output should be 1
By comparing id 2 and 3 the output should be 1
By comparing id 3 and 1 the output should be 2
Firstly, the data you listed should really be stored in a format where each row of the database stores a single id
and a single value
, i.e. the 3-element list would correspond to 3 rows. If that change was made to your structure then the following answer would be relevant Compare similarities between two result sets
As it stands though, here's a nice little MySQL function I put together that you could use for your purposes. This takes in 2 arguments which are comma-separated lists and will return the number of elements in list 1 that appear in list 2.
This will not as it stands prevent duplicate IDs in list 1 being counted twice in list 2 (i.e. '1,1,2' and '1,2' would return a value of 3) but you could figure out how to adjust this fairly easily to do that if you so wished.
To use this, just do
SELECT
countMatchingElements( '3' , '1,3' ) AS testCase1
countMatchingElements( '1,2,3' , '1,3' ) AS testCase2
countMatchingElements( '3' , '1,2,3' ) AS testCase3;
The stored function logic is as follows
CREATE DEFINER = `yourUserGoesHere`@`%` FUNCTION `countMatchingElements`(inFirstList VARCHAR(1000), inSecondList VARCHAR(1000))
RETURNS tinyint(3) unsigned
NO SQL
DETERMINISTIC
SQL SECURITY INVOKER
BEGIN
DECLARE numReturn TINYINT UNSIGNED DEFAULT 0;
DECLARE idsInFirstList TINYINT UNSIGNED;
DECLARE currentListItem VARCHAR(255) DEFAULT '';
DECLARE currentID TINYINT UNSIGNED;
SET idsInFirstList = ( CHAR_LENGTH( inFirstList ) + 1 ) - CHAR_LENGTH( REPLACE( inFirstList , ',' , '' ) );
SET currentID = 1;
-- Loop over inFirstList, and for each element that is in inSecondList increment numReturn
firstListLoop: REPEAT
SET currentListItem = SUBSTRING_INDEX( SUBSTRING_INDEX( inFirstList , ',' , currentID ) , ',' , -1 );
IF FIND_IN_SET( currentListItem , inSecondList ) THEN
SET numReturn = numReturn + 1;
END IF;
SET currentID = currentID + 1;
UNTIL currentID > idsInFirstList
END REPEAT firstListLoop;
RETURN numReturn;
END
if it's a SET type column, you might be able to use & operator and then BIT_COUNT():
BIT_COUNT(values1 & values2)