Kompendium Badań nad Bazami Danych SQL oraz Architekturą Hurtowni Danych

Logiczny Przebieg Przetwarzania Zapytania SQL (Logical Query Processing)
  • Silnik bazy danych nie przetwarza zapytania SQL w kolejności zapisu tekstu od góry do dołu. Kolejność wykonywania poszczególnych klauzul jest ściśle określona i uniezależniona od kolejności pisanej przez programistę.

  • Pełna, precyzyjna hierarchia logicznego przetwarzania zapytania SQL obejmuje następujące kroki:

    • FROM (wraz ze złączeniami JOIN): Identyfikacja i zestawienie tabel źródłowych oraz utworzenie początkowego zestawu wierszy.

    • ON: Ewaluacja warunków złączenia dla tabel i filtrowanie powiązanych rekordów.

    • WHERE: Filtrowanie surowych wierszy z tabel źródłowych na podstawie warunków logicznych jeszcze przed wykonaniem jakiejkolwiek agregacji.

    • GROUP BY: Podział przefiltrowanych rekordów na logiczne grupy na podstawie wskazanych kolumn.

    • HAVING: Filtrowanie skumulowanych i zagregowanych grup powstałych po działaniu klauzuli GROUP BY.

    • SELECT: Wyznaczenie ostatecznej listy kolumn, wyliczenie wyrażeń, ewaluacja funkcji oraz nadanie aliasów.

    • DISTINCT: Usunięcie zduplikowanych wierszy z wygenerowanego zbioru wynikowego.

    • ORDER BY: Uporządkowanie ostatecznego zbioru wyników według wskazanych kryteriów sortowania.

    • LIMIT / OFFSET / TOP: Ograniczenie liczby zwracanych wierszy i pominięcie określonej liczby wierszy początkowych (paginacja).

  • Zrozumienie tej kolejności wyjaśnia kluczowe ograniczenia składniowe: w klauzuli WHERE oraz HAVING nie można odwołać się do aliasu kolumny utworzonego w klauzuli SELECT, ponieważ SELECT jest ewaluowany logicznie po tych klauzulach. Z kolei klauzula ORDER BY może bezpiecznie korzystać z aliasów zdefiniowanych w SELECT, gdyż wykonuje się po nim.

