Към съдържанието
wannacode

Много таблици и таблица със себе си

Накратко: Няколко JOIN един след друг свързват верига от таблици, а self join свързва таблица със самата нея, например категорията с родителската ѝ категория.

Проблем

Оборотът по категории

Собственичката иска да знае от кои категории идват парите. Количеството и цената са в order_items. Дали поръчката е отказана, пише в orders. Категорията на продукта е в products, а името на категорията в categories.

Четири таблици за един отчет. JOIN не спира на две.

Идеята

Верига от JOIN

Всеки следващ JOIN добавя таблица към това, което вече е събрано. Поръчка 60, с продуктите и категориите им:

SQLбаза: магазин

Пътят е по външните ключове: orders → order_items (по order_id) → products (по product_id) → categories (по category_id). Всяка връзка е отделен JOIN … ON.

И products, и categories имат колона name. Затова тук им даваме имена с AS: product и category. Иначе в резултата щеше да има две колони name.

Пробвай

Кой какво е оценил

Покажи за всеки отзив името на клиента, името на продукта и оценката.

SQLбаза: магазин

Виж го

Изгубените пари

Оборотът по категории, без отказаните поръчки:

SQLбаза: магазин

Изглежда наред. Сега целият оборот, без категории:

SQLбаза: магазин

Шестте категории дават 1 537 €, а оборотът е 1 697 €.

1. Сборът по категории е 1 537 €, а целият оборот е 1 697 €. Къде са 160 €?

Във верига от JOIN всяка връзка може тихо да изхвърли редове. За продукт без категория двойка в categories няма. С LEFT JOIN към категориите продажбите остават, а COALESCE дава име на липсващата категория:

SQLбаза: магазин

Седем реда и сборът е 1 697 €. Щом отчетът брои пари, сравни сбора му с общия. Разликата показва изгубените редове.

Пробвай

Оборотът по градове

Покажи оборота по град на клиента, без отказаните поръчки.

SQLбаза: магазин

Идеята

Таблица, свързана със себе си

В категориите parent_id сочи към id в същата таблица. За да видиш категорията до родителската ѝ, свързваш categories със себе си. Таблицата влиза два пъти, с две различни кратки имена:

SQLбаза: магазин

c е категорията, parent е същата таблица, видяна като родител. ON parent.id = c.parent_id казва: родителят е редът, чието id е равно на parent_id на категорията. Това се казва self join. Тук кратките имена са задължителни: без тях name от двете копия не се различава.

LEFT JOIN е, за да останат „Храни“ и „Дом“, които нямат родител.

Упражнение

Две задачи

1. За новия каталог трябват всички 25 продукта с категорията и родителската категория. Подаръчната карта също трябва да е в списъка.

Продуктът, категорията и родителската категория, за всички продукти:

SQLбаза: магазин

2. Колко е оборотът на двете главни категории, „Храни“ и „Дом“? Без отказаните поръчки.

Оборотът по главна категория:

SQLбаза: магазин
По-точно, за любопитните

Редът на JOIN в една заявка не променя резултата на обикновения JOIN: базата сама избира от коя таблица да започне. При LEFT JOIN редът е важен, защото „лява“ е всичко, събрано преди него.

Таблица, свързана със себе си, дава само едно ниво нагоре. Дърво с много нива (подкатегория на подкатегория) се обхожда с WITH RECURSIVE, в модула за подзаявките.

Тест

Провери се

1. Заявка свързва orders, order_items, products и categories. Колко JOIN … ON има в нея?
2. Защо в FROM categories c LEFT JOIN categories parent … кратките имена са задължителни?
3. Отчет по категории с JOIN categories губи продуктите без категория. Как се пазят?
4. В резултата има две колони name (на клиента и на продукта). Какво правиш?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·