0Pricing
Coding Interview Prep · Lekcja

Pełny zestaw zadań do próbnej rozmowy rekrutacyjnej

Zadania kompleksowe z limitem czasu, łączące złączenia, funkcje okna i CTE w warunkach rozmowy rekrutacyjnej.

Pełny zestaw zadań do próbnej rozmowy rekrutacyjnej to bezpłatna lekcja Coding Interview Prep na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Coding Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Przebieg rundy rozmowy kwalifikacyjnej z SQL

Ten końcowy moduł przeprowadzi Państwa przez pełne przykładowe zadania łączące złączenia, funkcje okna i CTE w warunkach rozmowy kwalifikacyjnej. Najpierw umiejętność nadrzędna: jak zachować się podczas rozmowy.

  • Ponownie sformułować problem i potwierdzić schemat.
  • Doprecyzować przypadki brzegowe (NULL-e, remisy, duplikaty) przed rozpoczęciem kodowania.
  • Omówić swoje podejście, a następnie napisać zapytanie.
  • Sprawdzić rozwiązanie na małym przykładowym zbiorze w myślach.

Rekruterzy oceniają sposób pracy w takim samym stopniu jak końcowe zapytanie.

Wspólny schemat

Wszystkie poniższe zadania korzystają z tego niewielkiego schematu sklepu internetowego. Proszę zapoznać się z nim raz, aby każde zapytanie było zrozumiałe.

  • customers(id, name, country)
  • orders(id, customer_id, order_date, status, amount)
  • order_items(order_id, product_id, quantity)
  • products(id, name, category, price)

Należy o nim pamiętać — pozostała część lekcji odwołuje się do tych tabel.

-- orders.status is one of: 'paid','pending','cancelled'
-- amount is the order total in the customer's currency

Zadanie 1: Klienci o największych wydatkach

„Należy zwrócić 3 klientów o największej łącznej kwocie opłaconych zamówień wraz z nazwą klienta i łączną kwotą”.

Podejście: odfiltrować opłacone zamówienia, zagregować je według klienta, posortować wynik i ograniczyć jego rozmiar. Należy zaznaczyć, że wykluczają Państwo zamówienia anulowane i oczekujące — to przypadek brzegowy, który rekruterzy celowo umieszczają w zadaniu.

SELECT c.name,
       SUM(o.amount) AS total_spend
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'paid'
GROUP BY c.id, c.name
ORDER BY total_spend DESC
LIMIT 3;

Zadanie 2: Klienci, którzy nigdy nie złożyli zamówienia

„Należy wyświetlić klientów, którzy nigdy nie złożyli zamówienia”. To wzorzec anti-join. Dwa przejrzyste rozwiązania to LEFT JOIN z IS NULL albo NOT EXISTS.

Preferowane jest NOT EXISTS, ponieważ bezpiecznie obsługuje NULL (w przeciwieństwie do NOT IN). Warto wspomnieć o tym rozróżnieniu — właśnie na to czeka rekruter.

-- NULL-safe anti-join
SELECT c.id, c.name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
);

Zadanie 3: Druga najwyższa kwota zamówienia

„Należy znaleźć drugą najwyższą różną kwotę zamówienia”. Najbardziej przejrzyste rozwiązanie, odporne na remisy, używa DENSE_RANK, dzięki czemu identyczne kwoty otrzymują tę samą rangę.

Warto wskazać przypadek brzegowy: jeśli nie istnieje druga różna wartość, zapytanie nie zwróci żadnych wierszy. Może to być akceptowalne albo może wymagać opakowania w COALESCE, zależnie od wymagań.

SELECT amount
FROM (
  SELECT amount,
         DENSE_RANK() OVER (ORDER BY amount DESC) AS rnk
  FROM orders
) ranked
WHERE rnk = 2;

Zadanie 4: Najnowsze zamówienie każdego klienta