Klauzule i Operatory Filtrowania, Sortowania oraz Paginacji
  • Klauzula WHERE – Selekcja przed grupowaniem:

    • Służy do filtrowania wierszy z tabeli źródłowej lub widoku na podstawie warunków logicznych jeszcze przed wykonaniem jakiejkolwiek agregacji. Operuje bezpośrednio na pojedynczych, surowych rekordach.

    • W warunkach WHERE kategorycznie zabronione jest stosowanie funkcji agregujących, takich jak SUM()SUM() czy AVG()AVG(), ponieważ wyliczenie agregatów następuje w późniejszych krokach logicznych (po grupowaniu).

  • Klauzula HAVING – Filtrowanie grup po wykonaniu GROUP BY:

    • Pozwala na odsiewanie skumulowanych grup wygenerowanych przez klauzulę GROUP BY.

    • W przeciwieństwie do WHERE, w warunkach HAVING można i należy stosować funkcje agregujące, np. HAVING SUM(kwota)>1000\text{HAVING SUM(kwota)} > 1000. Odrzuca całe zagregowane podzbiory danych, które nie spełniają zdefiniowanych kryteriów biznesowych.

  • Operator DISTINCT – Deduplikacja i wpływ na wydajność:

    • Umieszczany na początku instrukcji SELECT wymusza usunięcie wszystkich zduplikowanych wierszy z końcowego wyniku.

    • Działanie operatora wymaga od silnika wykonania operacji sortowania lub budowy tablicy mieszającej (hash table) dla wszystkich pobranych rekordów, co przy dużych wolumenach danych znacząco obciąża procesor i pamięć RAM. Stosowanie DISTINCT powinno być poprzedzone weryfikacją, czy duplikaty nie są rezultatem błędnie sformułowanych złączeń JOIN.

  • Sortowanie za pomocą ORDER BY (ASC i DESC):

    • Uporządkowuje ostateczny zbiór wyników według wskazanej kolumny lub wyrażenia.

    • Domyślnym porządkiem jest sortowanie rosnące (ASCASC), które można opcjonalnie zmienić na malejące (DESCDESC). Jest to ostatnia główna operacja logiczna zapytania przed przekazaniem danych użytkownikowi.

  • Obsługa wartości NULL w ORDER BY:

    • Wartość NULLNULL reprezentuje brak danych i jest traktowana w sposób specyficzny zależnie od systemu bazodanowego:

    • W systemach PostgreSQL oraz SQL Server wartości NULLNULL są traktowane domyślnie jako najmniejsze możliwe i przy sortowaniu ASCASC pojawiają się na samym początku wyniku. W silniku Oracle wartości NULLNULL są domyślnie traktowane jako największe.

    • Zachowanie to można kontrolować za pomocą klauzul NULLS FIRSTNULLS\ FIRST oraz NULLS LASTNULLS\ LAST.

  • Ograniczanie liczby zwracanych wierszy (LIMIT i TOP):

    • Pozwala na wycięcie podzbioru wyników z początku zbioru.

    • Systemy PostgreSQL i MySQL wykorzystują klauzulę LIMITLIMIT dopisywaną na samym końcu zapytania, podczas gdy system SQL Server wykorzystuje konstrukcję SELECT TOP N\text{SELECT TOP N} umieszczaną na początku klauzuli SELECT.

  • Mechanizm Paginacji z użyciem OFFSET:

    • Klauzula OFFSETOFFSET pomija określoną liczbę początkowych wierszy przed pobraniem kolejnej porcji danych. Najczęściej występuje w parze z LIMITLIMIT (np. LIMIT 10 OFFSET 20\text{LIMIT 10 OFFSET 20} w systemie PostgreSQL).

    • Przy bardzo dużych wartościach OFFSETOFFSET wydajność zapytania gwałtownie spada, ponieważ silnik bazy danych musi fizycznie odczytać i odrzucić wszystkie poprzedzające rekordy.

  • Aliasowanie za pomocą słowa kluczowego AS:

    • Nadaje tymczasowe, czytelne nazwy kolumnom lub tabelom (słowo kluczowe ASAS można pominąć, stosując odstęp).

    • Aliasy kolumn służą do budowania czytelnych nagłówków raportów oraz zapobiegania konfliktom nazw. Aliasy tabel są wymagane przy złożonych złączeniach wielu tabel w celu precyzyjnego jednoznacznego wskazania pochodzenia kolumn.

  • Operatory logiczne IN oraz NOT IN:

    • Operator ININ sprawdza, czy wartość znajduje się na liście statycznej lub w wyniku podzapytania (np. WHERE status IN (’NOWY’, ’W_TOKU’)\text{WHERE status IN ('NOWY', 'W\_TOKU')}), stanowiąc czytelną alternatywę dla wielokrotnych warunków OROR.

    • Operator NOT INNOT\ IN odfiltrowuje wiersze nieznajdujące się na liście. Jeżeli na liście wewnątrz NOT INNOT\ IN znajdzie się choćby jedna wartość NULLNULL, całe wyrażenie zwraca wartość UNKNOWNUNKNOWN, co powoduje zwrócenie pustego zbioru wyników przez zapytanie.

  • Inkluzywny operator przedziału BETWEEN:

    • Filtruje dane w podanym zakresie domkniętym (np. WHERE data BETWEEN ’2025-01-01’ AND ’2025-12-31’\text{WHERE data BETWEEN '2025-01-01' AND '2025-12-31'}). Granice przedziału (minmin i maxmax) są inkluzywne (wchodzą w skład zbioru wynikowego). Stanowi skrót logiczny dla wyrażenia kolumna≥min AND kolumna≤max\text{kolumna} \ge \text{min AND kolumna} \le \text{max}.

  • Wyszukiwanie wzorców tekstowych LIKE:

    • Znak procenta (%\%) zastępuje dowolny ciąg znaków o długości zero lub więcej. Znak podkreślenia (_\_) zastępuje dokładnie jeden, dowolny znak.

  • Priorytety operatorów logicznych (AND, OR, NOT):

    • Kolejność ewaluacji operatorów logicznych to: NOTNOT, następnie ANDAND, a na końcu OROR. Operator ANDAND wykonuje się przed operatorem OROR. Aby wymusić właściwą kolejność i uniknąć błędów logicznych, należy stosować nawiasy okrągłe.

