I need to write a PostgreSQL query, that filters on two columns of a database table, where the filtering condition for one of the columns depends on the specific value in the other. For example, if my columns are "Make" and "Color", I want to retrieve all of the records for:
- Red Toyotas or blue Toyotas,
- Red Volkswagens or green Volkswagens,
- Blue Hondas or green Hondas
If I could hardcode the filtering criteria into my query, the WHERE
clause is obviously simple enough to create:
SELECT * FROM Table
WHERE (Make = "Toyota" AND Color in ("red", "blue"))
OR (Make = "Volkswagen" AND Color in ("red, "green"))
OR (Make = "Honda" AND Color in ("blue, "green"))
...
However, the query needs to be constructed so that it is configurable via JSON, and I do not know ahead of time how many Makes there will be, nor how many Colors there will be per Make, and there will almost certainly be a different number of Colors per Make. This information all needs to be delivered through a JSON variable.
I haven't been able to find the right PostgreSQL/JSON term to describe the data structure I am looking for (in Python, I'd use a list-of-lists), but is there some way I can set up a JSON variable where I can specify a set of Makes, for each Make specify a list of Colors, and then create a WHERE
clause in PostgreSQL that tests for a match on any of the Makes AND
the list of colors associated with that Make that was matched?
UPDATE
This query works...
SELECT x.y->'Make' as Make
from jsonb_array_elements('[
{"Make": "Toyota"},
{"Make": "Volkswagen"},
{"Make": "Honda"}
]') as x(y)
...and outputs a table with the three Makes.
However, attempting to use the above in a subquery fails, with an error message from the application that calls SQL of "ERROR: Function 'JSONB_ARRAY_ELEMENTS' is not supported in this context"
.
SELECT *
FROM table t
WHERE EXISTS(SELECT x.y->'Make' as Make
from jsonb_array_elements('[
{"Make": "Toyota"},
{"Make": "Volkswagen"},
{"Make": "Honda"}
]') as x(y)
where x.y->>'Make' = t.Make)
Is there some reason why the jsonb_array_elements
function shouldn't work in a subquery?
UPDATE 2
The difficulties with the subquery will be split into its own question