Analityk Systemowy Analiza systemowa, wymagania, UML, API i integracje Poznaj tematy

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

Objaw nie jest przyczyną

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';
Przykładowy wynik: jedno zamówienie — 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;
Stan bieżący: zamówienie 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;
Historia: 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;
Płatności: 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;
Zdarzenia: dwa rekordy 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

  1. 10:01 — zamówienie utworzone.
  2. 10:03 — płatność potwierdzona.
  3. 10:04 — zdarzenie logistyczne wysłane.
  4. 10:06 — zamówienie anulowane.
  5. 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.

Wyniki fixture: dwa zamówienia bez pozycji, jedno anulowane i opłacone, jedno zdarzenie bez identyfikatora, jeden powtórzony identyfikator, jeden status bez odpowiednika w historii oraz jedno nowe zamówienie zablokowanego klienta. Każdy zbiór jest kandydatem do osobnego sprawdzenia wymagania; nie wolno sumować tych liczb jako „ośmiu błędów”, ponieważ jeden obiekt może spełniać kilka warunków.

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;
Oczekiwany wynik testu: 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.

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

PoziomPrzykładGranica
DowódBrak zdarzenia ORDER_CANCELLED.Potwierdza stan tabeli.
HipotezaModuł publikacji nie obsłużył anulowania.Wymaga logów i konfiguracji.
WniosekProces kompensacji wymaga dalszej weryfikacji.Łączy dane, wymaganie i oś czasu.

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

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.