Manipulacja Tekstem, Liczbami i Datami w Zapytaniach SQL
  • Funkcje tekstowe:

    • CONCATCONCAT: Łączy ze sobą dwa lub więcej ciągów tekstowych. Bezpiecznie obsługuje wartości NULLNULL – zamiast unieważniać cały ciąg (jak klasyczny operator ++ lub ∥∣\||), przekształca NULLNULL w pusty tekst.

    • SUBSTRINGSUBSTRING: Wycina fragment tekstu na podstawie wskazanej pozycji początkowej oraz długości wycinka.

    • LEFTLEFT oraz RIGHTRIGHT: Pobierają określoną liczbę znaków odpowiednio od lewej lub prawej strony ciągu tekstowego.

    • UPPERUPPER oraz LOWERLOWER: Konwertują litery w ciągu tekstowym na wielkie lub małe. Służą do standaryzacji danych przed złączeniami lub grupowaniem, wykluczając sytuacje, w których wartości o różnej wielkości liter (np. "Warszawa" i "warszawa") są traktowane jako odrębne encje.

    • TRIMTRIM, LTRIMLTRIM, RTRIMRTRIM: Usuwają zbędne białe znaki (spacje). TRIMTRIM usuwa je z obu stron tekstu, LTRIMLTRIM z lewej, a RTRIMRTRIM z prawej. Są kluczowe w procesach czyszczenia danych (Staging).

  • Funkcje matematyczne:

    • ROUNDROUND: Zaokrągla wartość numeryczną do podanej liczby miejsc po przecinku.

    • CEILCEIL (lub CEILINGCEILING): Zaokrągla liczbę w górę do najbliższej liczby całkowitej.

    • FLOORFLOOR: Zaokrągla liczbę w dół do najbliższej liczby całkowitej.

    • ABSABS: Zwraca wartość bezwzględną liczby.

  • Pobieranie i komponenty dat i czasu:

    • Pobieranie bieżącego czasu: Standard ANSI SQL definiuje CURRENT_DATECURRENT\_DATE oraz CURRENT_TIMESTAMPCURRENT\_TIMESTAMP. System SQL Server wykorzystuje GETDATE()GETDATE(), natomiast MySQL i PostgreSQL korzystają z NOW()NOW().

    • Ekstrakcja składowych daty: Funkcje YEARYEAR, MONTHMONTH oraz DAYDAY wyciągają poszczególne elementy z pól datowych.

    • Stosowanie funkcji bezpośrednio na kolumnach datowych w klauzuli WHERE (np. YEAR(data)=2025\text{YEAR(data)} = 2025) uniemożliwia użycie indeksów B-Tree na tej kolumnie (niszczy właściwość SARGable).