„Należy zwrócić najnowsze zamówienie każdego klienta”. To wzorzec zachowania najnowszego wiersza dla każdego klucza, rozwiązywany za pomocą ROW_NUMBER z partycjonowaniem według klienta i sortowaniem malejąco według daty.

Należy dodać dodatkowe kryterium rozstrzygające, takie jak identyfikator zamówienia, aby wynik był deterministyczny, gdy dwa zamówienia mają tę samą datę. To szczegół, który uwzględniają najlepsi kandydaci.

SELECT customer_id, id AS order_id, order_date, amount
FROM (
  SELECT o.*,
         ROW_NUMBER() OVER (
           PARTITION BY customer_id
           ORDER BY order_date DESC, id DESC
         ) AS rn
  FROM orders o
) t
WHERE rn = 1;

Zadanie 5: Zmiana miesiąc do miesiąca

„Należy obliczyć miesięczny przychód z opłaconych zamówień oraz jego procentową zmianę w stosunku do poprzedniego miesiąca”. Wymaga to połączenia agregacji w CTE z funkcją LAG.

W pierwszym kroku należy wykonać agregację według miesiąca, a w drugim porównać każdy miesiąc z poprzednim za pomocą LAG. Należy zabezpieczyć dzielenie, aby pierwszy miesiąc, który nie ma poprzednika, nie powodował błędu.

WITH monthly AS (
  SELECT DATE_TRUNC('month', order_date) AS mth,
         SUM(amount) AS revenue
  FROM orders
  WHERE status = 'paid'
  GROUP BY DATE_TRUNC('month', order_date)
)
SELECT mth,
       revenue,
       LAG(revenue) OVER (ORDER BY mth) AS prev_revenue,
       ROUND(
         100.0 * (revenue - LAG(revenue) OVER (ORDER BY mth))
         / NULLIF(LAG(revenue) OVER (ORDER BY mth), 0), 2
       ) AS pct_change
FROM monthly
ORDER BY mth;

Zadanie 6: Najlepszy produkt w każdej kategorii

„Dla każdej kategorii należy zwrócić najlepiej sprzedający się produkt według łącznej liczby sztuk”. To wzorzec top-N dla grup: agregacja, nadanie rang w obrębie partycji i odfiltrowanie rangi 1.

Jeśli remisy mają znaczenie, należy zamienić ROW_NUMBER na RANK, aby uwzględnić wszystkich współliderów. Wskazanie tego wyboru pokazuje, że rozumieją Państwo różnicę.

WITH sales AS (
  SELECT p.category,
         p.name AS product,
         SUM(oi.quantity) AS qty
  FROM order_items oi
  JOIN products p ON p.id = oi.product_id
  GROUP BY p.category, p.name
)
SELECT category, product, qty
FROM (
  SELECT s.*,
         ROW_NUMBER() OVER (
           PARTITION BY category ORDER BY qty DESC
         ) AS rn
  FROM sales s
) r
WHERE rn = 1;

Zadanie 7: Narastająca suma przychodu

„Należy wyświetlić narastającą sumę przychodu z opłaconych zamówień według dnia”. Funkcja okna SUM z uporządkowaną ramą tworzy narastającą sumę bez złączenia tabeli z samą sobą.

Warto wspomnieć o ramie ROWS dla prawdziwego narastania wiersz po wierszu — domyślna rama RANGE może nieoczekiwanie działać przy powtarzających się datach.

