This post on Reddit asked how to run a query that takes a list of items (in this case ingredients) as the input and returns all rows with at least one of those items in a JSON list, ordered by the most matches.
I jumped on this as a great opportunity to demonstrate Datasette Lite as a tool for answering SQL questions.
I started with the following SQL to create the demo table:
create table recipes (id integer primary key, name text, ingredients text);
insert into recipes values (1, 'Cake', '["flour", "sugar", "eggs"]');
insert into recipes values (2, 'Pancakes', '["flour", "eggs", "butter"]');
insert into recipes values (3, 'Waffles', '["flour", "milk", "eggs"]');
insert into recipes values (4, 'Pizza', '["flour", "sugar", "eggs", "cheese"]');I actually got GitHub Copilot to write most of that for me:
I saved that to a gist and opened it in Datasette Lite with this URL:
Here's the SQL recipe I came up with to solve the question:
select id, name, ingredients, (
select json_group_array(value) from json_each(ingredients)
where value in (select value from json_each(:p0))
) as matching_ingredients
from recipes
where json_array_length(matching_ingredients) > 0
order by json_array_length(matching_ingredients) descExample of that query with an input for p0 of ["sugar", "cheese"], which returns:
| id | name | ingredients | matching_ingredients |
|---|---|---|---|
| 4 | Pizza | ["flour", "sugar", "eggs", "cheese"] | ["sugar","cheese"] |
| 1 | Cake | ["flour", "sugar", "eggs"] | ["sugar"] |
The key trick here is the bit that creates that matching_ingredients column, which uses a sub-select like this:
select json_group_array(value) from json_each(ingredients)
where value in (select value from json_each(:p0))json_group_array(value) is an aggregation function that turns the results into a JSON array.
where value in (select value from json_each('["sugar", "cheese"]') is the bit that calculates the intersection of the two JSON arrays.
Then at the end I use json_array_length() to remove rows with no overlap and then sort with the most matching ingredients first.
Created 2022-08-17T16:21:00-07:00, updated 2022-08-17T16:32:39-07:00 · History · Edit