Agregacja Danych, Logika Trójwartościowa i Obsługa Wartości NULL
  • Funkcje agregujące:

    • COUNT(∗)COUNT(*): Zlicza całkowitą liczbę wierszy w tabeli lub grupie, uwzględniając rekordy zawierające wartości NULLNULL we wszystkich kolumnach.

    • COUNT(kolumna)COUNT(kolumna): Zlicza wyłącznie te wiersze, w których podana kolumna zawiera wartość różną od NULLNULL.

    • COUNT(DISTINCT kolumna)COUNT(DISTINCT\ kolumna): Zlicza liczbę unikalnych, niepowtarzalnych i niepustych wartości w danej kolumnie.

    • SUMSUM oraz AVGAVG: SUMSUM oblicza sumę wartości numerycznych, pomijając wartości NULLNULL. AVGAVG oblicza średnią arytmetyczną poprzez podzielenie sumy wartości przez liczbę niepustych rekordów.

    • MINMIN oraz MAXMAX: Odnajdują najmniejszą i największą wartość w kolumnie. Działają na liczbach, tekstach (porządek alfabetyczny) oraz datach.

  • Koncepcja NULL i Logika Trójwartościowa (Three-Valued Logic):

    • NULLNULL oznacza całkowity brak wiedzy lub wartość nieznaną. Nie jest równoważny cyfrze zero (00) ani pustemu ciągowi znaków ("""").

    • Każda operacja arytmetyczna lub porównanie wykonywane na wartości NULLNULL zwraca w wyniku NULLNULL lub wartość logiczną UNKNOWNUNKNOWN. Logika SQL opiera się na trzech wartościach: TRUETRUE, FALSEFALSE oraz UNKNOWNUNKNOWN.

  • Funkcje zastępowania i obsługi NULL:

    • COALESCECOALESCE: Standardowa funkcja ANSI SQL przyjmująca listę argumentów od lewej do prawej. Zwraca pierwszą napotkaną wartość różną od NULLNULL (np. COALESCE(telefon, ’Brak numeru’)\text{COALESCE(telefon, 'Brak numeru')}).

    • ISNULLISNULL: Dialektalna funkcja systemu T-SQL (SQL Server) przyjmująca dokładnie dwa argumenty. Zastępuje NULLNULL drugą wartością oraz rzutuje typ drugiego argumentu na typ pierwszego.

    • NULLIFNULLIF: Porównuje dwa wyrażenia. Jeśli są sobie równe, zwraca NULLNULL; w przeciwnym razie zwraca pierwsze wyrażenie. Stosowana do zapobiegania błędom dzielenia przez zero poprzez zamianę zera w mianowniku na NULL$.\n\n- **Warunkowa logika CASE WHEN**:\n - Instrukcja \text{CASE WHEN … THEN … ELSE … END} działa jak instrukcja warunkowa IF-THEN-ELSE. Pozwala na dynamiczną kategoryzację danych w nowych kolumnach oraz może być osadzana wewnątrz funkcji agregujących do realizowania tzw. agregacji warunkowej (pivotowania danych).\n\n### Złącza Tabel (JOINs) i Operatory Zbiorowe\n\n- **Rodzaje Złączeń (JOINs)**:\n - **INNER JOIN**: Zwraca wyłącznie te wiersze, dla których warunek złączenia jest spełniony jednocześnie w lewej i prawej tabeli. Rekordy bez pary są odrzucane.\n - **LEFT JOIN** (Left Outer Join): Zwraca wszystkie wiersze z lewej tabeli. Jeśli w prawej tabeli istnieje dopasowanie, dane są dołączane; w przeciwnym razie kolumny prawej tabeli są wypełniane wartościami NULL$.

    • RIGHT JOIN (Right Outer Join): Działa odwrotnie do LEFT JOIN – zachowuje wszystkie wiersze z prawej tabeli, dołączając dopasowane dane z lewej lub wartości NULL$.\n - **FULL OUTER JOIN**: Zwraca pełny zbiór wierszy z obu tabel. W miejscach braku dopasowania z dowolnej strony, brakujące pola uzupełniane są wartościami NULL$.

    • CROSS JOIN: Generuje iloczyn kartezjański – łączy każdy wiersz pierwszej tabeli z każdym wierszem drugiej tabeli. Przy tabelach o rozmiarach NN oraz MM wynik liczy N×MN \times M wierszy.

    • Self-Join: Złączenie tabeli z jej własną kopią za pomocą nadania dwóch różnych aliasów w klauzuli FROM. Stosowane do analizy struktur hierarchicznych (np. pracownik i jego przełożony w tej samej tabeli).

  • Operatory Zbiorowe (Pionowe scalanie wyników):

    • UNION: Scalają wyniki dwóch zapytań o identycznej strukturze kolumn. Automatycznie sortuje zbiór i usuwa zduplikowane wiersze, co generuje dodatkowy narzut wydajnościowy.

    • UNION ALL: Scalają wyniki zapytań, zachowując wszystkie wiersze wraz z duplikatami. Nie wykonuje kosztownej operacji deduplikacji i sortowania, dzięki czemu działa znacznie szybciej i jest zalecanym operatorem w skryptach zasilających hurtownie danych.

    • INTERSECT: Zwraca część wspólną dwóch zapytań (wyłącznie wiersze występujące jednocześnie w obu wynikach), automatycznie usuwając duplikaty.

    • EXCEPT (w systemie Oracle pod nazwą MINUS): Zwraca wiersze z pierwszego zapytania, które nie występują w wyniku drugiego zapytania. Wykorzystywany do audytu danych i weryfikacji migracji.

Definiowanie i Modyfikowanie Struktury Danych (DDL, DML, Transakcje)
  • Więzy Integralności (Constraints):

    • PRIMARY KEY (Klucz główny): Jednoznacznie identyfikuje każdy wiersz w tabeli. Żaden ze składników klucza głównego nie może zawierać wartości NULLNULL, a wszystkie wartości muszą być unikalne.

    • FOREIGN KEY (Klucz obcy): Zapewnia spójność relacyjną poprzez wskazanie, że wartość w danej kolumnie musi odpowiadać kluczowi głównemu w innej tabeli. Zapobiega powstawaniu rekordów osieroconych.

    • UNIQUE: Wymusza unikalność wartości w kolumnie spoza klucza głównego. Pozwala na przechowanie jednej wartości NULLNULL (ponieważ NULL≠NULLNULL \neq NULL).

    • CHECK: Waliduje dane na podstawie wyrażenia logicznego podczas zapisu lub edycji (np. wiek>0\text{wiek} > 0). Transakcja naruszająca warunek zostaje odrzucona.

    • DEFAULT: Automatycznie przypisuje domyślną wartość do kolumny w przypadku pominięcia jej w instrukcji INSERT.

  • Komendy DDL (Data Definition Language):

    • CREATE TABLE oraz ALTER TABLE: Tworzą nowe tabele lub modyfikują ich strukturę (dodawanie/zmiana kolumn i więzów) bez utraty istniejących danych.

    • DROP TABLE: Całkowicie i bezpowrotnie usuwa tabelę ze struktury bazy danych wraz z zawartością, indeksami i uprawnieniami.

    • TRUNCATE TABLE: Szybko usuwa wszystkie wiersze z tabeli. W przeciwieństwie do DELETE, nie usuwa rekordów po jednym i nie loguje każdego wiersza w dzienniku transakcyjnym, lecz zwalnia całe strony alokacji danych na dysku.

  • Komendy DML (Data Manipulation Language):

    • INSERT INTO: Wstawia nowe wiersze do tabeli.

    • UPDATE: Modyfikuje wartości w istniejących rekordach na podstawie warunku WHERE.

    • DELETE: Usuwa określone wiersze na podstawie warunku WHERE. Działanie jest logowane wiersz po wierszu w dzienniku transakcyjnym.

  • Transakcje i Zarządzanie Spójnością (ACID):

    • Transakcja to podzbiór operacji DML stanowiący nierozerwalną całość.

    • COMMIT: Trwale zatwierdza wszystkie zmiany dokonane w ramach transakcji na dysku.

    • ROLLBACK: Cofa wszystkie modyfikacje wykonane od początku trwania transakcji w przypadku wystąpienia błędu.

  • Różnica między systemami OLTP a OLAP:

    • Systemy OLTP (Online Transaction Processing): Zoptymalizowane pod kątem szybkiego zapisu, dużej liczby krótkich transakcji, znormalizowanych struktur danych i bieżącej obsługi aplikacji.

    • Systemy OLAP (Online Analytical Processing): Hurtownie danych zoptymalizowane pod kątem masowego odczytu danych historycznych, złożonych agregacji, struktur zdenormalizowanych i wspomagania decyzji biznesowych.

Zaawansowane Funkcje Okna (Window Functions)
  • Składnia i Mechanika Działania:

    • Funkcje okna wykonują obliczenia na zdefiniowanym podzbiorze wierszy (oknie) powiązanym z bieżącym rekordem, nie redukując przy tym liczby wierszy w zwracanym wyniku zapytania.

    • Ogólna składnia ma postać: FUNKCJA() OVER (PARTITION BY … ORDER BY …)\text{FUNKCJA() OVER (PARTITION BY … ORDER BY …)}.

    • Klauzula PARTITION BYPARTITION\ BY dzieli zbiór danych na niezależne grupy logiczne. Klauzula ORDER BYORDER\ BY wymusza sekwencję przetwarzania wierszy wewnątrz każdej partycji.

  • Ramki Okna (Window Frames):

    • Doprecyzowują zakres wierszy w partycji biorących udział w obliczeniach względem wiersza bieżącego.

    • Modyfikator ROWS BETWEENROWS\ BETWEEN operuje na fizycznej liczbie wierszy (np. ROWS BETWEEN 2 PRECEDING AND CURRENT ROW\text{ROWS BETWEEN 2 PRECEDING AND CURRENT ROW}).

    • Modyfikator RANGE BETWEENRANGE\ BETWEEN operuje na zakresach wartości logicznych.

  • Funkcje Numeracji i Rankingu:

    • ROW_NUMBER(): Nadaje unikalną, sekwencyjną numerację całkowitą zaczynającą się od 1 dla każdego wiersza w partycji. W przypadku remisów wartości sortowanych numery są przydzielane losowo/liniowo bez powtórzeń. Stosowana do deduplikacji.

    • RANK(): Przydziela ten sam numer wierszom o identycznych wartościach sortowanych. Kolejny unikalny wiersz otrzymuje numer powiększony o łączną liczbę remisów, co tworzy luki (dziury) w numeracji (sekwencja: 1, 2, 2, 4).

    • DENSE_RANK(): Przydziela ten sam numer przy remisach, ale kolejny unikalny wiersz otrzymuje numer o dokładnie 1 większy. Zachowuje całkowitą ciągłość sekwencji bez luk (sekwencja: 1, 2, 2, 3).

  • Funkcje Przesunięcia (Offset Functions):

    • LAG(): Pobiera wartość z kolumny wiersza oddalonego o NN pozycji w tył względem wiersza bieżącego w ramach tej samej partycji. Pozwala na porównywanie wartości bieżących z okresami poprzednimi bez złączeń zwrotnych.

    • LEAD(): Pobiera wartość z kolumny wiersza oddalonego o NN pozycji w przód względem wiersza bieżącego.

  • Zaawansowane Zastosowania Analityczne:

    • Skumulowana suma (Running Total): Realizowana za pomocą wyrażenia SUM(kolumna) OVER (PARTITION BY grupa ORDER BY data ROWS UNBOUNDED PRECEDING)\text{SUM(kolumna) OVER (PARTITION BY grupa ORDER BY data ROWS UNBOUNDED PRECEDING)}.

    • Ruchoma średnia (Moving Average): Wygładza wahania danych poprzez wyliczenie średniej z określonej ramki czasowej lub liczbowej.

    • Funkcje dystrybucji: NTILE(n)NTILE(n) dzieli partycję na nn równych grup (kubełków), PERCENT_RANK()PERCENT\_RANK() wylicza względną pozycję procentową, a CUME_DIST()CUME\_DIST() zwraca dystrybuantę skumulowaną.

Tymczasowe Zbiory Wyników (CTE) oraz Podzapytania
  • Common Table Expressions (CTE):

    • Zdefiniowane za pomocą klauzuli WITH cte_name AS (...)\text{WITH cte\_name AS (...)}.

    • Tworzą tymczasowy, nazwany zbiór wyników istniejący wyłącznie w pamięci RAM na czas wykonania pojedynczego zapytania. Zastępują głęboko zagnieżdżone podzapytania, podnosząc czytelność kodu SQL.

  • Zagnieżdżone i Wielokrotne CTE:

    • W ramach jednej klauzuli WITH można zdefiniować wiele struktur CTE rozdzielonych przecinkami. Kolejne struktury CTE mogą odwoływać się do wyników wcześniej zdefiniowanych CTE w tym samym zapytaniu, tworząc potoki transformacji danych.

  • Rekurencyjne CTE (Recursive CTE):

    • Składają się z zapytania bazowego (Anchor Member), operatora UNION ALL oraz zapytania rekurencyjnego (Recursive Member) odwołującego się do nazwy CTE, wraz z warunkiem stopu.

    • Służą do przetwarzania struktur hierarchicznych i drzewiastych (np. struktury organizacyjne firm, drzewa kategorii produktów, listy materiałowe BOM).

  • Podzapytania Skorelowane a Nieskorelowane:

    • Podzapytanie skorelowane odwołuje się do kolumn z zapytania zewnętrznego, przez co musi być ewaluowane osobno dla każdego wiersza przetwarzanego przez zapytanie główne, co generuje duże obciążenie przy gigantycznych wolumenach.

  • Porównanie EXISTS / NOT EXISTS vs IN / NOT IN:

    • Operator EXISTSEXISTS sprawdza jedynie fakt istnienia co najmniej jednego pasującego rekordu i przerywa przeszukiwanie po znalezieniu pierwszej zgodności (krótkie spięcie / short-circuit execution).

    • Operator NOT INNOT\ IN zwraca pusty wynik w przypadku obecności wartości NULLNULL w podzapytaniu, podczas gdy NOT EXISTSNOT\ EXISTS prawidłowo obsługuje wartości NULL$.\n\n- **Transpozycja Danych (Pivot / Unpivot)**:\n - Zamiana wierszy na kolumny realizowana jest w klasycznym SQL poprzez agregację warunkową: \text{SUM(CASE WHEN kategoria = 'A' THEN wartosc ELSE 0 END)}.\n\n### Obiekty Programistyczne w Bazach Danych: Procedury, Funkcje i Wyzwalacze\n\n- **Procedury Składowane (Stored Procedures)**:\n - Zamknięte, skompilowane bloki kodu SQL zapisane bezpośrednio w silniku bazy danych. Przyjmują parametry wejściowe (IN)orazzwracająparametrywyjsˊciowe() oraz zwracają parametry wyjściowe (OUT).\n - Mogą wykonywać sekwencje instrukcji DML i DDL, służąc do enkapsulacji logiki biznesowej i automatyzacji procesów ETL.\n - Kontrola błędów i transakcji: Wyposażane w bloki \text{BEGIN TRY … END TRY}orazoraz\text{BEGIN CATCH … END CATCH}, pozwalające na wyłapywanie błędów, rejestrację wpisów logujących oraz bezpieczne wycofywanie zmian za pomocą **ROLLBACK**.\n\n- **Funkcje Użytkownika (User-Defined Functions - UDF)**:\n - Funkcje Skalarne: Zwracają pojedynczą wartość określanego typu.\n - Funkcje Tabelaryczne Inline: Zwracają zbiór wierszy i działają jak sparametryzowane widoki.\n - Funkcje Tabelaryczne Multi-statement: Budują i wypełniają tabelę wewnętrzną w procesie wielokrokowym.\n - Funkcje UDF mogą być wywoływane bezpośrednio wewnątrz klauzuli **SELECT** (w przeciwieństwie do procedur).\n\n- **Wyzwalacze Bazodanowe (Triggers)**:\n - Specjalne procedury wywoływane automatycznie w odpowiedzi na zdarzenia DML (**INSERT**, **UPDATE**, **DELETE**).\n - Wyzwalacze **AFTER** / **FOR**: Uruchamiają się po zakończeniu operacji modyfikacji danych (stosowane m.in. do audytu zmian).\n - Wyzwalacze **INSTEAD OF**: Przechwytują operację bazową i zastępują ją własną logiką (stosowane m.in. przy edycji widoków złożonych).\n\n### Fizyczna Organizacja Danych, Indeksowanie i Optymalizacja Zapytań\n\n- **Architektura Indeksów B-Tree**:\n - Większość relacyjnych silników bazodanowych organizuje indeksy w strukturę B-Drzewa (B-Tree).\n - Składa się z Węzła Głównego (Root Node), Węzłów Pośrednich (Intermediate Nodes) oraz Liści (Leaf Nodes) podzielonych na fizyczne strony pamięci o stałym rozmiarze.\n - Zapewnia złożoność obliczeniową wyszukiwania na poziomie O(\log N).\n\n- **Indeksy Klastrowe a Nieklastrowe**:\n - **Indeks Klastrowy (Clustered Index)**: Fizycznie porządkuje i układa wiersze danych bezpośrednio na dysku twardym według klucza indeksu. Tabela może posiadać maksymalnie JEDEN indeks klastrowy (zakładany domyślnie na kluczu głównym).\n - **Indeks Nieklastrowy (Non-Clustered Index)**: Osobna struktura w B-Tree zawierająca kopie wybranych kolumn oraz adresy fizyczne (wskaźniki) do pełnych wierszy w tabeli głównej. Tabela może posiadać wiele indeksów nieklastrowych.\n\n- **Indeksy Pokrywające (Covering Index / Included Columns)**:\n - Indeks nieklastrowy zawierający w sobie wszystkie kolumny niezbędne do obsłużenia zapytania (kolumny z **SELECT**, **WHERE**, **JOIN**).\n - Eliminują kosztowną operację sięgania do tabeli głównej (tzw. Bookmark Lookup lub Key Lookup).\n\n- **Koncepcja Zapytania SARGable (Search Argument Able)**:\n - Zapytanie jest typu SARGable, jeśli jego warunki filtrujące pozwalają silnikowi na wydajne wykorzystanie indeksu (wykonanie operacji Index Seek).\n - Stosowanie funkcji na kolumnach w klauzuli **WHERE** (np. \text{YEAR(data)} = 2025) niszczy właściwość SARGable, zmuszając silnik do przeliczenia wartości dla każdego wiersza i wykonania pełnego skanowania tabeli (Table Scan).\n\n- **Analiza Planu Wykonania (Execution Plan)**:\n - **Table Scan**: Przeszukanie całej tabeli wiersz po wierszu (najmniej wydajne dla dużych zbiorów).\n - **Index Scan**: Przeszukanie całego indeksu od początku do końca.\n - **Index Seek**: Punktowe, bezpośrednie odnalezienie konkretnych gałęzi w indeksie na podstawie wartości klucza (najbardziej pożądana operacja).\n\n- **Zjawisko Parameter Sniffing**:\n - Sytuacja, w której silnik optymalizuje plan wykonania procedury składowanej na podstawie parametrów przekazanych podczas jej pierwszego wywołania (kompilacji).\n - Jeśli pierwsze wywołanie dotyczyło nietypowego parametru, stworzony plan może okazać się wysoce niewydajny przy kolejnych masowych uruchomieniach procedury.\n\n- **Partycjonowanie Tabel (Table Partitioning)**:\n - Fizyczny podział wielkiej tabeli na mniejsze, niezależne podzbiory na dysku według klucza (np. daty). Umożliwia mechanizm **Partition Elimination** – ignorowanie odczytu partycji niezawartych w warunkach zapytania.\n\n- **Widoki Zmaterializowane (Materialized Views)**:\n - Fizycznie zapisują wynik złożonego zapytania analitycznego na dysku w postaci stałej tabeli. Zapewniają natychmiastowy odczyt w raportach BI, ale wymagają procesów odświeżania (Refresh) przy zmianach w tabelach źródłowych.\n\n### Poziomy Izolacji Transakcji i Anomalie Współbieżności\n\n- **Anomalie Współbieżnego Dostępu do Danych**:\n - **Brudny Odczyt (Dirty Read)**: Transakcja odczytuje dane zmodyfikowane przez inną transakcję, która nie została jeszcze zatwierdzona (**COMMIT**) i może zostać wycofana (**ROLLBACK**).\n - **Niepowtarzalny Odczyt (Non-repeatable Read)**: Transakcja odczytuje ten sam wiersz dwukrotnie, lecz w międzyczasie inna transakcja go zmodyfikowała i zatwierdziła, zwracając inne wartości przy drugim odczycie.\n - **Odczyt Widmowy (Phantom Read)**: Transakcja wykonuje zapytanie zakresowe dwukrotnie, zaś w międzyczasie inna transakcja wstawiła nowe wiersze spełniające ten warunek i zatwierdziła je, generując nowe wiersze-widma.\n\n- **Standardowe Poziomy Izolacji Transakcji (ANSI SQL)**:\n - **Read Uncommitted**: Dopuszcza brudne odczyty. Najszybszy poziom, brak blokad odczytu.\n - **Read Committed**: Eliminuję brudne odczyty. Domyślny poziom w większości systemów.\n - **Repeatable Read**: Eliminuję brudne oraz niepowtarzalne odczyty poprzez blokowanie odczytywanych wierszy do końca transakcji.\n - **Serializable**: Całkowicie izoluje transakcje, eliminując odczyty widmowe. Wymusza szeregowe wykonywanie transakcji, co drastycznie obniża wydajność.\n\n- **Mechanizmy Blokowania i Zakleszczenia (Deadlocks)**:\n - Silnik zakłada blokady Współdzielone (Shared Locks) do odczytu oraz Ekskluzywne (Exclusive Locks) do zapisu.\n - Zakleszczenie (Deadlock) występuje, gdy dwie transakcje wzajemnie zablokują zasoby potrzebne drugiej stronie do kontynuacji pracy.\n - Silnik bazy wykrywa zakleszczenie i automatycznie wyznacza oraz przerywa jedną z transakcji (tzw. Deadlock Victim).\n\n### Modelowanie Wielowymiarowe, Hurtownie Danych i ETL/ELT\n\n- **Schematy Hurtowni Danych**:\n - **Schemat Gwiazdy (Star Schema)**: Składa się z centralnej tabeli faktów oraz otaczających ją płaskich, zdenormalizowanych tabel wymiarów. Upraszcza zapytania SQL i przyspiesza generowanie raportów BI.\n - **Schemat Płatka Śniegu (Snowflake Schema)**: Normalizuje tabele wymiarów, dzieląc je na pod-wymiary. Oszczędza miejsce na dysku, lecz komplikuje zapytania przez konieczność wykonywania wielu złączeń **JOIN**.\n\n- **Klasyfikacja Miar w Tabelach Faktów**:\n - **Miary Addytywne**: Mogą być sumowane wzdłuż wszystkich wymiarów (np. wartość sprzedaży, liczba sztuk).\n - **Miary Póładdytywne**: Mogą być sumowane wzdłuż większości wymiarów, z wyjątkiem wymiaru czasu (np. stan magazynowy, saldo konta).\n - **Miary Nieaddytywne**: Nie podlegają bezpośredniemu sumowaniu (np. marża procentowa, wskaźniki podziału). Wymagają przeliczenia na poziomie zagregowanym.\n\n- **Koncepcja Ziarnistości (Granularity)**:\n - Określa poziom szczegółowości pojedynczego wiersza w tabeli faktów (np. pojedynczy paragon, linia faktury, czy dzienny podsumowany obrót). Wyznaczenie ziarnistości jest pierwszym i najważniejszym krokiem w projektowaniu modelu wielowymiarowego.\n\n- **Specjalne Typy Tabel Faktów i Wymiarów**:\n - **Tabela Faktów Bez Miar (Factless Fact Table)**: Przechowuje wyłącznie zestaw kluczy obcych do wymiarów bez miar numerycznych. Służy do rejestrowania faktu zaistnienia zdarzenia (np. obecność pracownika, logowanie do systemu).\n - **Wymiar Śmieciowy (Junk Dimension)**: Łączy w jedną tabelę słownikową wiele luźnych, niskokardynalnych flag, kodów i atrybutów tak/nie.\n - **Wymiar Zdegenerowany (Degenerated Dimension)**: Identyfikator dokumentu źródłowego (np. numer faktury) przechowywany bezpośrednio w tabeli faktów bez tworzenia dla niego osobnej tabeli wymiarowej.\n - **Wymiary Wielorolowe (Role-playing Dimensions)**: Ta sama fizyczna tabela wymiaru (np. kalendarz) dołączana wielokrotnie do tabeli faktów pod różnymi aliasami (np. data zamówienia, data wysyłki, data płatności).\n\n- **Slowly Changing Dimensions (SCD) – Wymiary Wolnozmienne**:\n - **SCD Typ 0**: Brak zmian (dane stałe).\n - **SCD Typ 1**: Nadpisanie starej wartości nową (brak historii zmian).\n - **SCD Typ 2**: Wersjonowanie – dodanie nowego wiersza z unikalnym kluczem zastępczym oraz datami ważności (\text{DataFrom},,\text{DataTo}) i flagą aktualności.\n - **SCD Typ 3**: Dodanie nowej kolumny do wiersza przechowującej poprzednią wartość atrybutu.\n - **SCD Typ 4**: Wydzielenie historii zmian do osobnej tabeli historycznej (Mini-Dimension).\n - **SCD Typ 6**: Hybryda łącząca techniki Typu 1, Typu 2 oraz Typu 3 (1 + 2 + 3 = 6$$).

  • Klucze Zastępcze (Surrogate Keys) a Klucze Biznesowe:

    • Klucz Biznesowy (Naturalny): Identyfikator ze świata rzeczywistego (np. PESEL, NIP, SKU).

    • Klucz Zastępczy (Surrogate Key): Sztucznie wygenerowany po stronie hurtowni danych unikalny identyfikator całkowity (Integer). Izoluje hurtownię danych od zmian w systemach źródłowych i umożliwia pełną obsługę SCD Typu 2.

  • Architektura Procesów ETL vs ELT:

    • ETL (Extract, Transform, Load): Dane są pobierane, transformowane na zewnętrznym serwerze transformacyjnym i ładowane do bazy docelowej.

    • ELT (Extract, Load, Transform): Dane są pobierane i ładowane w surowej postaci wprost do chmurowej hurtowni danych (np. Snowflake, BigQuery), a cała transformacja wykonywana jest wewnątrz hurtowni z wykorzystaniem jej mocy obliczeniowej.

  • Architektura Medalowa (Medallion Architecture):

    • Warstwa Bronze: Surowe dane ładowane 1:1 ze źródeł (Staging).

    • Warstwa Silver: Dane wyczyszczone, znormalizowane i ustrukturyzowane w model hurtowni.

    • Warstwa Gold: Zbudowane gotowe modele wysoce zagregowane i Data Marts dedykowane pod raportowanie BI.

  • Dokumentacja Source-to-Target Mapping (STTM):

    • Specyfikacja techniczna tworzona przez analityka, precyzyjnie opisująca zmapowanie pól ze struktur źródłowych do tabel docelowych hurtowni wraz z dokładnymi regułami transformacji biznesowej.

  • Mechanizmy CDC (Change Data Capture) i Ładowanie Przyrostowe:

    • Śledzenie zmian bezpośrednio w dziennikach transakcyjnych systemów źródłowych. Pozwala na realizację ładowania przyrostowego (Incremental Load), wyciągającego wyłącznie nowe lub zmodyfikowane rekordy od ostatniego zasilenia.