SELECT order_date,
       SUM(daily) OVER (
         ORDER BY order_date
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS running_total
FROM (
  SELECT order_date, SUM(amount) AS daily
  FROM orders
  WHERE status = 'paid'
  GROUP BY order_date
) d
ORDER BY order_date;

Zadanie 8: Kolejne aktywne dni

„Należy znaleźć użytkowników, którzy mają co najmniej 3 kolejne dni, w których złożono opłacone zamówienie”. To wariant wzorca gaps-and-islands wykorzystujący trik różnicy numerów wierszy.

Odjęcie numeru wiersza przypisanego użytkownikowi od daty daje stałą wartość w obrębie kolejnego ciągu dni, dlatego można grupować według tej wartości i zliczać wiersze. To sygnał kompetencji na poziomie seniora.

WITH days AS (
  SELECT DISTINCT customer_id, order_date
  FROM orders WHERE status = 'paid'
),
grp AS (
  SELECT customer_id, order_date,
         order_date - (ROW_NUMBER() OVER (
           PARTITION BY customer_id ORDER BY order_date
         ) * INTERVAL '1 day') AS island
  FROM days
)
SELECT customer_id, COUNT(*) AS streak_len
FROM grp
GROUP BY customer_id, island
HAVING COUNT(*) >= 3;

Wydajność i typowe pułapki

Po przedstawieniu poprawnego zapytania rekruterzy pytają: „Jak można je przyspieszyć?” i sprawdzają, czy pamiętają Państwo o typowych pułapkach. Warto mieć gotową następującą listę kontrolną:

  • Należy indeksować kolumny używane do złączeń i filtrowania (np. orders(customer_id, status)), a w WHERE unikać funkcji stosowanych na indeksowanych kolumnach.
  • W przypadku dużych operacji anti-join należy preferować EXISTS zamiast IN; NOT IN z wartością NULL po cichu nie zwraca żadnych wyników.
  • Filtrowanie w WHERE kolumny z tabeli dołączonej za pomocą złączenia zewnętrznego po cichu zmienia je w złączenie wewnętrzne.
  • Zawsze należy dodać kryterium rozstrzygające remisy, aby wyniki top-N były deterministyczne.
  • Należy sprawdzić plan EXPLAIN pod kątem skanów sekwencyjnych na dużych tabelach.

Szybki test

Potrzebują Państwo pojedynczego, najnowszego zamówienia każdego klienta, a dwa zamówienia mogą mieć tę samą datę.

Podsumowanie: pełny zestaw próbnych zadań rekrutacyjnych

Przeszli już Państwo przez najczęściej spotykane zadania rekrutacyjne od początku do końca:

  • Agregacja + LIMIT dla top-N wydatków.
  • Anti-joiny z użyciem NOT EXISTS (bezpieczne dla NULL).
  • DENSE_RANK dla N-tej najwyższej wartości, ROW_NUMBER dla najnowszego wiersza dla klucza i najlepszego elementu w grupie.
  • LAG dla zmian miesiąc do miesiąca, SUM OVER dla sum narastających.
  • Trik z numerami wierszy w schemacie gaps-and-islands do wykrywania ciągów.
  • Każdą odpowiedź należy zakończyć omówieniem indeksów, EXPLAIN oraz typowych pułapek.

Często zadawane pytania

Czy lekcja „Pełny zestaw zadań do próbnej rozmowy rekrutacyjnej” jest bezpłatna?

Tak — pełny tekst „Pełny zestaw zadań do próbnej rozmowy rekrutacyjnej” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Coding Interview Prep, przejdź na CoddyKit PRO. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Co nauczysz się w „Pełny zestaw zadań do próbnej rozmowy rekrutacyjnej”?

Zadania kompleksowe z limitem czasu, łączące złączenia, funkcje okna i CTE w warunkach rozmowy rekrutacyjnej. Ćwiczysz Coding Interview Prep z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Coding Interview Prep?

Nie wymagamy żadnego doświadczenia. Coding Interview Prep w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Pełny zestaw zadań do próbnej rozmowy rekrutacyjnej”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Coding Interview Prep?

Tak. Każda lekcja Coding Interview Prep zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Normalizacja do postaci 3NF
  2. Modelowanie ER i krotność relacji
  3. Schemat gwiazdy i projektowanie hurtowni danych
  4. Pełny zestaw zadań do próbnej rozmowy rekrutacyjnej
← Powrót do Coding Interview Prep