Search code examples
sqlrelational-division

Search for data that matches every single tag (using the LIKE operator)


For the past two days I've been doing my best to put together a query that will pull data based on inputted tags. The purpose is for an autocomplete field, where the words the user inputs are split into tags. I really need to use the LIKE operator because the whole purpose of autocomplete is that the user does not need to write out full words

CREATE TABLE `movies` (
  `id` int(10) unsigned NOT NULL,
  `name` varchar(250) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `tags` (
  `tag` varchar(50) NOT NULL DEFAULT '',
  `mid` int(10) unsigned NOT NULL,
  KEY `mid` (`mid`),
  KEY `alphabetizer` (`tag`),
  CONSTRAINT `tags_ibfk_1` FOREIGN KEY (`mid`) REFERENCES `movies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Current query:

SELECT *
    FROM movies ,
    JOIN tags t ON m.id = t.mid
   WHERE t.tag LIKE 'Dawn%' OR t.tag LIKE 'of%'
GROUP BY m.id
  HAVING COUNT(DISTINCT m.tag) = 2

EDIT: The issue is that, as more tags are added, the vaguer the results get. This is the opposite effect.


Solution

  • SELECT m.id, group_concat(t.tag separator ', ') as tags
      FROM movies
      JOIN tags t
        ON m.id = t.mid
     GROUP BY m.id
    HAVING group_concat(t.tag) like '%DAWN%'
       and group_concat(t.tag) like '%OF%'
    

    NOTE: Are the tags uppercase or lowercase, or mixed? In the above answer I assume they are all uppercase. You can use the UPPER or LOWER functions if the tags are not consistent, but they should be consistently upper or lowercase.

    In the above query I used group_concat to show all tags on one row for each ID. That is a MYSQL function that will only work in MYSQL (you didn't mention what database you're using). If postgresql you would use string_agg, if Oracle you would use LISTAGG.