A Northstar laborban az orders tábla
rendelésenként egy sort, az order_items
tábla pedig rendelési tételenként egy sort tartalmaz.
Egy rendeléshez több tétel tartozhat. Az üzleti kérdés: „A rendelések
mekkora hányada késik a hét napos ígéretet meghaladóan?” A
csatlakoztatás után a sor már nem feltétlenül rendelést jelent; a késési
címke az adott rendelés valamennyi tételsorán ismétlődik. A cél, hogy a
kulcsokat, a kapcsolat kardinalitását és a számítás nevezőjét a
lekérdezés előtt ellenőrizzük.
Tanulási eredmények. Az olvasó képes (1) egy-a-többhöz és egy-az-egyhez kapcsolatot ellenőrizni; (2) join előtti és utáni sorszámot értelmezni; (3) hibás tételszintű átlagot felismerni; (4) helyes rendelésenkénti aggregációt építeni; (5) az adatszerződés sérülésekor tudatosan hibával megállni.
Legyen az -edik rendelés késési jelzője , tételsorainak száma . A rendelésalapú késési arány
Ha rendelés- és tételtáblát összekapcsolunk, majd az így létrejött sorokon átlagolunk, akkor ehelyett
keletkezik. Ez tételszámmal súlyozott rendelési
átlag. Csak külön feltételek mellett egyezik meg a keresett
rendelésalapú aránnyal. LEFT JOIN esetén a nulla tételes
rendelések egy NULL-lal kiegészített sort adhatnak; ezt a külön esetet
nem szabad észrevétlenül ugyanebbe a képletbe beleérteni.
A példa SQLite-ban végrehajtható, és nem igényel külső adatfájlt:
CREATE TABLE orders_demo (
order_id TEXT PRIMARY KEY,
delivery_days INTEGER NOT NULL,
promised_days INTEGER NOT NULL
);
CREATE TABLE items_demo (
item_id TEXT PRIMARY KEY,
order_id TEXT NOT NULL REFERENCES orders_demo(order_id),
line_total_minor INTEGER NOT NULL
);
INSERT INTO orders_demo VALUES ('A', 9, 7), ('B', 5, 7);
INSERT INTO items_demo VALUES
('A1', 'A', 100), ('A2', 'A', 200), ('A3', 'A', 300),
('B1', 'B', 400);
-- HELYTELEN a rendelések arányához: minden tételsort egyszer számol.
SELECT AVG(CASE WHEN o.delivery_days > o.promised_days
THEN 1.0 ELSE 0.0 END) AS weighted_rate
FROM orders_demo AS o
JOIN items_demo AS i ON i.order_id = o.order_id;
-- HELYES: a címke rendelésenként egyetlen alkalommal szerepel.
SELECT AVG(CASE WHEN delivery_days > promised_days
THEN 1.0 ELSE 0.0 END) AS order_rate
FROM orders_demo;
-- Egy másik HELYES eljárás: tételeket előbb rendelésenként aggregálunk.
WITH item_totals AS (
SELECT order_id, COUNT(*) AS item_rows,
SUM(line_total_minor) AS item_total_minor
FROM items_demo GROUP BY order_id
)
SELECT o.order_id, o.delivery_days > o.promised_days AS target_late,
t.item_rows, t.item_total_minor
FROM orders_demo AS o
LEFT JOIN item_totals AS t ON t.order_id = o.order_id
ORDER BY o.order_id;Kézi kontroll: a hibás érték
,
a helyes rendelésalapú késési arány
.
Az item_totals eredménye A rendelésre 3 tétel és 600 cent,
B-re 1 tétel és 400 cent. A LEFT JOIN után két sor
marad.
import sqlite3
with sqlite3.connect(":memory:") as conn:
conn.executescript("""
CREATE TABLE orders_demo(order_id TEXT PRIMARY KEY,
delivery_days INTEGER, promised_days INTEGER);
CREATE TABLE items_demo(item_id TEXT PRIMARY KEY, order_id TEXT,
line_total_minor INTEGER);
INSERT INTO orders_demo VALUES ('A',9,7),('B',5,7);
INSERT INTO items_demo VALUES ('A1','A',100),('A2','A',200),
('A3','A',300),('B1','B',400);
""")
wrong = conn.execute("""SELECT AVG(CASE WHEN o.delivery_days > o.promised_days
THEN 1.0 ELSE 0.0 END)
FROM orders_demo o JOIN items_demo i ON o.order_id=i.order_id""").fetchone()[0]
right = conn.execute("""SELECT AVG(CASE WHEN delivery_days > promised_days
THEN 1.0 ELSE 0.0 END)
FROM orders_demo""").fetchone()[0]
assert abs(wrong - 0.75) < 1e-12
assert abs(right - 0.50) < 1e-12
assert conn.execute("SELECT COUNT(*) FROM orders_demo").fetchone()[0] == 2
assert conn.execute("SELECT COUNT(*) FROM items_demo").fetchone()[0] == 4A kódblokk szintaktikája és az ellenőrző értékek külső fájlt nem igényelnek. A teljes Northstar-adatkészlet sorszámait azonban kizárólag a mellékelt laboradatokból szabad igazolni.
Az alábbi ellenőrzéseket célszerű beépíteni a feldolgozó folyamatba:
orders.order_id egyedi és nem hiányzó;
order_items.item_id szintén egyedi.order_items.order_id létező rendelésre mutat
(árva tétel nincs), vagy az eltérés dokumentáltan karanténba kerül.orders és item_totals közötti
összekapcsolás után a rendelések száma és az order_id
egyedisége változatlan.shipping_fee_minor rendelésenkénti attribútumot
nem összegezzük közvetlenül a nyers tételsorokon;
máskülönben a díj a tételszámmal sokszorozódik.LEFT JOIN megőrzi a rendelést, de a hiányzó tételösszegre
vonatkozó üzleti szabályt külön kell meghatározni: a NULL
nem minden esetben jogosan alakítható nullává.1. Értelmezés. Három rendelés címkéje 1, 0 és 0; rendre 5, 1 és 2 tételük van. Mennyi a rendelés- és mennyi a tételszinten számolt késési arány?
2. Implementálás. Írj olyan SQL-lekérdezést, amely a
orders és order_items táblákból rendelésenként
adja vissza az item_rows és item_total_minor
értékeket, és megtartja a nulla tételes rendeléseket is.
3. Hibakeresés. Mi történik, ha a
customers táblában ugyanaz a customer_id
kétszer szerepel, majd orders-szel összekapcsoljuk? Mit
kell ellenőrizni a join előtt?
4. Transzfer. A tételszámok 5, 1, 2, a késési címkék 1, 0, 0. Mi változik, ha a legnagyobb tételszámú rendelés még tíz tételt kap? Miért nem változhat a helyes üzleti mutató?
WITH t AS (SELECT order_id, COUNT(*) AS item_rows, SUM(line_total_minor) AS item_total_minor FROM order_items GROUP BY order_id) SELECT o.order_id, t.item_rows, t.item_total_minor FROM orders o LEFT JOIN t ON t.order_id=o.order_id;
A hiányzó összegek üzleti jelentését ezután kell rendezni.customers.customer_id egyediségét és
hiánytalanságát ellenőrizni kell, és a nem egyedi törzset először
javítani vagy elutasítani.A JOIN szintaktikailag hibátlan lehet akkor is, ha
statisztikailag rossz nevezőt hoz létre. A mérőszám megfigyelési
egységét előbb rögzítjük, és csak utána választjuk meg a
csatlakoztatást. A következő alfejezetben az időben helyes
korábbi rendeléseket CTE-vel és ablakfüggvényekkel állítjuk
elő.
Join-invariáns. Amikor rendelésenként egy kimenetet
kérünk, a csatlakoztatás után ellenőrizni kell a order_id
egyediségét, vagy a tételszintű adatot előbb rendelésenként aggregálni.
A sorok számának változása önmagában nem feltétlen hiba, de a mérendő
egység és a súlyozás megváltozása dokumentálást igényel.