I ask this on StackOverflow after carefully reading this answer about StackOverflow vs dba.se—I’m a non-expert database novice, and in my possibly-misguided estimation, a fellow non-DBA coder can help me just as well as a database expert. SQLite is also a “lite” database.
My SQLite table is for, say, a recipes scenario. It has two columns: each row has a field, meal
and one ingredient
required by the meal. Since most meals take more than one ingredient, there are many rows with the same meal
but different ingredient
s.
I need to know how many meals the exact set of ingredients can make—actually I need a sorted list of all the ingredients and how many meals can be made with exactly those ingredients. I hope the code will explain this completely:
CREATE TABLE recipes (
meal TEXT,
ingredient TEXT);
INSERT INTO recipes VALUES
("tandoori chicken","chicken"), ("tandoori chicken","spices"),
("mom's chicken","chicken"), ("mom's chicken","spices"),
("spicy chicken","chicken"), ("spicy chicken","spices"),
("parmesan chicken","chicken"), ("parmesan chicken","cheese"), ("parmesan chicken","bread"),
("breaded chicken","chicken"), ("breaded chicken","cheese"), ("breaded chicken","bread"),
("plain chicken","chicken");
Here, we have
- one set of three meals that use exactly the same ingredients (tandoori chicken, mom’s chicken, and spicy chicken),
- another set of two meals using a different set of ingredients, and
- one meal other meal that needs exactly its ingredient.
I want something like the following:
chicken,,,spices|3
chicken,,,cheese,,,bread|2
chicken|1
That is, a string containing the exact set of ingredients and how many meals can be made using exactly these ingredients. (Don’t worry about collating/sorting the ingredients, I can ensure that for each meal, rows will be inserted in the same order all the time. Also, don’t worry about pathological cases where the same meal
-ingredient
row is repeated—I can prevent that from happening.)
I can get the above output like this:
WITH t
AS (SELECT group_concat(recipes.ingredient, ",,,") AS ingredients
FROM recipes
GROUP BY recipes.meal)
SELECT t.ingredients,
count(t.ingredients) AS cnt
FROM t
GROUP BY t.ingredients
ORDER BY cnt DESC;
There’s a couple of reasons I’m not happy with this: first, it creates a sub-view and I’m really curious if there’s a way to achieve this without a sub-view—that would likely be faster and clearer. And second, inside the sub-view, I create a string via group_concat to represent the vector of ingredients—I feel like there ought to be a row-based, or data structure-like, way to get the same information out of SQL.
My question: can I get the above output, or some equivalent, without using sub-views and/or without string concatenation?