= Преглед: v_customer_contract_meals = ||= Датотека ||= `views/10_customer_contract_meals_view.sql` || ||= Шема ||= `kbnteam` || ||= Категорија ||= Оперативна поддршка || ||= Поврзани индекси ||= Ги користи индексите од `indexes/v_menu_meal_index.sql` || == Опис == Ги наведува оброците достапни на купувач под активни договори. Го прикажува целосното мени на ресторанот поврзан со договорот на компанијата на купувачот, вклучувајќи состојки и алергени преку CTE агрегации. Прегледот автоматски ги филтрира само активни договори и ги проверува тековните датуми на договори. '''Клучни филтри:''' * `contract_status_name = 'active'` (case-insensitive) * `CURRENT_DATE BETWEEN contract_start_date AND contract_end_date` == Зависности == ||= Табела ||= Тип на употреба || || `kbnteam.customer` || Главна табела || || `kbnteam.api_user` || JOIN — детали за купувачот || || `kbnteam.company` || JOIN — компанија || || `kbnteam.contract` || JOIN — договор || || `kbnteam.contract_status` || JOIN — статус на договор (филтер: 'active') || || `kbnteam.restaurant` || JOIN — ресторан || || `kbnteam.meal` || JOIN — оброци на ресторанот || || `kbnteam.category` || JOIN — категорија || || `kbnteam.meal_ingredient` || LEFT JOIN (CTE) — состојки || || `kbnteam.ingredient` || JOIN (CTE) — назив на состојка || || `kbnteam.alergen_ingredient` || JOIN (CTE) — алерген-состојка || || `kbnteam.alergen` || JOIN (CTE) — назив на алерген || == SQL Дефиниција == {{{ #!sql CREATE OR REPLACE VIEW kbnteam.v_customer_contract_meals AS WITH meal_ingredients AS ( SELECT x.meal_id, string_agg(x.ingr_name, ', ' ORDER BY x.ingr_name) AS ingredients FROM ( SELECT DISTINCT mi.meal_id, i.ingr_name FROM kbnteam.meal_ingredient mi JOIN kbnteam.ingredient i ON i.ingr_id = mi.ingr_id ) x GROUP BY x.meal_id ), meal_allergens AS ( SELECT x.meal_id, string_agg(x.alergen_name, ', ' ORDER BY x.alergen_name) AS allergens FROM ( SELECT DISTINCT mi.meal_id, a.alergen_name FROM kbnteam.meal_ingredient mi JOIN kbnteam.alergen_ingredient ai ON ai.ingr_id = mi.ingr_id JOIN kbnteam.alergen a ON a.alergen_id = ai.alergen_id ) x GROUP BY x.meal_id ) SELECT cu.user_id AS customer_user_id, au.user_first_name AS customer_first_name, au.user_last_name AS customer_last_name, au.user_email AS customer_email, cu.company_id, cmp.company_name, ct.contract_id, r.rest_id, r.rest_name, m.meal_id, m.meal_name, m.meal_description, m.meal_price, m.meal_weight, c.cat_id, c.cat_name, COALESCE(mi.ingredients, '') AS ingredients, COALESCE(ma.allergens, '') AS allergens FROM kbnteam.customer cu JOIN kbnteam.api_user au ON au.user_id = cu.user_id JOIN kbnteam.company cmp ON cmp.company_id = cu.company_id JOIN kbnteam.contract ct ON ct.company_id = cu.company_id JOIN kbnteam.contract_status cs ON cs.contract_status_id = ct.contract_status_id JOIN kbnteam.restaurant r ON r.rest_id = ct.rest_id JOIN kbnteam.meal m ON m.rest_id = r.rest_id JOIN kbnteam.category c ON c.cat_id = m.cat_id LEFT JOIN meal_ingredients mi ON mi.meal_id = m.meal_id LEFT JOIN meal_allergens ma ON ma.meal_id = m.meal_id WHERE lower(cs.contract_status_name) = 'active' AND CURRENT_DATE BETWEEN ct.contract_start_date AND ct.contract_end_date; }}} == Тестирање на перформанси == === Препорачано тест прашање === {{{ #!sql SET search_path TO kbnteam; SET statement_timeout = '60s'; -- Тест: по купувач (типичен App use-case) EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT * FROM kbnteam.v_customer_contract_meals WHERE customer_user_id = 1; -- Тест 2: по ресторан EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT * FROM kbnteam.v_customer_contract_meals WHERE rest_id = 1; }}} === Применети индекси (од v_menu_meal_index.sql) === {{{ #!sql CREATE INDEX IF NOT EXISTS idx_meal_cat_id_meal_id ON kbnteam.meal (cat_id, meal_id); CREATE INDEX IF NOT EXISTS idx_meal_ingredient_meal_id_ingr_id ON kbnteam.meal_ingredient (meal_id, ingr_id); CREATE INDEX IF NOT EXISTS idx_alergen_ingredient_ingr_id_alergen_id ON kbnteam.alergen_ingredient (ingr_id, alergen_id); }}} === Резултати пред индексирање === ||= Метрика ||= Тест 1 (customer) ||= Тест 2 (rest_id) || || Planning Time || ___ ms || ___ ms || || Execution Time || ___ ms || ___ ms || || Rows Returned || ___ || ___ || || meal scan || ___ || ___ || || meal_ingredient scan || ___ || ___ || {{{ -- Излезот од EXPLAIN ANALYZE овде (пред индексирање) }}} === Резултати по индексирање === ||= Метрика ||= Тест 1 (customer) ||= Тест 2 (rest_id) || || Planning Time || ___ ms || ___ ms || || Execution Time || ___ ms || ___ ms || || Rows Returned || ___ || ___ || || meal scan || ___ || ___ || || meal_ingredient scan || ___ || ___ || {{{ -- Излезот од EXPLAIN ANALYZE овде (по индексирање) }}} === Анализа на подобрување === ||= Метрика ||= Пред ||= По ||= Δ Подобрување || || Execution Time (Тест 1) || ___ ms || ___ ms || ___ % || || Execution Time (Тест 2) || ___ ms || ___ ms || ___ % ||