SQL w analizie błędów i testach systemowych
Użytkownik zgłasza: „Klient opłacił zamówienie, następnie je anulował, ale system nadal pokazuje przygotowanie przesyłki”. Komunikat opisuje objaw. SQL pomaga sprawdzić stan i odtworzyć sekwencję, ale nie powinien udawać, że sam zna przyczynę.
Komunikat użytkownika opisuje objaw
Stan CANCELLED przy płatności PAID może oznaczać błąd, oczekiwany zwrot, stan przejściowy, opóźnienie albo niepełny model statusów.
Krok 1 — jednoznaczna identyfikacja obiektu
Najpierw trzeba ustalić, którego zamówienia dotyczy zgłoszenie. Użyteczne są order_id, identyfikator zewnętrzny, adres e-mail klienta z datą oraz identyfikator korelacyjny. Nie należy zaczynać od szerokiego zapytania, które miesza kilka podobnych rekordów.
SELECT o.order_id, o.external_order_id, o.created_at
FROM orders AS o
INNER JOIN customers AS c ON c.customer_id = o.customer_id
WHERE c.email = 'anna@example.test'
AND o.created_at >= '2026-07-04'
AND o.created_at < '2026-07-05';
1002 / EXT-1002. Dopiero jednoznaczny wynik pozwala przejść dalej. Gdyby zapytanie zwróciło kilka rekordów, potrzebny byłby dodatkowy identyfikator lub czas zgłoszenia; wybór „pierwszego pasującego” mógłby skierować analizę na inny obiekt.Krok 2 — aktualny stan zamówienia
SELECT
order_id,
order_status,
payment_status,
external_order_id,
created_at,
updated_at
FROM orders
WHERE order_id = 1002;
1002 ma status CANCELLED, płatność PAID i identyfikator EXT-1002. To punkt startowy, nie diagnoza.To daje punkt startowy. Warto zapisać wynik wraz z czasem odczytu i środowiskiem. Aktualny status jest ważny, ale sam nie pokazuje kolejności zmian.
Krok 3 — historia statusów
SELECT status, changed_at, changed_by
FROM order_status_history
WHERE order_id = 1002
ORDER BY changed_at ASC;
NEW 10:01 → CANCELLED 10:06. Historia potwierdza kolejność zapisanych zmian, ale nie zawiera informacji, czy powstało zdarzenie kompensujące.Historia może pokazać brak wpisu, powtórzenie, nietypową kolejność albo źródło zmiany. Brak wpisu nie wyjaśnia jeszcze, czy proces go nie wykonał, czy historia nie jest pełnym źródłem prawdy.
Krok 4 — płatność
SELECT
p.payment_id,
p.payment_status,
p.amount,
p.provider_reference,
p.created_at,
p.updated_at
FROM payments AS p
WHERE p.order_id = 1002
ORDER BY p.created_at ASC;
PAID 10:03 oraz REFUND_PENDING 10:08. Drugi rekord wskazuje rozpoczęcie zwrotu po anulowaniu.Nie zakładaj, że orders.payment_status jest jedynym źródłem prawdy. Płatność może mieć historię, korekty albo kilka prób. Liczba rekordów i czas aktualizacji są częścią analizy.
Krok 5 — zdarzenia integracyjne
SELECT
event_id,
event_type,
external_id,
processing_status,
created_at
FROM integration_events
WHERE order_id = 1002
ORDER BY created_at ASC;
ORDER_SENT_TO_LOGISTICS z tym samym EXT-1002, w tym retry. Brakuje śladu ORDER_CANCELLED w tej tabeli.Sprawdź, czy powstało zdarzenie anulowania, czy ma identyfikator korelacyjny, czy zostało ponowione i czy system zewnętrzny potwierdził obsługę. Brak rekordu oznacza brak śladu w tej tabeli, nie automatycznie brak wysłania w całym systemie.
Krok 6 — porównanie osi czasu
- 10:01 — zamówienie utworzone.
- 10:03 — płatność potwierdzona.
- 10:04 — zdarzenie logistyczne wysłane.
- 10:06 — zamówienie anulowane.
- 10:07 — brak widocznego zdarzenia kompensującego.
Taka oś pozwala postawić hipotezę: system mógł nie obsłużyć anulowania po wysłaniu wcześniejszego zdarzenia. Hipotezę trzeba potwierdzić w logach aplikacji, konfiguracji procesu i zasadach kompensacji.
Zapytania wykrywające anomalie
-- Zamówienia bez pozycji
SELECT o.order_id
FROM orders AS o
LEFT JOIN order_items AS oi ON oi.order_id = o.order_id
WHERE oi.order_item_id IS NULL;
-- Anulowane zamówienia z płatnością PAID
SELECT order_id
FROM orders
WHERE order_status = 'CANCELLED'
AND payment_status = 'PAID';
-- Zdarzenia bez identyfikatora korelacyjnego
SELECT event_id, order_id, event_type
FROM integration_events
WHERE external_id IS NULL;
-- Powtórzone identyfikatory zdarzeń
SELECT external_id, COUNT(*) AS event_count
FROM integration_events
WHERE external_id IS NOT NULL
GROUP BY external_id
HAVING COUNT(*) > 1;
-- Aktualny status bez odpowiednika w historii
SELECT o.order_id, o.order_status
FROM orders AS o
LEFT JOIN order_status_history AS h
ON h.order_id = o.order_id
AND h.status = o.order_status
WHERE h.history_id IS NULL;
-- Zablokowani klienci z nowymi zamówieniami
SELECT c.customer_id, o.order_id
FROM customers AS c
INNER JOIN orders AS o ON o.customer_id = c.customer_id
WHERE c.customer_status = 'BLOCKED'
AND o.order_status = 'NEW';
Każdy wynik oznacza rekord wymagający weryfikacji reguły biznesowej. Nie przedstawiaj go automatycznie jako błędu: duplikat może być niepoprawnym retry, ale może też być przewidzianą historią prób.
SQL w testach systemowych
Test można opisać jako: stan początkowy → wykonanie scenariusza → stan końcowy. Przykład: po anulowaniu zamówienia system ustawia CANCELLED, zapisuje historię i po czasie anulowania nie wysyła już nowego zdarzenia realizacji.
SELECT
o.order_status,
COUNT(DISTINCT h.history_id) AS cancelled_history_entries,
COUNT(DISTINCT e.event_id) AS logistics_events
FROM orders AS o
LEFT JOIN order_status_history AS h
ON h.order_id = o.order_id
AND h.status = 'CANCELLED'
LEFT JOIN integration_events AS e
ON e.order_id = o.order_id
AND e.event_type = 'ORDER_SENT_TO_LOGISTICS'
AND e.created_at > h.changed_at
WHERE o.order_id = 1002
GROUP BY o.order_status;
CANCELLED, jeden wpis historii i zero zdarzeń realizacji. Każda wartość jest osobną asercją. Jeśli nie znamy stanu początkowego albo fixture był współdzielony przez kilka testów, wynik może opisywać pozostałość po innym scenariuszu.- sprawdź rekord zamówienia;
- sprawdź wpis historii;
- sprawdź liczbę zdarzeń;
- sprawdź brak płatności;
- porównaj czas zmiany i czas zdarzenia;
- wyklucz duplikaty.
Test przeszedł w interfejsie, ale nie w danych
Komunikat sukcesu w UI nie potwierdza jeszcze pełnego wykonania procesu. Rekord mógł nie powstać, mógł zostać zapisany dwa razy albo otrzymać błędną wartość domyślną. Możliwa jest też operacja częściowa: stan lokalny zmienił się, lecz zdarzenie nie zostało wysłane, albo system zewnętrzny przyjął zdarzenie, ale lokalny status pozostał stary.
Dowód, hipoteza i wniosek
Bezpieczeństwo pracy
Pracuj na danych z minimalnym zakresem, najlepiej przez dostęp tylko do odczytu. Maskuj dane osobowe, ogranicz czas i zakres zapytań, sprawdzaj plan ciężkich operacji i nie kopiuj produkcyjnych rekordów do nieautoryzowanych narzędzi ani publicznego AI.
Dokumentowanie analizy błędu
Identyfikator zgłoszenia:
Środowisko:
Obiekt biznesowy:
Identyfikatory:
Objaw:
Oczekiwany wynik:
Stan danych:
Oś czasu:
Zapytania:
Wyniki:
Hipotezy:
Dalsza weryfikacja:
Wniosek:
Checklista analityka
- Czy obiekt został jednoznacznie zidentyfikowany?
- Czy sprawdzono stan bieżący i historię?
- Czy sprawdzono powiązane obiekty oraz integracje?
- Czy porównano czasy zdarzeń?
- Czy wynik jest dowodem, czy tylko poszlaką?
- Czy zapytanie było bezpieczne?
- Czy analiza zawiera oczekiwane wymaganie i następny krok?
Dalsza ścieżka
SQL pozwala zobaczyć ślady pozostawione przez proces. Nie zastąpi logów, dokumentacji ani rozmowy z zespołem, ale oddziela „system podobno zrobił” od „system zapisał dokładnie to”. Przy ustalaniu przyczyny wróć również do wymagań i procesu analizy systemowej oraz sprawdź kontrakt API i przebieg integracji.