| 222 | | Рецепти чија секоја состојка е од растителна категорија, проверени наспроти веганската ознака. пронаоѓа рецептите во кои секоја состојка е од растително потекло. Тоа е релациско делење: рецептот се квалификува само ако бројот на неговите растителни состојки е еднаков на бројот на сите негови состојки. Една состојка од животинско потекло го дисквалификува целиот рецепт. Растителни се типовите: |
| 223 | | * vegetable |
| 224 | | * fruit |
| 225 | | * legume |
| 226 | | * nut |
| 227 | | * seed |
| 228 | | * oil |
| 229 | | * herb |
| 230 | | * spice |
| 231 | | * carb |
| 232 | | * beverage |
| 233 | | * //Медот и јајцето// се од типот **other** -> дисквалификуваат |
| | 222 | Две релациски делења во еден прашалник, и двете напишани како NOT EXISTS во NOT EXISTS — двојната негација со која во SQL се изразува „за сите". |
| | 223 | * Првото делење прима рецепт само ако не постои негова состојка што не е од растителна категорија. |
| | 224 | * Второто го прима само ако не постои макронутриент што рецептот не го дава. |
| | 225 | * Делителот на второто сам се пресметува со вгнезден EXISTS: не сите макронутриенти од каталогот, туку само оние што навистина се запишани кај некоја состојка. |
| | 226 | * Резултатот истовремено е и проверка на конзистентност. |
| | 227 | * //Медот и јајцето се од типот other, па го дисквалификуваат рецептот како што треба.// |
| 236 | | SELECT r.name AS recipe, |
| 237 | | u.username AS author, |
| 238 | | COUNT(*) AS ingredient_count, |
| 239 | | ROUND(r.kcal_sum / r.servings) AS kcal_per_portion, |
| | 230 | SELECT r.name AS recipe, |
| | 231 | (SELECT u.username FROM "user" u WHERE u.id = r.user_id) AS author, |
| | 232 | ROUND(r.kcal_sum / r.servings) AS kcal_per_portion, |
| | 233 | (SELECT COUNT(*) FROM recipe_contains_ingredient rci |
| | 234 | WHERE rci.recipe_id = r.id) AS ingredients, |
| | 235 | (SELECT COUNT(DISTINCT icn.nutrient_id) |
| | 236 | FROM recipe_contains_ingredient rci |
| | 237 | JOIN ingredient_contains_nutrient icn |
| | 238 | ON icn.ingredient_id = rci.ingredient_id |
| | 239 | WHERE rci.recipe_id = r.id |
| | 240 | AND icn.quantity > 0 |
| | 241 | AND icn.nutrient_id IN (SELECT n.id FROM nutrient n |
| | 242 | WHERE n.type = 'macro')) AS macros_supplied, |
| 246 | | JOIN "user" u ON u.id = r.user_id |
| 247 | | JOIN recipe_contains_ingredient rci ON rci.recipe_id = r.id |
| 248 | | JOIN ingredient i ON i.id = rci.ingredient_id |
| 249 | | WHERE i.type IN ('vegetable', 'fruit', 'legume', 'nut', 'seed', |
| 250 | | 'oil', 'herb', 'spice', 'carb', 'beverage') |
| 251 | | GROUP BY r.id, r.name, u.username, r.kcal_sum, r.servings |
| 252 | | HAVING COUNT(*) = (SELECT COUNT(*) |
| 253 | | FROM recipe_contains_ingredient rci2 |
| 254 | | WHERE rci2.recipe_id = r.id) |
| | 249 | WHERE |
| | 250 | NOT EXISTS ( |
| | 251 | SELECT 1 |
| | 252 | FROM recipe_contains_ingredient rci |
| | 253 | WHERE rci.recipe_id = r.id |
| | 254 | AND NOT EXISTS ( |
| | 255 | SELECT 1 |
| | 256 | FROM ingredient i |
| | 257 | WHERE i.id = rci.ingredient_id |
| | 258 | AND i.type IN ('vegetable', 'fruit', 'legume', 'nut', 'seed', |
| | 259 | 'oil', 'herb', 'spice', 'carb', 'beverage'))) |
| | 260 | AND NOT EXISTS ( |
| | 261 | SELECT 1 |
| | 262 | FROM nutrient n |
| | 263 | WHERE n.type = 'macro' |
| | 264 | AND EXISTS (SELECT 1 FROM ingredient_contains_nutrient icn0 |
| | 265 | WHERE icn0.nutrient_id = n.id) |
| | 266 | AND NOT EXISTS ( |
| | 267 | SELECT 1 |
| | 268 | FROM recipe_contains_ingredient rci2 |
| | 269 | JOIN ingredient_contains_nutrient icn |
| | 270 | ON icn.ingredient_id = rci2.ingredient_id |
| | 271 | WHERE rci2.recipe_id = r.id |
| | 272 | AND icn.nutrient_id = n.id |
| | 273 | AND icn.quantity > 0)) |
| 259 | | Plant ← {'vegetable', 'fruit', 'legume', 'nut', 'seed', |
| 260 | | 'oil', 'herb', 'spice', 'carb', 'beverage'} |
| 261 | | |
| 262 | | AnimalUse ← π_{rci.recipe_id} ( |
| 263 | | σ_{i.type ∉ Plant} ( |
| 264 | | Recipe_Contains_Ingredient ⋈_{rci.ingredient_id = i.id} Ingredient |
| 265 | | ) |
| 266 | | ) |
| 267 | | |
| 268 | | PlantOnly ← π_{rci.recipe_id} (Recipe_Contains_Ingredient) − AnimalUse |
| 269 | | |
| | 279 | Plant ← {'vegetable','fruit','legume','nut','seed','oil','herb','spice','carb','beverage'} |
| | 280 | AllRec ← π_{recipe_id} (Recipe_Contains_Ingredient) |
| | 281 | |
| | 282 | -- division 1: recipes that use an ingredient outside Plant |
| | 283 | NonPlant ← π_{rci.recipe_id} ( |
| | 284 | σ_{i.type ∉ Plant} ( |
| | 285 | Recipe_Contains_Ingredient ⋈_{rci.ingredient_id = i.id} Ingredient)) |
| | 286 | |
| | 287 | -- the divisor: macronutrients that are recorded for at least one ingredient |
| | 288 | Macros ← π_{n.id} (σ_{n.type = 'macro'} (Nutrient) ⋉ Ingredient_Contains_Nutrient) |
| | 289 | |
| | 290 | -- what each recipe actually supplies |
| | 291 | Supplied ← π_{rci.recipe_id, icn.nutrient_id} ( |
| | 292 | σ_{icn.quantity > 0} ( |
| | 293 | Recipe_Contains_Ingredient |
| | 294 | ⋈_{rci.ingredient_id = icn.ingredient_id} |
| | 295 | Ingredient_Contains_Nutrient)) |
| | 296 | |
| | 297 | -- division 2, written as a difference: recipes missing at least one macro |
| | 298 | Missing ← π_{recipe_id} ( (AllRec × Macros) − Supplied ) |
| | 299 | |
| | 300 | Result ← AllRec − NonPlant − Missing |
| | 301 | |
| 271 | | γ_{r.id, r.name, u.username; COUNT(*) → ingredient_count} ( |
| 272 | | (PlantOnly ⋈_{recipe_id = r.id} Recipe) |
| 273 | | ⋈_{r.user_id = u.id} User |
| 274 | | ⋈_{r.id = rci.recipe_id} Recipe_Contains_Ingredient |
| | 303 | π_{name, username → author, kcal_sum/servings → kcal_per_portion, |
| | 304 | ingredients, macros_supplied, tagged_vegan} ( |
| | 305 | Result ⋈_{recipe_id = r.id} (Recipe ⋈_{r.user_id = u.id} User) |