12

I have following data in table:

+----------------------+----------------------------------------------------------+--------------+
| subscriber_fields_id | name                                                     | field_type   |
+----------------------+----------------------------------------------------------+--------------+
|                  143 | Peshawar/Islamabad/Lahore/Swat/Mardan/Karachi            | Job Location |
|                  146 | Karachi                                                  | Job Location |
|                  147 | Lahore and Karachi                                       | Job Location |
|                  149 | Karachi, Mirpur Khas, Sukkur, Layyah, Gilgit, Charsaddah | Job Location |
|                  152 | Islamabad or Lahore                                      | Job Location |
|                  155 | Islamabad                                                | Job Location |
|                  157 | 7 Districts of Sindh and Karachi                         | Job Location |
+----------------------+----------------------------------------------------------+--------------+

My query is:

select * from subscriberfields
where  name like '%Khairpur,Islamabad,Karachi%';

Result:

+----------------------+-----------------------------------------------+--------------+
| subscriber_fields_id | name                                          | field_type   |
+----------------------+-----------------------------------------------+--------------+
|                  143 | Peshawar/Islamabad/Lahore/Swat/Mardan/Karachi | Job Location |
|                  152 | Islamabad or Lahore                           | Job Location |
|                  155 | Islamabad                                     | Job Location |
+----------------------+-----------------------------------------------+--------------+

It should return all rows where the name includes Islamabad, Khairpur or Karachi but it is not.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Muhammad Taqi
  • 5,356
  • 7
  • 36
  • 61
  • You want `WHERE name LIKE '%Khairpur%' OR name LIKE ...`. However, it is not sargable and therefore will require a full table scan—it will become desperately inefficient as the table size grows. You should consider using [fulltext search](http://www.postgresql.org/docs/8.3/static/textsearch.html) instead. – eggyal Mar 09 '15 at 09:52
  • Have you tried `SIMILAR TO` like I've suggested in the answer? – benscabbia Mar 09 '15 at 10:22
  • @gudthing: *Never* use `SIMILAR TO`, it's an utterly pointless construct - there is always a better option. I added an answer. – Erwin Brandstetter Mar 09 '15 at 13:04

5 Answers5

25

For a proper solution, either normalize your database design or, barring that, consider full text search.

For a quick solution to the problem at hand, use a regular expression match (~) or three simple LIKE expressions:

SELECT *
FROM   subscriberfields 
WHERE  name ~ '(Khairpur|Islamabad|Karachi)';

Or:

WHERE (name LIKE '%Khairpur%'
    OR name LIKE '%Islamabad%'
    OR name LIKE '%Karachi%')

.. which can be compressed like Mario demonstrates in his answer. Or shorter, yet, with an array literal:

WHERE name LIKE ANY ('{%Khairpur%, %Islamabad%, %Karachi%}');

But the regexp match gets the same query plan in modern Postgres (can use the same trigram index) and is shorter, yet. See:

Or use ~* or ILIKE for case-insensitive matching.

Since another answer suggested it: never use SIMILAR TO:

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
5

You can use this:

select * from subscriberfields
where  name like any(array['%Khairpur%','%Islamabad%','%Karachi%']);

https://postgres.cz/wiki/PostgreSQL_SQL_Tricks#LIKE_to_list_of_patterns

Mario Leonel
  • 51
  • 1
  • 3
3

Try using SIMILAR TO like below:

SELECT * FROM subscriberfields 
WHERE name SIMILAR TO '%(Khairpur|Islamabad|Karachi)%';

Also you should read up on database normalization. Your design could and should definitely be improved.

benscabbia
  • 17,592
  • 13
  • 51
  • 62
0

In MySQL try using a regular expression "REGEXP" and operator | which works like OR:

SELECT * FROM subscriberfields  WHERE  name REGEXP 'Khairpur|Islamabad|Karachi';

so you will get results containing at least one of these words.

Alternatively, if you want results that will include ALL words, use:

SELECT * FROM subscriberfields  WHERE  name REGEXP '(?=.*Khairpur)(?=.*Islamabad)(?=.*Karachi)';

Works with MySQL on server version 10 MariaDB and PHP 8

If you want to learn more about REGEXP try:

https://www.geeksforgeeks.org/mysql-regular-expressions-regexp/ https://www.freecodecamp.org/news/sql-contains-string-sql-regex-example-query/

There are many blogs with REGEXP examples, but not everyone will give you all the patterns and values you can use, but for starters, have a look at these.

Mironek
  • 11
  • 2
-1

Use OR in WHERE clause, like,

select * from subscriberfields where name like '%Khairpur%' OR name like '%Islamabad%' OR name like '%Karachi%';

Hope it works.

BabyDuck
  • 1,249
  • 1
  • 9
  • 22
  • no, the value is coming from database, i cannot split it by commas because sometimes it is split by , , /, - etc. – Muhammad Taqi Mar 09 '15 at 09:49
  • 1
    @MTaqi: This sounds like very poor database design indeed. You may like to read up to [database normalization](http://en.wikipedia.org/wiki/Database_normalization) and also take a look at [Is storing a delimited list in a database column really that bad?](http://stackoverflow.com/q/3653462) – eggyal Mar 09 '15 at 09:51
  • In that case you really need to consider **FULLTEXT Searching**, as suggested by **eggyal**. – BabyDuck Mar 09 '15 at 09:52