1

PostgreSQL table1

id | columnA             | columnB
---+---------------------+--------
1  | A 01,A 02,A 03,A 04 | FALSE
2  | A 01,A 02           | FALSE
3  | A 01,A 02,A 03,A 04 | TRUE 
4  | A 01,A 02           | TRUE 

I used to use below query to find out how many records:

  • Query 1:
SELECT *
FROM DB1.table1
WHERE columnA LIKE 'A 04,%'
  OR columnA LIKE '%,A 04,%'
  OR columnA LIKE '%,A 04'
  AND columnB = 'false'
  • Query 2:
SELECT *
FROM DB1.table1
WHERE columnA LIKE 'A 02,%'
  OR columnA LIKE '%,A 02,%'
  OR columnA LIKE '%,A 02'
  AND columnB = 'false'

Is there better way to just have one query to find which column has 'A 02' or 'A 04' and 'FALSE'?

3
  • 1
    Tough luck, comma separated data... Will cause you lots of trouble. Commented Sep 19, 2019 at 9:49
  • What does "clinic" mean? Commented Sep 19, 2019 at 9:55
  • Typo error. I corrected Commented Sep 19, 2019 at 13:16

3 Answers 3

1

Your initial posted query indicates you're searching for text at the beginning of the string (A 04,), at the end of the string (,A 04) or in the middle of the string (,A 04,). These can simply be reduced to anywhere in the string or simply (A 04). Combining with the (A 02) predicate value and the columnB predicate we get

select *
  from db1.table1
 where not columnB
   and (columnA like '%A 02%' or columnA like '%A 02%');

But I reiterate having multiple values in the same column, or even same data in separate columns with in a row is very bad design. Ther should be in sepreate rows.

Sign up to request clarification or add additional context in comments.

1 Comment

This will fail real quick with higher values, e.g. BA 02 and A 021. The array or regex versions are more robust.
1

demo:db<>fiddle

SELECT *
FROM
    mytable
WHERE
    columnB = false AND ARRAY['A 02', 'A 04', 'clinic 02'] && string_to_array(columnA, ',')
  1. Create an array out of your interesting values: ARRAY['value1','value2']
  2. Convert your string list into an array: string_to_array(list, ',')
  3. Use the && comparator to check if both arrays overlap, meaning if both arrays share at least one element.

Further reading: Postgres arrays


Note: You should think about normalizing your data instead of holding some string separated values in one column. Your current way could lead in many problems.

9 Comments

Alternative would be WHERE columnB = false AND columnA ~ ,?A 0[24],?, not sure how regex performance compares to creating an array for every record.
@404 Very nice idea! In the fiddle engine the query planner show not very different cost results: dbfiddle.uk/… But it's definitely worth a try with the real data.
What could be the problem? When query? Best approach to store multiple value?
Hard to query has you can see here: You always need to split the value. Better approach is taking a simple array instead of a concatenated string. Best approach is to store every value in its own row. In that case you could simply use WHERE to filter. Furthermore indexes can be appended. And if you need the concatenated string you simply do a GROUP BY and string_agg()
Store every value in its own row. The application behave as one row per unique id only. One unique id has many values. Unless business logic changed, otherwise I couldn't see how designer can change the model. Make many columns not right too. As the values can be up to 50 different values .
|
1

You should fix the data model! Storing multiple values in a single column is very bad -- and Postgres has many better alternatives than strings. That said, sometimes we are stuck with other people's really, really bad decisions.

You can use like for this purpose:

SELECT *
FROM DB1.table1
WHERE ',' || columnA || ',' ~ ',A 02,|,A 04,' AND
      NOT columnB   -- assuming this is boolean

For a single value, you would use:

WHERE ',' || columnA || ',' LIKE '%,A 02,%' AND
      NOT columnB   -- assuming this is boolean

2 Comments

What could be the potential problems? What is the best approaches if not store it in one column? Create many column does not sounds right.
@user2201789 . . . The values should be stored in separate rows of a junction/association table.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.