Bazy danych bez tajemnic

Schemat „Kotomarketu”

11 min
What you'll learn
  • wskazywać właściwą tabelę spośród pięciu tabel „Kotomarketu”: users, products, orders, order_items, events
  • czytać diagram ER: określać kardynalność powiązania (1:N, N:M, 1:1) po tym, gdzie leży klucz obcy
  • rozwiązywać relację „wiele do wielu” przez tabelę pośredniczącą z dwoma FK — jak order_items z order_id + product_id
  • wyjaśniać, dlaczego zawartości zamówienia nie można przechowywać jako ciągu id bezpośrednio w orders

Dziś QUERY wysuwa na główny stół cały inwentarz naraz. Pięć świecących płaszczyzn zawisa w powietrzu i powoli się obraca — mapa ocalałego świata. Obok migocze dziennik konserwacji dołączony do migawki, a jedna linijka jest w nim podkreślona: „Przekazuję pięć tabel i ślad szóstej. — K.” Przeliczasz płaszczyzny. Dokładnie pięć. Gdzie ślad?

QUERY: Nie rozpraszaj się śladami. Najpierw naucz się tych pięciu tak, żeby trafiać tu z zamkniętymi oczami — resztę archiwum pokaże samo, gdy uzna cię za gotowego.

Pięć tabel „Kotomarketu”

Dalej będziemy pracować z tą bazą — migawką sklepu internetowego z 2024 roku. Traktuj ją jak mapę sklepu: kto przyszedł, co leży na wystawie, co kupiono i co działo się przed zakupem.

TabelaCo przechowuje
userskupujących: id, imię i nazwisko, miasto oraz datę rejestracji
productstowary z wystawy: id, nazwę, kategorię, cenę i stan magazynowy
orderszamówienia: id, user_id, datę, status i łączną kwotę
order_itemszawartość zamówień: jaki towar, ile sztuk i po jakiej cenie
eventszdarzenia użytkowników: wyświetlenia, dodania do koszyka i zakupy

Powiązania czyta się tak: jeden user → wiele orders; jeden order → wiele order_items; jeden product → wiele order_items. Jeśli się pogubisz, otwórz schemat po prawej — działa jak plan sali sprzedaży.

Zajrzyjmy do tabeli zamówień: w każdym wierszu jest user_id — odwołanie do kupującego. Tak jedna tabela łączy się z drugą, a mapa przestaje być pięcioma osobnymi wyspami.

Pięć holograficznych tabel-płaszczyzn obraca się jak konstelacja, połączonych nićmi; z boku ledwo widoczny przerywany ślad szóstego konturu
Mapa archiwum: pięć tabel i powiązania między nimi. Dziennik konserwacji obiecuje jeszcze „ślad szóstej” — ale na razie go nie widać.

Kotomarket’s five tables

From here on we’ll be working with this database — a of an online shop from 2024. Hold it like a map of the store: who walked in, what’s on the shelves, what they bought, and what they did before buying.

TableWhat it holds
usersbuyers: id, name, city, and signup date
productsstorefront items: id, name, category, price, and stock
ordersorders: id, user_id, date, status, and total
order_itemsorder contents: which product, how many, and at what price
eventsbehavioral events: views, add-to-carts, and purchases

The links read like this: one user → many orders; one order → many order_items; one product → many order_items. If you get lost, open the schema on the right — it’s like the floor plan of the shop.

Let’s peek into the orders table: every row has a user_id — a reference to a buyer. That’s how one table links to another, and the map stops being five separate islands.

Zamówienia i ich powiązanie z kupującym przez user_id:
Query result
iduser_idstatustotal_amount
118paid5980.00
210paid19750.00
326cancelled9560.00
426paid15530.00
58paid26710.00
637paid42110.00

Jak czytać diagram ER

Mapę, którą rozwinął QUERY, w branży nazywa się diagramem ER (entity–relationship): prostokąty to tabele, linie między nimi to powiązania po kluczach obcych. Najważniejsza na linii jest kardynalność: ile wierszy z jednej strony może odpowiadać ilu wierszom z drugiej.

  • 1:N, jeden-do-wielu — najczęstsze powiązanie. Jeden kupujący — wiele zamówień. Klucz obcy zawsze leży po stronie „wielu”: user_id przechowuje się w orders, a nie odwrotnie. To prosta reguła czytania: znalazłeś FK — znalazłeś stronę N.
  • N:M, wiele-do-wielu — w jednym zamówieniu może być wiele towarów, a jeden towar może pojawiać się w wielu zamówieniach. Bezpośrednio takiego powiązania w bazie relacyjnej wyrazić się nie da: klucz obcy nie ma gdzie się zmieścić. Rozwiązuje się je przez tabelę pośredniczącą — u nas to order_items. Każdy jej wiersz niesie parę odwołań order_id + product_id i zamienia jedno powiązanie N:M w dwa powiązania 1:N. Przy okazji samo powiązanie zyskuje atrybuty — liczbę sztuk i cenę w chwili zakupu.
  • 1:1, jeden-do-jednego — spotyka się rzadziej: na przykład ciężkie albo prywatne pola przenosi się do osobnej tabeli z tym samym kluczem.
-- Rozplątanie N:M w działaniu: pary „zamówienie — towar” z order_items
SELECT order_id, product_id, quantity
FROM order_items
LIMIT 6;
usersidnameproductsidpriceordersiduser_ideventsuser_idproduct_idorder_itemsorder_idproduct_iduser_id → idproduct_id → idPKFK (reference)
Diagram ER „Kotomarketu”: powiązania 1:N od users do orders i rozplątanie N:M między orders a products przez order_items.

Pułapka: przechowywać zawartość zamówienia bezpośrednio w orders — jako ciąg '7,12,3' albo tablicę identyfikatorów. Takich danych nie da się ochronić kluczem obcym, rzetelnie policzyć ani połączyć z katalogiem bez akrobatyki. Widzisz relację „wiele do wielu” — twórz tabelę pośredniczącą z dwoma kluczami obcymi, jak order_items.

Interview question

Pytanie z rozmowy kwalifikacyjnej: jak w bazie relacyjnej zrealizować powiązanie „wiele do wielu”?

Mocna odpowiedź: przez tabelę pośredniczącą z dwoma kluczami obcymi do łączonych tabel — jak order_items z order_id i product_id: zamienia ona N:M w dwa powiązania 1:N. Przy okazji można przechowywać w niej atrybuty samego powiązania — liczbę sztuk, cenę w chwili zakupu. Klucz główny takiej tabeli jest albo złożony z dwóch FK, albo sztuczny id.

Check yourself
Gdzie w schemacie widać, jaki towar trafił do jakiego zamówienia?