{
  "assessmentTests": {
    "sql_test": {
      "name": "Test SQL",
      "desc": "30 pytań scenariuszowych na temat filtrowania, semantyki NULL, połączeń, agregacji, podkwerend i funkcji okienkowych — sprawdź, czy Twoja znajomość SQL odpowiada temu, co pracodawcy rozumieją przez biegłość w SQL.",
      "recommendation": "Twój profil umiejętności SQL",
      "results": {
        "beginner": {
          "name": "Początkujący",
          "desc": "Potrafisz napisać działającą instrukcję SELECT i filtrować kilka warunków, ale pytania, które przegapiłeś, skupiają się wokół obsługi NULL i mechaniki połączeń, a nie składni — porównanie kolumny z NULL przy użyciu =, co LEFT JOIN faktycznie zachowuje, jak działają granice BETWEEN. Nic z tego nie chodzi o bycie słabym w bazach danych; to są konkretne zasady, które wprawiają w trudności ludzi, którzy nauczyli się SQL przez próby i błędy, a nie ze standardu. Mają znaczenie w pracy, ponieważ każda z nich to miejsce, gdzie zapytanie zwraca wiarygodnie wyglądającą, ale złą liczbę wierszy.",
          "recommendation": "Zacznij od trzech rzeczy, w tej kolejności: dlaczego WHERE col = NULL nigdy niczego nie zwraca (i IS NULL jest wymagane zamiast tego), jak INNER JOIN usuwa niezapasowane wiersze, podczas gdy LEFT JOIN je zachowuje, i dokładnie jakie granice BETWEEN zawiera. Samouczek SQL Mode Analytics i dokumentacja PostgreSQL obejmują wszystkie trzy z pracującymi przykładami."
        },
        "intermediate": {
          "name": "Zaawansowany początkujący",
          "desc": "Komfortowo obsługujesz codzienne zapytania raportów — połączenia, GROUP BY, proste filtrowanie — i nie byłbyś spowolniony rutynową pracą dashboardu lub analityką ad hoc. Różnica między tym poziomem a Zaawansowanym jest głównie w tym, co dzieje się, gdy klauzule wchodzą w interakcję: klauzula WHERE na połączonej tabeli cicho przekształcająca LEFT JOIN z powrotem w INNER JOIN, połączenie, które rozprzestrzenia się liczby wierszy przed zastosowaniem agregacji, NOT IN, które cicho zwraca nic, ponieważ jedna wartość NULL wkradła się do podkwerendy. To są tego rodzaju błędy, które przechodzą szybki przegląd i pojawiają się tylko wtedy, gdy ktoś porównuje całkowitą wartość z innym raportem.",
          "recommendation": "Skoncentruj się na tym, jak klauzule wchodzą w interakcję, a nie na tym, co każda robi sama: filtrowanie WHERE na kolumnach po lewej stronie LEFT JOIN, mnożenie liczby wierszy z połączeń jeden-do-wielu przed zastosowaniem agregacji, i dlaczego NOT IN przerywa się w obecności NULL (EXISTS zwykle nie). Następnie HAVING versus WHERE, ponieważ ten podział wprawia w trudności ludzi, którzy już znają obie klauzule indywidualnie."
        },
        "advanced": {
          "name": "Zaawansowany",
          "desc": "To jest poziom, który większość ogłoszeń o pracę rozumie przez \"silny SQL\". Czytasz wielołączeniowe zapytanie i możesz przewidzieć jego liczbę wierszy, zanim je uruchomisz, wiesz dlaczego zestaw wyników się zmienił, a nie tylko że się zmienił, i sięgasz po CTE lub funkcję okienkową zamiast zagnieżdżonego podkwerendy, gdy jest to jaśniejsze narzędzie. To, co oddziela tę kategorię od szczytu, to defensywna strona pracy: wiedza, którą funkcję rankingową wybrać, gdy remisy mają znaczenie, co transakcja izoluje od równoczesnej sesji, i co faktycznie robi brakująca reguła ON DELETE na poziomie bazy danych.",
          "recommendation": "Zanurz się w części, które chronią dane, których dotykają również inne osoby: różnica między RANK, DENSE_RANK i ROW_NUMBER pod względem remisów, co COMMIT faktycznie czyni widocznym i dla kogo, i zachowanie klucza obcego przy DELETE. Artykuły pogłębiające The Index newsletter'a lub SQL for Devs na temat funkcji okienkowych i izolacji transakcji to następny przystań dla obu."
        },
        "expert": {
          "name": "Ekspert",
          "desc": "Uzyskałeś wyniki na górze każdej sekcji — filtrowanie i semantyka NULL, połączenia i operacje zbiorów, agregacja i podkwerendy, oraz funkcje okienkowe, CTE i ograniczenia. Praktycznie oznacza to, że możesz otrzymać obcy raport z wielołączeniowym zapytaniem i wyjaśnić, dlaczego zwraca liczbę wierszy, którą zwraca, a nie tylko co składnia mówi, że powinna robić, co jest trudniejszą i bardziej wartościową umiejętnością. Na tym poziomie język zapytań jest rzadko czynnikiem ograniczającym; limit to zwykle projekt schematu lub rozmiar danych pod spodem.",
          "recommendation": "Zwroty są teraz w planach wykonywania i projektach: czytanie EXPLAIN zamiast założenia, że zapytanie jest wolne, strategia indeksowania jako kompromis wobec kosztów zapisu, a nie darmowe wygrane, i decyzje normalizacji, które się utrzymują, gdy schemat rośnie. Jeśli uczestniczysz w proceście rekrutacji, opisz błąd w zapytaniu, taki jak rozprzestrzenianie się połączeń lub pułapka NOT IN/NULL, którą znalazłeś w produkcji, zamiast wymieniać funkcje SQL — to pokazuje rozumowanie, a nie tylko słownictwo."
        }
      },
      "questions": [
        {
          "question": "Tabela ma kolumnę age, którą można ustawić na NULL. Uruchamiasz SELECT * FROM users WHERE age = NULL. Ile wierszy to zwraca, nawet jeśli kilka wierszy ma age ustawione na NULL?",
          "options": [
            {
              "icon": "",
              "label": "Każdy wiersz, gdzie age to NULL, ponieważ = dopasowuje NULL jak każdą inną wartość"
            },
            {
              "icon": "",
              "label": "Zero — porównanie czegokolwiek z NULL za pomocą = daje UNKNOWN, nigdy TRUE, więc żadne wiersze się nie zgadzają; IS NULL jest wymagane zamiast tego"
            },
            {
              "icon": "",
              "label": "Błąd składni — NULL nie może pojawić się po prawej stronie ="
            },
            {
              "icon": "",
              "label": "Każdy wiersz w tabeli, ponieważ porównania NULL domyślnie dają TRUE"
            }
          ]
        },
        {
          "question": "Uruchamiasz SELECT DISTINCT department, role FROM employees. Co DISTINCT usuwa duplikaty?",
          "options": [
            {
              "icon": "",
              "label": "Kombinacja department i role razem — wiersz jest usuwany tylko wtedy, gdy obie kolumny dokładnie dopasowują inny wiersz"
            },
            {
              "icon": "",
              "label": "Tylko duplikatowe wartości department, zachowując każdy role"
            },
            {
              "icon": "",
              "label": "Tylko duplikatowe wartości role, zachowując każdy department"
            },
            {
              "icon": "",
              "label": "Nic — DISTINCT działa tylko z jedną kolumną"
            }
          ]
        },
        {
          "question": "Kolumna name jest filtrowana za pomocą WHERE name LIKE 'A_'. Które z tych wartości pasują: 'A', 'Al', 'Ana', 'Ally'?",
          "options": [
            {
              "icon": "",
              "label": "'A' — podkreślnik jest opcjonalny i dopasowuje zero lub więcej znaków"
            },
            {
              "icon": "",
              "label": "'Al' — podkreślnik dopasowuje dokładnie jeden znak, więc LIKE 'A_' dopasowuje każdy łańcuch dwuznakowy zaczynający się od A"
            },
            {
              "icon": "",
              "label": "'Ana' i 'Ally' — podkreślnik dopasowuje dowolną liczbę końcowych znaków"
            },
            {
              "icon": "",
              "label": "Wszystkie cztery wartości pasują, ponieważ LIKE ignoruje długość"
            }
          ]
        },
        {
          "question": "Kolumna price jest filtrowana za pomocą WHERE price BETWEEN 10 AND 20. Czy wiersze z price równym dokładnie 10 lub dokładnie 20 są uwzględniane?",
          "options": [
            {
              "icon": "",
              "label": "Nie — BETWEEN wyklucza oba końce"
            },
            {
              "icon": "",
              "label": "Tak — BETWEEN jest włączny na obu końcach, równoważny price >= 10 AND price <= 20"
            },
            {
              "icon": "",
              "label": "Tylko price = 10 jest uwzględniany; górna granica jest wyłączna"
            },
            {
              "icon": "",
              "label": "Tylko price = 20 jest uwzględniany; dolna granica jest wyłączna"
            }
          ]
        },
        {
          "question": "Tabela orders ma 10 wierszy, a 3 z nich mają NULL shipped_date. Co zwraca SELECT COUNT(*) FROM orders i co zwraca SELECT COUNT(shipped_date) FROM orders?",
          "options": [
            {
              "icon": "",
              "label": "10, następnie 10 — COUNT zawsze liczy wiersze niezależnie od NULL"
            },
            {
              "icon": "",
              "label": "7, następnie 7 — obie formy pomijają wiersze z NULL"
            },
            {
              "icon": "",
              "label": "10, następnie 7 — COUNT(*) liczy każdy wiersz, COUNT(column) liczy tylko wiersze, gdzie ta kolumna nie jest NULL"
            },
            {
              "icon": "",
              "label": "10, następnie 3 — COUNT(column) liczy tylko wartości NULL"
            }
          ]
        },
        {
          "question": "Uruchamiasz SELECT name, salary FROM employees ORDER BY 2 DESC. Do czego odnosi się 2?",
          "options": [
            {
              "icon": "",
              "label": "Błąd składni — ORDER BY akceptuje tylko nazwy kolumn, nie liczby"
            },
            {
              "icon": "",
              "label": "Drugi wiersz wyniku"
            },
            {
              "icon": "",
              "label": "Wartość dosłowna 2, używana jako tiebreaker"
            },
            {
              "icon": "",
              "label": "Druga kolumna na liście SELECT, salary — ORDER BY akceptuje numer pozycji kolumny jako skrót"
            }
          ]
        },
        {
          "question": "W standardowym SQL, do czego oblicza się 'Ana' || ' ' || 'Lee'?",
          "options": [
            {
              "icon": "",
              "label": "Błąd składni — SQL nie ma operatora konkatenacji"
            },
            {
              "icon": "",
              "label": "3 — || jest traktowany jako logiczny OR i zwraca liczbę"
            },
            {
              "icon": "",
              "label": "'AnaLee' — || łączy bez zachowywania spacji"
            },
            {
              "icon": "",
              "label": "'Ana Lee' — || to standardowy operator konkatenacji łańcuchów SQL"
            }
          ]
        },
        {
          "question": "Które z tych jest dokładnie równoważne WHERE status IN ('open', 'pending', 'review')?",
          "options": [
            {
              "icon": "",
              "label": "WHERE status = 'open' AND status = 'pending' AND status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status != 'open' OR status != 'pending' OR status != 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status = 'open' OR status = 'pending' OR status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status LIKE 'open,pending,review'"
            }
          ]
        },
        {
          "question": "customers ma 100 wierszy; 20 z nich nigdy nie złożyło zamówienia. Uruchamiasz SELECT c.id FROM customers c INNER JOIN orders o ON c.id = o.customer_id. Czy 20 klientów bez zamówień pojawia się w wyniku?",
          "options": [
            {
              "icon": "",
              "label": "Tak, raz każdy, z o.id pokazanym jako NULL"
            },
            {
              "icon": "",
              "label": "Tak, ale tylko jeśli pojawią się również w klauzuli WHERE"
            },
            {
              "icon": "",
              "label": "Nie — INNER JOIN zwraca tylko wiersze, które mają dopasowanie w obu tabelach, więc klienci bez zamówień są całkowicie usuwani"
            },
            {
              "icon": "",
              "label": "Tak, ale zduplikowanych raz na każdą kolumnę w orders"
            }
          ]
        },
        {
          "question": "Chcesz każdego klienta, niezależnie od tego, czy ma zamówienia, więc piszesz SELECT c.id, o.total FROM customers c LEFT JOIN orders o ON c.id = o.customer_id WHERE o.total > 100. Czy to wciąż zwraca klientów bez zamówień?",
          "options": [
            {
              "icon": "",
              "label": "Nie — filtrowanie o.total w klauzuli WHERE usuwa wiersze NULL, które LEFT JOIN wyprodukował dla niezapasowanych klientów, więc zachowuje się jak INNER JOIN"
            },
            {
              "icon": "",
              "label": "Tak — LEFT JOIN zawsze zachowuje każdy wiersz z customers, niezależnie od tego, co następuje"
            },
            {
              "icon": "",
              "label": "Tak, z o.total pokazanym jako 0 dla klientów bez zamówień"
            },
            {
              "icon": "",
              "label": "Nie — LEFT JOIN cicho konwertuje się na RIGHT JOIN, gdy dodana jest klauzula WHERE"
            }
          ]
        },
        {
          "question": "Tabela employees ma kolumnę id i kolumnę manager_id, która wskazuje na inny wiersz id. Aby wyświetlić każdego pracownika obok imienia ich menadżera, łączysz tabelę do siebie: SELECT e.name, m.name FROM employees e JOIN employees m ON e.manager_id = m.id. Jak to się nazywa?",
          "options": [
            {
              "icon": "",
              "label": "Cross join — każdy pracownik jest dopasowywany z każdym menadżerem"
            },
            {
              "icon": "",
              "label": "Recursive join — pobiera pełny łańcuch zarządzania"
            },
            {
              "icon": "",
              "label": "Self-join — ta sama tabela jest łączona do siebie przy użyciu dwóch różnych aliasów"
            },
            {
              "icon": "",
              "label": "To jest nieprawidłowy SQL — tabela nie może być łączona do siebie"
            }
          ]
        },
        {
          "question": "Dwa SELECT z tymi samymi kolumnami są łączone za pomocą UNION. Jeśli oba zapytania zwracają identyczny wiersz, ile kopii tego wiersza pojawia się w ostatecznym wyniku?",
          "options": [
            {
              "icon": "",
              "label": "Jeden — UNION usuwa duplikatowe wiersze w połączonym wyniku; UNION ALL zachowaćby obie kopie"
            },
            {
              "icon": "",
              "label": "Dwa — UNION zachowuje każdy wiersz z obu zapytań"
            },
            {
              "icon": "",
              "label": "Zero — UNION usuwa każdy wiersz, który pojawia się w obu zapytaniach"
            },
            {
              "icon": "",
              "label": "Zależy to od tego, które zapytanie wymieniło wiersz pierwsze"
            }
          ]
        },
        {
          "question": "sizes ma 3 wiersze i colors ma 4 wiersze. Ile wierszy zwraca SELECT * FROM sizes CROSS JOIN colors?",
          "options": [
            {
              "icon": "",
              "label": "7 — CROSS JOIN dodaje liczby wierszy razem"
            },
            {
              "icon": "",
              "label": "12 — CROSS JOIN zwraca każdą możliwą kombinację wierszy z obu tabel (3 x 4)"
            },
            {
              "icon": "",
              "label": "3 — CROSS JOIN zwraca jeden wiersz na wiersz w pierwszej tabeli"
            },
            {
              "icon": "",
              "label": "0 — CROSS JOIN wymaga warunku ON lub zwraca nic"
            }
          ]
        },
        {
          "question": "orders ma 1 wiersz dla zamówienia nr 100, a order_items ma 3 wiersze dla zamówienia nr 100 (jeden na pozycję). Uruchamiasz SELECT o.id, o.total FROM orders o JOIN order_items i ON o.id = i.order_id WHERE o.id = 100. Ile wierszy wraca dla zamówienia nr 100?",
          "options": [
            {
              "icon": "",
              "label": "3 — połączenie tworzy jeden wiersz wyjścia dla każdego wiersza order_items, więc pojedynczy wiersz zamówienia nr 100 jest powtarzany raz na pozycję"
            },
            {
              "icon": "",
              "label": "1 — orders ma tylko jeden wiersz dla zamówienia nr 100, więc połączenie nie może wytworzyć więcej"
            },
            {
              "icon": "",
              "label": "4 — jeden wiersz dla zamówienia plus jeden na pozycję"
            },
            {
              "icon": "",
              "label": "0 — połączenie jednowierszowej tabeli do trzywierszowej tabeli na nieunikalnym kluczu się nie powodzi"
            }
          ]
        },
        {
          "question": "SELECT c.name, o.id FROM customers c RIGHT JOIN orders o ON c.id = o.customer_id zwraca to samo, co które z nich?",
          "options": [
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c INNER JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o LEFT JOIN customers c ON c.id = o.customer_id — zamiana kolejności tabeli i użycie LEFT JOIN zamiast RIGHT JOIN jest równoważne"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c LEFT JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o CROSS JOIN customers c"
            }
          ]
        },
        {
          "question": "W standardowym SQL uruchamiasz SELECT department, name, AVG(salary) FROM employees GROUP BY department. Czy to prawidłowe zapytanie?",
          "options": [
            {
              "icon": "",
              "label": "Tak — GROUP BY musi zawierać tylko department, ponieważ jest wymieniony pierwszy"
            },
            {
              "icon": "",
              "label": "Nie — name jest wybierany, ale ani nie jest agregowany, ani nie jest wymieniony w GROUP BY, a standardowy SQL wymaga, aby każda nieagregowana wybrana kolumna pojawiła się w klauzuli GROUP BY"
            },
            {
              "icon": "",
              "label": "Tak — SQL automatycznie wybiera jedno arbitralne name na department"
            },
            {
              "icon": "",
              "label": "Nie — AVG() nie może być łączone z GROUP BY w tym samym zapytaniu"
            }
          ]
        },
        {
          "question": "Chcesz departamentów, których średnia pensja przekracza 80000. Która klauzula filtruje wartość zagregowaną taką jak AVG(salary) po grupowaniu — WHERE czy HAVING?",
          "options": [
            {
              "icon": "",
              "label": "WHERE — HAVING jest używane tylko z zapytaniami UNION"
            },
            {
              "icon": "",
              "label": "Każda z nich działa identycznie z funkcjami agregującymi"
            },
            {
              "icon": "",
              "label": "Żadna — filtrowanie agregacji wymaga podkwerendy"
            },
            {
              "icon": "",
              "label": "HAVING — WHERE filtruje poszczególne wiersze przed grupowaniem, HAVING filtruje grupy po agregacji"
            }
          ]
        },
        {
          "question": "Piszesz SELECT salary * 1.1 AS new_salary FROM employees WHERE new_salary > 50000. Czy to się uruchamia?",
          "options": [
            {
              "icon": "",
              "label": "Tak — aliasy zdefiniowane w SELECT są zawsze dostępne dla WHERE w tym samym zapytaniu"
            },
            {
              "icon": "",
              "label": "Tak, ale tylko dla numerycznych aliasów"
            },
            {
              "icon": "",
              "label": "Nie — AS nie jest dozwolone w zapytaniu filtrowanym WHERE"
            },
            {
              "icon": "",
              "label": "Nie — WHERE jest oceniany przed SELECT przypisuje alias new_salary, więc alias jeszcze nie istnieje w tym momencie wykonania"
            }
          ]
        },
        {
          "question": "SELECT name FROM employees e WHERE salary > (SELECT AVG(salary) FROM employees WHERE department = e.department). Dlaczego to się nazywa skorelowaną podkwerendą?",
          "options": [
            {
              "icon": "",
              "label": "Ponieważ zamiast klauzuli WHERE używa JOIN"
            },
            {
              "icon": "",
              "label": "Wewnętrzne zapytanie odnosi się do e.department z zewnętrznego zapytania, więc musi być ponownie oceniane dla każdego wiersza, który zewnętrzne zapytanie rozważa"
            },
            {
              "icon": "",
              "label": "Ponieważ zwraca więcej niż jedną kolumnę"
            },
            {
              "icon": "",
              "label": "Ponieważ uruchamia się dokładnie raz przed rozpoczęciem zewnętrznego zapytania"
            }
          ]
        },
        {
          "question": "Podkwerenda SELECT manager_id FROM employees zwraca niektóre wartości NULL wraz z rzeczywistymi id. Uruchamiasz SELECT name FROM employees WHERE id NOT IN (SELECT manager_id FROM employees). Co się dzieje?",
          "options": [
            {
              "icon": "",
              "label": "Zwraca każdego pracownika, który nie jest menadżerem, ignorując wartości NULL"
            },
            {
              "icon": "",
              "label": "Zwraca zero wierszy — jedno NULL na liście NOT IN sprawia, że każde porównanie jest UNKNOWN, więc żaden wiersz nie może spełnić warunku"
            },
            {
              "icon": "",
              "label": "Podnosi błąd, ponieważ NOT IN nie może być używane z podkwerendami"
            },
            {
              "icon": "",
              "label": "Zwraca każdego pracownika, ponieważ NULL jest traktowany jako nieograniczony"
            }
          ]
        },
        {
          "question": "SELECT name FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id). Co to zwraca?",
          "options": [
            {
              "icon": "",
              "label": "Każdego klienta, który ma co najmniej jeden wiersz w orders — EXISTS sprawdza tylko, czy podkwerenda zwraca jakieś wiersze, nie jakie wartości zawierają"
            },
            {
              "icon": "",
              "label": "Każdego klienta, ponieważ SELECT 1 zawsze zwraca true"
            },
            {
              "icon": "",
              "label": "Błąd, ponieważ podkwerenda wybiera liczbę zamiast nazwy kolumny"
            },
            {
              "icon": "",
              "label": "Tylko klientów z dokładnie jednym zamówieniem"
            }
          ]
        },
        {
          "question": "Piszesz SELECT name, (SELECT order_id FROM orders WHERE customer_id = c.id) AS last_order FROM customers c, a dany klient ma 3 wiersze w orders. Co się dzieje, gdy to zapytanie się uruchamia?",
          "options": [
            {
              "icon": "",
              "label": "Zwraca pierwszą pasującą order_id i cicho ignoruje pozostałe dwie"
            },
            {
              "icon": "",
              "label": "Zwraca łańcuch wszystkich trzech order_id oddzielonych przecinkami"
            },
            {
              "icon": "",
              "label": "Zwraca 3 wiersze dla tego klienta, jeden na zamówienie"
            },
            {
              "icon": "",
              "label": "Podnosi błąd w czasie wykonywania — skalarna podkwerenda na liście SELECT musi zwrócić co najwyżej jeden wiersz, a to zwraca trzy"
            }
          ]
        },
        {
          "question": "Cztery wiersze wiążą się za najwyższą ocenę. Używając RANK() ORDER BY score DESC, wszystkie cztery otrzymują rangę 1. Jaką rangę otrzymuje następny wiersz?",
          "options": [
            {
              "icon": "",
              "label": "5 — RANK() pozostawia lukę równą liczbie związanych wierszy, zanim będzie kontynuować"
            },
            {
              "icon": "",
              "label": "2 — RANK() zawsze zwiększa dokładnie jeden po każdym wiążu"
            },
            {
              "icon": "",
              "label": "1 — każdy następny wiersz otrzymuje również rangę 1"
            },
            {
              "icon": "",
              "label": "4 — RANK() restartuje liczenie z liczby wiążu"
            }
          ]
        },
        {
          "question": "Cztery wiersze wiążą się za najwyższą ocenę. Używając DENSE_RANK() ORDER BY score DESC, wszystkie cztery otrzymują rangę 1. Jaką rangę otrzymuje następny wiersz?",
          "options": [
            {
              "icon": "",
              "label": "5 — DENSE_RANK() zachowuje się dokładnie jak RANK()"
            },
            {
              "icon": "",
              "label": "1 — DENSE_RANK() przypisuje tę samą rangę każdemu pozostałemu wierszowi"
            },
            {
              "icon": "",
              "label": "2 — DENSE_RANK() nigdy nie pozostawia luk, więc następna odrębna wartość zawsze otrzymuje następną kolejną rangę"
            },
            {
              "icon": "",
              "label": "3 — DENSE_RANK() pomija jedną rangę na grupę wiążu"
            }
          ]
        },
        {
          "question": "SUM(amount) OVER (PARTITION BY region ORDER BY amount) jest dodawana do zapytania. Co robi PARTITION BY region tutaj?",
          "options": [
            {
              "icon": "",
              "label": "Restartuje bieżącą sumę oddzielnie dla każdego regionu, zamiast akumulować się w całym zestawie wyników"
            },
            {
              "icon": "",
              "label": "Filtruje wyniki do jednego regionu"
            },
            {
              "icon": "",
              "label": "Grupuje i zwija wiersze do jednego na region, jak GROUP BY"
            },
            {
              "icon": "",
              "label": "Sortuje regiony alfabetycznie przed sumowaniem"
            }
          ]
        },
        {
          "question": "ROW_NUMBER() OVER (ORDER BY score DESC) jest stosowana do pięciu wierszy, z których dwa mają dokładnie ten sam wynik. Czy dwa wiersze mogą kiedyś otrzymać ten sam numer wiersza?",
          "options": [
            {
              "icon": "",
              "label": "Tak — związane wiersze zawsze dzielą ten sam numer wiersza"
            },
            {
              "icon": "",
              "label": "Tylko jeśli PARTITION BY jest również używane"
            },
            {
              "icon": "",
              "label": "Zależy to od tego, czy związek znajduje się na pierwszej czy ostatniej pozycji"
            },
            {
              "icon": "",
              "label": "Nie — ROW_NUMBER() zawsze przypisuje unikalną, ściśle rosnącą liczbę całkowitą do każdego wiersza, nawet gdy wartości są związane"
            }
          ]
        },
        {
          "question": "WITH high_earners AS (SELECT * FROM employees WHERE salary > 100000) SELECT department, COUNT(*) FROM high_earners GROUP BY department. Co to jest high_earners?",
          "options": [
            {
              "icon": "",
              "label": "Wspólne wyrażenie tabelaryczne (CTE) — nazwany, czasowy zestaw wyników, do którego reszta zapytania może odwoływać się jak do tabeli"
            },
            {
              "icon": "",
              "label": "Trwała tabela utworzona w bazie danych"
            },
            {
              "icon": "",
              "label": "Widok, który utrzymuje się po zakończeniu zapytania"
            },
            {
              "icon": "",
              "label": "Procedura przechowywana, którą trzeba wywołać oddzielnie"
            }
          ]
        },
        {
          "question": "Kolumna jest deklarowana PRIMARY KEY. Czy możesz wstawić wiersz, gdzie ta kolumna to NULL?",
          "options": [
            {
              "icon": "",
              "label": "Tak — PRIMARY KEY wymaga tylko unikalności, nie braku wartości NULL"
            },
            {
              "icon": "",
              "label": "Tak, ale tylko jeden wiersz NULL jest dozwolony, jak w przypadku ograniczenia UNIQUE"
            },
            {
              "icon": "",
              "label": "Nie — kolumna PRIMARY KEY jest niejawnie NOT NULL, więc wstawienie NULL do niej jest odrzucane"
            },
            {
              "icon": "",
              "label": "Zależy to od tego, czy kolumna ma również wartość domyślną"
            }
          ]
        },
        {
          "question": "Wewnątrz otwartej transakcji uruchamiasz UPDATE, ale jeszcze nie uruchomiłeś COMMIT. Z drugiego, oddzielnego połączenia z bazą danych, czy ta aktualizacja jest widoczna?",
          "options": [
            {
              "icon": "",
              "label": "Tak — wszystkie połączenia widzą każdy zapis w chwili jego uruchomienia"
            },
            {
              "icon": "",
              "label": "Tak, ale tylko jeśli drugie połączenie również otwiera transakcję"
            },
            {
              "icon": "",
              "label": "Zależy to tylko od tego, która tabela była aktualizowana"
            },
            {
              "icon": "",
              "label": "Nie — niezatwierdzona zmiana jest widoczna tylko wewnątrz transakcji, która ją dokonała, aż COMMIT ją utrwali i uczyni widoczną dla innych"
            }
          ]
        },
        {
          "question": "products.category_id ma ograniczenie FOREIGN KEY odnoszące się do categories.id. Próbujesz DELETE wiersz z categories, który wciąż ma products do niego wskazujące, bez określonej reguły ON DELETE. Co się dzieje?",
          "options": [
            {
              "icon": "",
              "label": "Wiersz kategoria jest usuwany, a dopasowujące wartości products.category_id są automatycznie ustawiane na NULL"
            },
            {
              "icon": "",
              "label": "Wiersz kategoria jest usuwany i każdy produkt, który do niego się odnosił, jest również usuwany"
            },
            {
              "icon": "",
              "label": "DELETE jest odrzucany — domyślne zachowanie klucza obcego blokuje usunięcie wiersza, do którego się odnoszą zależne wiersze"
            },
            {
              "icon": "",
              "label": "DELETE succeeds silently, leaving the products' category_id pointing at a category that no longer exists"
            }
          ]
        }
      ],
      "optionOrderVersion": "e0466e547cfd8a45"
    }
  }
}
