Czyszczenie i transformacja danych w T-SQL – data wrangling w praktyce

Praktyczny przewodnik po data wrangling w T-SQL: czyszczenie brudnych danych, usuwanie duplikatów, standaryzacja tekstu, walidacja wartości, mapowanie słowników oraz pivot/unpivot na konkretnych przykładach.
09 maja 2026
blog

Wprowadzenie do data wrangling w T-SQL: czym są „brudne dane” i cele oczyszczania

Data wrangling to praktyczny proces porządkowania, poprawiania i ujednolicania danych tak, aby nadawały się do analiz, raportowania oraz dalszego przetwarzania. W środowisku baz danych rolę tę bardzo często realizuje się bezpośrednio w T-SQL, ponieważ to właśnie tam dane są przechowywane, filtrowane i łączone. Dzięki temu można wykrywać problemy jakościowe już na poziomie źródła, zamiast przenosić je do kolejnych etapów pracy.

Określenie „brudne dane” odnosi się do danych, które są niepełne, niespójne, błędne albo zapisane w różnych formatach. Nie zawsze oznacza to dane całkowicie bezużyteczne. Często są one po prostu trudne do jednoznacznej interpretacji: ten sam typ informacji może być zapisany na kilka sposobów, część wartości może być pusta, a niektóre rekordy mogą zawierać literówki, nadmiarowe spacje lub niepoprawne formaty. W praktyce takie problemy prowadzą do błędnych wyników raportów, trudności przy łączeniu tabel i niepewnych wniosków biznesowych.

W bazach danych najczęściej spotyka się kilka podstawowych kategorii problemów jakościowych:

  • braki danych – pola puste, wartości nieznane lub zastąpione umownymi znacznikami,
  • niespójny zapis – ta sama informacja zapisana różnie, na przykład z odmienną wielkością liter, odstępami lub skrótami,
  • duplikaty – powielone rekordy opisujące ten sam obiekt lub zdarzenie,
  • błędy formatów – wartości tekstowe tam, gdzie oczekiwany jest numer, data albo kod,
  • wartości niepoprawne logicznie – dane mieszczące się formalnie w typie, ale niezgodne z regułami jakości,
  • niejednolite kody i słowniki – różne oznaczenia tej samej kategorii.

Właśnie dlatego oczyszczanie danych nie polega wyłącznie na „poprawianiu błędów”. Jego celem jest także nadanie danym spójnej postaci, tak aby można było je bezpiecznie porównywać, agregować i wykorzystywać w zapytaniach. Dobrze przygotowany zbiór danych zmniejsza ryzyko pomyłek analitycznych, upraszcza logikę raportów i pozwala budować bardziej przewidywalne procesy przetwarzania.

T-SQL jest do tego szczególnie przydatny, ponieważ umożliwia pracę bezpośrednio na rekordach w relacyjnej bazie danych. Z jednej strony pozwala identyfikować odstępstwa od oczekiwanego wzorca, a z drugiej — wykonywać masowe operacje transformacji w kontrolowany sposób. To odróżnia oczyszczanie danych w bazie od ręcznych poprawek w arkuszu kalkulacyjnym: działania są powtarzalne, możliwe do zautomatyzowania i łatwiejsze do audytu.

W praktyce cele data wranglingu w T-SQL można streścić do kilku kluczowych punktów:

  • zwiększenie wiarygodności danych używanych w analizach i raportach,
  • ujednolicenie sposobu zapisu, aby te same wartości były rozpoznawane jako równoważne,
  • eliminacja lub ograniczenie niejednoznaczności w polach tekstowych i identyfikatorach,
  • przygotowanie danych do łączenia z innymi tabelami i źródłami,
  • ułatwienie walidacji oraz kontroli jakości w codziennej pracy,
  • budowanie powtarzalnych procedur, które można uruchamiać wielokrotnie dla nowych danych.

Warto też odróżnić dwa pojęcia, które bywają używane zamiennie. Czyszczenie danych koncentruje się głównie na wykrywaniu i korygowaniu problemów jakościowych, natomiast transformacja danych obejmuje szerszy zakres zmian prowadzących do uzyskania formy wygodnej do dalszego użycia. W praktyce te działania zwykle się przenikają: trudno ujednolicić dane bez wcześniejszego wykrycia błędów, a samo usunięcie błędów często nie wystarcza, jeśli dane nadal są zapisane w niepraktyczny sposób.

Dobrze przeprowadzony data wrangling nie powinien być przypadkowym zestawem poprawek. To raczej świadome zastosowanie reguł jakości, które odpowiadają na konkretne problemy występujące w zbiorze. Tylko wtedy dane stają się nie tylko „czystsze”, ale przede wszystkim bardziej użyteczne i przewidywalne w dalszej pracy z T-SQL.

Przygotowanie przykładowego zbioru: tworzenie tabeli i wstawienie danych z typowymi błędami

Aby sensownie pokazać data wrangling w T-SQL, warto zacząć od małego, kontrolowanego zbioru danych, który celowo zawiera problemy spotykane w codziennej pracy. Taki zbiór nie powinien być idealny — przeciwnie, jego zadaniem jest odwzorowanie sytuacji, w których dane pochodzą z różnych formularzy, importów CSV, ręcznego wprowadzania lub niespójnych systemów źródłowych.

Podczas szkoleń Cognity ten temat wraca regularnie, dlatego zdecydowaliśmy się omówić go również tutaj. Właśnie na etapie budowania przykładowej tabeli najlepiej widać, z jakimi nieprawidłowościami pracuje się później w zapytaniach oczyszczających i transformujących dane.

Na etapie przygotowania danych testowych najważniejsze jest, aby w tabeli znalazły się kolumny reprezentujące kilka podstawowych typów informacji: identyfikator rekordu, dane tekstowe, wartości przypominające liczby, daty oraz pola opcjonalne. Dzięki temu można później przećwiczyć zarówno oczyszczanie prostych błędów formatowania, jak i wykrywanie problemów związanych z niepełnymi lub niejednoznacznymi wartościami.

Przykładowy zbiór powinien zawierać przede wszystkim typowe błędy jakości danych, takie jak:

  • zbędne spacje na początku, końcu lub wewnątrz tekstu,
  • różne warianty zapisu tej samej wartości,
  • niespójne użycie wielkich i małych liter,
  • brakujące dane zapisane jako puste ciągi zamiast wartości NULL,
  • wartości wpisane w niewłaściwym formacie,
  • duplikaty lub rekordy bardzo do siebie podobne,
  • pola łączące kilka informacji w jednym tekście.

W praktyce dobrze jest przygotować tabelę możliwie prostą, ale wystarczająco zróżnicowaną. Nie chodzi o rozbudowany model relacyjny, lecz o wygodny materiał roboczy do demonstracji. Tabela testowa powinna pozwalać zauważyć różnicę między danymi surowymi a danymi gotowymi do analizy. Surowy zbiór zwykle odzwierciedla stan po imporcie, natomiast zbiór po oczyszczeniu ma być spójny, czytelny i przewidywalny w dalszych operacjach.

Warto też pamiętać, że nie każdy błąd jest błędem technicznym. Część problemów wynika z braku standardu zapisu. Dwie wartości mogą oznaczać dokładnie to samo, ale różnić się wyglądem. Inne przypadki są poważniejsze — rekord wygląda poprawnie, lecz nie nadaje się do bezpiecznego przetwarzania bez dodatkowej walidacji. Już na etapie tworzenia przykładowego zbioru dobrze jest uwzględnić oba typy sytuacji.

Przygotowanie danych demonstracyjnych ma jeszcze jedną zaletę: pozwala od razu rozdzielić problemy według kategorii. Jedne kolumny będą służyły do pracy z duplikatami, inne do standaryzacji tekstu, jeszcze inne do sprawdzania poprawności konwersji i uzupełniania braków. Dzięki temu dalsze operacje nie są wykonywane na abstrakcyjnych przykładach, lecz na zestawie, który przypomina realne dane operacyjne.

Najlepszy zbiór do ćwiczeń to taki, który jest mały, ale zawiera dużą różnorodność nieprawidłowości. Pozwala to szybko testować zapytania, porównywać wyniki przed i po zmianach oraz jasno pokazać, że data wrangling w T-SQL nie polega wyłącznie na „czyszczeniu tekstu”, ale na systematycznym przygotowaniu danych do dalszego użycia w raportowaniu, integracji i analizie.

Usuwanie duplikatów i wybór rekordu kanonicznego (ROW_NUMBER, CTE, DELETE/SELECT)

Duplikaty to jeden z najczęstszych problemów w procesie oczyszczania danych. Nie zawsze oznaczają one rekordy identyczne w każdym polu. W praktyce częściej spotyka się duplikaty logiczne, czyli wiersze opisujące ten sam obiekt, ale zapisane z drobnymi różnicami: inną pisownią, brakującą wartością, odmiennym formatem lub inną datą aktualizacji.

W T-SQL usuwanie duplikatów zwykle sprowadza się do dwóch kroków:

  • wykrycia grup rekordów, które należy uznać za duplikaty,
  • wyboru rekordu kanonicznego, czyli tego jednego wiersza, który zostaje zachowany.

To drugie jest szczególnie ważne, ponieważ samo usunięcie nadmiarowych wierszy bez jasnej reguły może prowadzić do utraty bardziej kompletnej lub nowszej wersji danych.

Co oznacza rekord kanoniczny

Rekord kanoniczny to preferowana reprezentacja danej encji w zbiorze. Jest to wiersz wybrany według określonej reguły biznesowej lub technicznej, na przykład:

  • najświeższy według daty modyfikacji,
  • najbardziej kompletny,
  • posiadający poprawny identyfikator,
  • najstarszy, jeśli traktujemy pierwszy zapis jako źródłowy.

Bez zdefiniowania takiej zasady deduplikacja staje się przypadkowa. Dlatego przed użyciem DELETE warto najpierw wykonać analizę w trybie SELECT i sprawdzić, które rekordy zostaną oznaczone do usunięcia.

Najczęstsze podejście: ROW_NUMBER()

Jednym z najpraktyczniejszych narzędzi do deduplikacji w T-SQL jest funkcja okna ROW_NUMBER(). Pozwala ona ponumerować rekordy wewnątrz każdej grupy duplikatów. Dzięki temu można łatwo odróżnić wiersz, który ma zostać zachowany, od tych przeznaczonych do usunięcia.

Typowy schemat wygląda tak:

  • PARTITION BY określa, które kolumny definiują grupę potencjalnych duplikatów,
  • ORDER BY ustala kolejność w grupie i tym samym wybiera rekord kanoniczny,
  • wiersz z numerem 1 zostaje, a rekordy z numerem większym niż 1 są nadmiarowe.
WITH Duplikaty AS (
    SELECT
        *,
        ROW_NUMBER() OVER (
            PARTITION BY Email
            ORDER BY DataModyfikacji DESC, Id DESC
        ) AS rn
    FROM dbo.Kontakty
)
SELECT *
FROM Duplikaty
WHERE rn > 1;

W tym przykładzie duplikaty są grupowane według pola Email, a rekord kanoniczny to najnowszy wpis. Najpierw używany jest SELECT, aby bezpiecznie zobaczyć wynik działania reguły.

Dlaczego CTE jest wygodne

CTE, czyli Common Table Expression, nie usuwa duplikatów samo w sobie, ale bardzo ułatwia zapis i czytelność zapytania. Dzięki niemu można najpierw zbudować logiczny zestaw danych z nadanym numerem wiersza, a dopiero potem wykonać na nim filtrację, podgląd albo usunięcie.

Największe zalety CTE w takim scenariuszu to:

  • czytelne rozdzielenie logiki identyfikacji duplikatów od operacji końcowej,
  • łatwe przełączanie między SELECT i DELETE,
  • mniejsze ryzyko pomyłki podczas testowania reguł deduplikacji.

SELECT przed DELETE

W praktyce dobrą zasadą jest rozpoczęcie od zapytania diagnostycznego. Najpierw warto sprawdzić:

  • jak wiele grup duplikatów występuje,
  • jakie rekordy zostaną oznaczone jako kanoniczne,
  • czy reguła ORDER BY rzeczywiście wybiera właściwy wiersz.

Dopiero po weryfikacji można przejść do usuwania.

WITH Duplikaty AS (
    SELECT
        *,
        ROW_NUMBER() OVER (
            PARTITION BY Email
            ORDER BY DataModyfikacji DESC, Id DESC
        ) AS rn
    FROM dbo.Kontakty
)
DELETE FROM Duplikaty
WHERE rn > 1;

Taki zapis jest zwięzły i bardzo często spotykany w codziennej pracy z danymi operacyjnymi oraz stagingowymi.

Jak wybrać właściwe kryterium duplikatu

Kluczowe znaczenie ma poprawne określenie kolumn w PARTITION BY. Jeśli wybór będzie zbyt wąski, można połączyć różne byty w jedną grupę. Jeśli będzie zbyt szeroki, rzeczywiste duplikaty nie zostaną wykryte.

Najczęściej stosowane są trzy warianty:

PodejścieNa czym polegaTypowe zastosowanie
Duplikat pełnyPorównanie wielu kolumn jednocześnieGdy rekordy powinny być niemal identyczne
Duplikat po kluczu biznesowymGrupowanie po polu takim jak e-mail, numer dokumentu lub kodGdy różne wersje opisują ten sam obiekt
Duplikat warunkowyGrupowanie po zestawie kolumn zależnym od reguły biznesowejGdy nie istnieje jeden naturalny identyfikator

Wybór rekordu kanonicznego powinien być równie świadomy jak wybór definicji duplikatu. Sama funkcja ROW_NUMBER() jest tylko mechanizmem technicznym — o wyniku decyduje logika zawarta w ORDER BY.

Najważniejsze różnice między podejściami

  • ROW_NUMBER() najlepiej sprawdza się wtedy, gdy trzeba zachować dokładnie jeden rekord z każdej grupy.
  • CTE poprawia czytelność i bezpieczeństwo pracy, szczególnie podczas testów i etapowego budowania zapytania.
  • SELECT służy do walidacji wyniku i powinien poprzedzać operację usuwania.
  • DELETE to końcowy krok, który warto wykonywać dopiero po potwierdzeniu reguł deduplikacji.

W praktyce te elementy nie konkurują ze sobą, lecz tworzą wspólny wzorzec pracy: najpierw identyfikacja i ranking rekordów, potem kontrola wyniku, a na końcu usunięcie nadmiarowych wierszy.

Na co uważać przy deduplikacji

  • Usunięcie rekordu starszego nie zawsze jest poprawne — czasem to on zawiera pełniejsze dane.
  • Duplikaty mogą wynikać z błędów formatu, a nie z rzeczywistego powielenia danych.
  • W tabelach powiązanych relacjami usunięcie rekordu może wymagać wcześniejszego przeadresowania kluczy obcych.
  • Ta sama reguła deduplikacji nie musi być poprawna dla całego zbioru.

Z tego powodu deduplikacja w T-SQL nie polega wyłącznie na znalezieniu powtarzających się wartości. To przede wszystkim kontrolowany proces wyboru tej wersji danych, która ma pozostać jako reprezentacja kanoniczna.

💡 Pro tip: Zanim uruchomisz DELETE, zawsze wykonaj tę samą logikę w SELECT i sprawdź, czy ORDER BY w ROW_NUMBER() naprawdę wskazuje rekord kanoniczny, który chcesz zachować. W deduplikacji największe ryzyko nie polega na znalezieniu duplikatu, ale na usunięciu niewłaściwej wersji danych.

Standaryzacja tekstu: TRIM, UPPER/LOWER, usuwanie nadmiarowych spacji i normalizacja formatów

Jednym z najczęstszych problemów w pracy z danymi tekstowymi są różnice w zapisie, które nie zmieniają znaczenia biznesowego, ale utrudniają filtrowanie, porównywanie i grupowanie rekordów. W praktyce te same wartości mogą występować z dodatkowymi spacjami, w różnych wariantach wielkości liter albo w niespójnym formacie. Standaryzacja tekstu w T-SQL polega na sprowadzeniu takich danych do jednolitej postaci.

Typowe przykłady to wartości takie jak " warszawa", "Warszawa ", "WARSZAWA" czy "warszawa". Dla użytkownika oznaczają to samo, ale dla bazy danych mogą być traktowane jako różne ciągi znaków, zależnie od kolacji, reguł porównań i sposobu użycia danych w zapytaniach. Dlatego standaryzacja jest często jednym z pierwszych etapów oczyszczania danych tekstowych. Doświadczenie Cognity pokazuje, że rozwiązanie tego problemu przynosi szybkie i zauważalne efekty w codziennej pracy.

Najczęstsze cele standaryzacji tekstu

  • usunięcie zbędnych spacji z początku i końca wartości,
  • ograniczenie wielokrotnych spacji wewnątrz tekstu,
  • ujednolicenie wielkości liter dla łatwiejszego porównywania,
  • normalizacja prostych formatów zapisu, na przykład kodów, skrótów lub identyfikatorów,
  • przygotowanie danych do dalszych operacji analitycznych i walidacyjnych.

TRIM, LTRIM i RTRIM

Podstawowym krokiem jest usunięcie spacji z początku i końca pola tekstowego. W tym celu najwygodniej użyć funkcji TRIM. Jej działanie jest prostsze i bardziej czytelne niż łączenie starszych funkcji LTRIM i RTRIM.

FunkcjaZastosowanieKiedy używać
TRIM()Usuwa spacje z początku i końca tekstuNajczęściej, gdy chcemy szybko oczyścić wartość brzegową
LTRIM()Usuwa spacje tylko z lewej stronyGdy zależy nam wyłącznie na początku tekstu
RTRIM()Usuwa spacje tylko z prawej stronyGdy problem dotyczy końca tekstu
SELECT 
    OriginalValue,
    TRIM(OriginalValue) AS CleanValue
FROM dbo.PrzykladoweDane;

To prosta operacja, ale bardzo ważna. Nawet pojedyncza spacja na końcu pola może powodować problemy przy porównywaniu wartości tekstowych, budowaniu raportów lub łączeniu danych z różnych źródeł.

UPPER i LOWER

Kolejnym częstym zabiegiem jest ujednolicenie wielkości liter. W T-SQL służą do tego funkcje UPPER i LOWER. Wybór jednej z nich zależy głównie od przyjętej konwencji:

  • UPPER() sprawdza się przy kodach, skrótach i identyfikatorach,
  • LOWER() bywa używane przy adresach e-mail, kluczach tekstowych i danych technicznych,
  • w niektórych przypadkach pozostawia się zapis mieszany, ale wcześniej usuwa się spacje i inne niepożądane różnice.
SELECT 
    TRIM(Miasto) AS MiastoPoTrim,
    UPPER(TRIM(Miasto)) AS MiastoUpper,
    LOWER(TRIM(Email)) AS EmailLower
FROM dbo.PrzykladoweDane;

Najważniejsze jest tu zachowanie spójności. Jeśli jedna kolumna ma być używana do wyszukiwania lub porównań, warto przyjąć jeden standard zapisu i stosować go konsekwentnie.

Usuwanie nadmiarowych spacji wewnątrz tekstu

TRIM rozwiązuje problem spacji na brzegach, ale nie usuwa wielokrotnych spacji wewnątrz wartości. To częsty przypadek w danych wprowadzanych ręcznie, na przykład "ul. Marszałkowska 10" albo "kod klienta". Taki zapis może utrudniać prezentację danych i tworzyć pozornie różne wartości.

Do prostego ograniczania powtarzających się spacji można użyć REPLACE. W praktyce często stosuje się wielokrotne wywołanie tej funkcji, jeśli chcemy zamienić podwójne spacje na pojedyncze.

SELECT 
    REPLACE(REPLACE(REPLACE(TRIM(Adres), '  ', ' '), '  ', ' '), '  ', ' ') AS AdresClean
FROM dbo.PrzykladoweDane;

Nie jest to rozwiązanie idealne dla każdego przypadku, ale dobrze sprawdza się przy podstawowym porządkowaniu tekstu. Pozwala szybko poprawić czytelność i ograniczyć liczbę wariantów tej samej wartości.

Normalizacja prostych formatów

Standaryzacja tekstu obejmuje też ujednolicanie prostych formatów zapisu. Chodzi nie tyle o interpretację znaczenia danych, ile o nadanie im wspólnej formy. Przykładowo:

  • kody mogą być zapisywane zawsze wielkimi literami,
  • ciągi znaków mogą mieć usunięte zbędne spacje wokół separatorów,
  • wartości tekstowe mogą być przechowywane bez przypadkowych znaków specjalnych lub nieregularnych odstępów.

W takich sytuacjach najczęściej łączy się kilka prostych funkcji, na przykład TRIM, UPPER, LOWER i REPLACE. Kluczowe jest to, aby wynik był przewidywalny i zgodny z ustalonym standardem.

SELECT 
    UPPER(REPLACE(TRIM(Kod), ' ', '')) AS KodStandard
FROM dbo.PrzykladoweDane;

Taki zapis może być użyteczny tam, gdzie kod nie powinien zawierać spacji i ma być zawsze prezentowany w jednej postaci.

Dobra praktyka: standaryzacja przed porównaniem danych

W wielu przypadkach najlepiej nie porównywać surowych wartości, lecz najpierw je wystandaryzować. Dzięki temu można ograniczyć błędy wynikające z drobnych różnic w zapisie. Dotyczy to szczególnie pól takich jak miasto, ulica, kod, adres e-mail czy nazwa jednostki organizacyjnej.

Przykładowe podejście:

SELECT *
FROM dbo.PrzykladoweDane
WHERE UPPER(TRIM(Miasto)) = 'WARSZAWA';

Taki warunek jest bardziej odporny na niejednolity zapis niż bezpośrednie porównanie surowej wartości z tabeli.

Na co uważać

  • Nie każda zmiana wielkości liter jest neutralna — w części systemów oryginalna forma może mieć znaczenie prezentacyjne.
  • Usuwanie spacji nie zawsze powinno być pełne — w niektórych polach odstępy są elementem poprawnego zapisu.
  • Warto rozróżnić pole do prezentacji i pole techniczne — jedno może zachowywać oryginalny zapis, a drugie wersję oczyszczoną do analizy.
  • Standaryzacja powinna być konsekwentna — najlepiej stosować te same reguły dla całej kolumny lub grupy podobnych pól.

Podstawowe funkcje tekstowe T-SQL pozwalają szybko uporządkować dane i usunąć najbardziej typowe niespójności. Nawet proste operacje, takie jak TRIM, UPPER, LOWER i REPLACE, znacząco poprawiają jakość danych oraz ułatwiają ich dalsze wykorzystanie w zapytaniach, raportach i procesach integracyjnych.

Parsowanie i ekstrakcja informacji z pól tekstowych: SUBSTRING, CHARINDEX, PATINDEX (krok po kroku)

W praktyce data wrangling bardzo często spotyka się kolumny, które przechowują kilka informacji naraz: kod i opis w jednym polu, identyfikator ukryty w komentarzu, fragment adresu osadzony w dłuższym ciągu albo numer dokumentu zapisany razem z dodatkowym tekstem. W takich sytuacjach potrzebne jest parsowanie, czyli wydzielanie konkretnych elementów z tekstu, oraz ekstrakcja, czyli pobieranie tylko tej części danych, która jest dalej użyteczna.

W T-SQL trzy bardzo przydatne funkcje do takich zadań to SUBSTRING, CHARINDEX oraz PATINDEX. Każda z nich rozwiązuje trochę inny problem:

FunkcjaDo czego służyTypowe zastosowanie
SUBSTRINGWycięcie fragmentu tekstu od wskazanej pozycjiPobranie kodu, prefiksu, części numeru
CHARINDEXZnalezienie pozycji konkretnego fragmentu tekstuWyszukanie separatora, np. myślnika, dwukropka, znaku @
PATINDEXZnalezienie pozycji wzorcaWykrywanie cyfr, liter lub nieregularnych układów znaków

Najprościej myśleć o nich tak: CHARINDEX znajduje stały tekst, PATINDEX znajduje tekst pasujący do wzorca, a SUBSTRING wycina wskazany fragment.

Krok 1: zlokalizowanie miejsca, od którego zaczyna się interesujący fragment

Najczęstszy scenariusz wygląda tak: najpierw trzeba ustalić, gdzie w polu tekstowym znajduje się separator albo charakterystyczny znak, a dopiero później wyciąć część danych. Do wskazania pozycji dobrze nadaje się CHARINDEX.

Przykładowo, jeśli w kolumnie znajduje się zapis w rodzaju KOD:ABC123, można najpierw znaleźć dwukropek, a potem pobrać tekst po nim.

SELECT 
    CHARINDEX(':', 'KOD:ABC123') AS PozycjaDwukropka;

Jeżeli wynik to 4, oznacza to, że separator został znaleziony na czwartej pozycji. Tę informację można od razu wykorzystać przy wycinaniu fragmentu.

Krok 2: wycięcie odpowiedniego fragmentu za pomocą SUBSTRING

Funkcja SUBSTRING przyjmuje trzy argumenty: tekst źródłowy, pozycję początkową oraz długość fragmentu. Jest użyteczna wtedy, gdy wiadomo już, od którego miejsca należy zacząć odczyt.

SELECT 
    SUBSTRING('KOD:ABC123', 5, 6) AS WyodrebnionyKod;

Wynik to ABC123. W prostych przypadkach długość można podać ręcznie, ale w praktyce często wyznacza się ją dynamicznie, na podstawie położenia separatorów.

Połączenie CHARINDEX + SUBSTRING jest jednym z najczęstszych wzorców pracy z tekstem w T-SQL.

SELECT 
    SUBSTRING('KOD:ABC123', CHARINDEX(':', 'KOD:ABC123') + 1, 6) AS Kod;

Taki zapis sprawdza się zwłaszcza wtedy, gdy początek właściwej informacji zależy od położenia znaku rozdzielającego.

Krok 3: odczyt danych znajdujących się między dwoma separatorami

Wiele pól tekstowych zawiera dane rozdzielone więcej niż jednym znakiem, na przykład PL-001-WARSAW. W takim przypadku trzeba znaleźć zarówno początek, jak i koniec poszukiwanego fragmentu.

Jeśli celem jest wyciągnięcie środkowego elementu, logika wygląda zwykle tak:

  • znajdź pozycję pierwszego separatora,
  • znajdź pozycję drugiego separatora,
  • wytnij tekst pomiędzy nimi.
SELECT 
    SUBSTRING(
        'PL-001-WARSAW',
        CHARINDEX('-', 'PL-001-WARSAW') + 1,
        CHARINDEX('-', 'PL-001-WARSAW', CHARINDEX('-', 'PL-001-WARSAW') + 1) 
            - CHARINDEX('-', 'PL-001-WARSAW') - 1
    ) AS SrodkowyFragment;

To podejście jest przydatne wszędzie tam, gdzie dane mają częściowo uporządkowany format, ale nie są rozbite na osobne kolumny.

Krok 4: kiedy CHARINDEX nie wystarcza i warto użyć PATINDEX

CHARINDEX działa dobrze, gdy wiadomo dokładnie, jakiego ciągu znaków szukać. Problem pojawia się wtedy, gdy nie chodzi o konkretny tekst, lecz o pewien typ znaku, na przykład pierwszą cyfrę, pierwszą literę po prefiksie albo miejsce wystąpienia niestandardowego układu znaków. Wtedy lepiej sprawdza się PATINDEX.

Funkcja ta pozwala szukać według wzorca. To przydatne na przykład wtedy, gdy numer zaczyna się w różnym miejscu, ale zawsze rozpoczyna się od cyfry.

SELECT 
    PATINDEX('%[0-9]%', 'ID=ABC789') AS PozycjaPierwszejCyfry;

Jeżeli wynik to 7, oznacza to, że od siódmego znaku zaczyna się fragment liczbowy. Tę pozycję można następnie przekazać do SUBSTRING.

SELECT 
    SUBSTRING('ID=ABC789', PATINDEX('%[0-9]%', 'ID=ABC789'), 3) AS Numer;

W rezultacie otrzymuje się 789. To prosty, ale bardzo praktyczny schemat: najpierw znajdź początek wzorca, potem wytnij potrzebny fragment.

Krok 5: wykorzystanie wzorców do wykrywania fragmentów o nieregularnej strukturze

PATINDEX jest szczególnie użyteczny, gdy dane nie są zapisane całkowicie jednolicie. Przykładowo, w jednym wierszu kod może zaczynać się od liter, a w innym od cyfr; czasem występują dodatkowe znaki, a czasem nie. Szukanie dosłownego separatora bywa wtedy niewystarczające.

Najczęstsze przypadki użycia wzorców to:

  • wyszukiwanie pierwszej cyfry: %[0-9]%,
  • wyszukiwanie pierwszej litery: %[A-Za-z]%,
  • wyszukiwanie znaku spoza oczekiwanego zakresu,
  • wstępne wykrywanie pól odstających od typowego formatu.

Dzięki temu można nie tylko wycinać dane, ale też szybciej zorientować się, czy tekst ma strukturę pozwalającą na dalsze przetwarzanie.

Typowy schemat pracy krok po kroku

Przy parsowaniu pól tekstowych dobrze sprawdza się prosty, powtarzalny proces:

  1. Sprawdź strukturę tekstu — ustal, czy dane mają separator, stały prefiks albo rozpoznawalny wzorzec.
  2. Znajdź pozycję początku — użyj CHARINDEX dla stałego fragmentu lub PATINDEX dla wzorca.
  3. Ustal koniec fragmentu — przez drugi separator, długość tekstu albo kolejne dopasowanie.
  4. Wytnij dane — zastosuj SUBSTRING.
  5. Zweryfikuj wynik — upewnij się, że brak separatora lub brak dopasowania nie powoduje błędnej ekstrakcji.

Taki układ jest bezpieczniejszy niż próba napisania jednego złożonego wyrażenia bez wcześniejszego sprawdzenia, gdzie naprawdę znajduje się poszukiwany fragment.

Na co uważać przy ekstrakcji danych tekstowych

  • Brak dopasowania — jeśli separator albo wzorzec nie występuje, wynik pozycji może być równy 0, co wymaga ostrożności.
  • Niejednolita długość danych — wycinanie „na sztywno” działa tylko wtedy, gdy format jest rzeczywiście stały.
  • Wiele separatorów — trzeba jasno określić, czy chodzi o pierwsze, ostatnie czy kolejne wystąpienie znaku.
  • Dane z dodatkowymi znakami — nawiasy, spacje, prefiksy lub sufiksy mogą przesuwać pozycję właściwego fragmentu.

Najważniejsze jest to, by traktować parsowanie nie jako pojedynczą funkcję, ale jako kombinację kilku prostych operacji. W T-SQL zwykle najpierw lokalizuje się punkt zaczepienia, potem oblicza zakres, a na końcu wycina właściwy fragment. Właśnie dlatego trio CHARINDEX, PATINDEX i SUBSTRING stanowi podstawowy zestaw narzędzi do pracy z tekstem podczas oczyszczania danych.

Walidacja i naprawa wartości oraz praca z NULL: CASE, COALESCE/NULLIF, TRY_CONVERT/TRY_CAST, reguły jakości

Na etapie oczyszczania danych bardzo często okazuje się, że problemem nie są tylko literówki czy nadmiarowe spacje, ale także wartości niepoprawne, puste, niejednoznaczne albo zapisane w niewłaściwym typie. W praktyce oznacza to konieczność sprawdzenia, czy dana wartość spełnia podstawowe reguły jakości, a jeśli nie — oznaczenia jej, naprawy lub bezpiecznego zastąpienia inną wartością.

W T-SQL najczęściej wykorzystuje się do tego zestaw prostych, ale bardzo skutecznych narzędzi: CASE, COALESCE, NULLIF, TRY_CONVERT oraz TRY_CAST. Pozwalają one budować logikę walidacyjną bez przerywania działania zapytania i bez ryzyka, że pojedyncza błędna wartość zatrzyma cały proces.

Po co walidować dane?

Walidacja ma dwa główne cele: wykrycie problemów oraz przygotowanie danych do dalszego użycia. Nawet jeśli źródło danych wygląda poprawnie, w praktyce można spotkać:

  • liczby zapisane jako tekst,
  • niepoprawne daty,
  • wartości puste zapisane jako pusty ciąg znaków zamiast NULL,
  • kody spoza dozwolonego zakresu,
  • wartości zastępcze typu 0, N/A, brak, -, które formalnie istnieją, ale nie niosą użytecznej informacji.

Bez uporządkowania takich przypadków trudno poprawnie filtrować dane, agregować je, łączyć z innymi tabelami lub raportować jako wiarygodne.

CASE — warunkowa ocena i naprawa wartości

CASE to podstawowe narzędzie do budowania reguł jakości. Umożliwia przypisanie wartości wynikowej zależnie od spełnienia określonych warunków. Najczęściej używa się go do:

  • oznaczania rekordów jako poprawne lub podejrzane,
  • naprawiania znanych błędów według prostych reguł,
  • tworzenia kolumn pomocniczych z flagami jakości,
  • uzupełniania braków wartością domyślną tylko w określonych przypadkach.
SELECT 
    CASE 
        WHEN TRY_CONVERT(date, DataZdarzenia) IS NULL THEN 'Błąd daty'
        WHEN Kwota < 0 THEN 'Kwota ujemna'
        ELSE 'OK'
    END AS StatusJakosci
FROM Dane;

Taki zapis jest czytelny i pozwala od razu zobaczyć, które rekordy wymagają dalszej uwagi. CASE nie służy wyłącznie do „naprawy” — równie często pełni rolę mechanizmu klasyfikacji problemów.

COALESCE i NULLIF — praca z brakami i wartościami pozornie wypełnionymi

W danych źródłowych brak informacji nie zawsze jest zapisany jako NULL. Często spotyka się pusty tekst, samą spację, zero lub umowny znacznik typu „brak”. Dlatego ważne jest rozróżnienie między rzeczywistą wartością a wartością technicznie obecną, ale biznesowo pustą.

NULLIF zamienia jedną wartość na NULL, jeśli spełnia określony warunek porównania. To bardzo wygodne przy oczyszczaniu danych wejściowych:

SELECT NULLIF(Kod, '') AS KodPoCzyszczeniu
FROM Dane;

Jeśli pole Kod zawiera pusty ciąg znaków, wynik będzie równy NULL. Dzięki temu można później traktować brak informacji spójnie.

COALESCE zwraca pierwszą nie-NULL-ową wartość z listy. Przydaje się, gdy chcemy wskazać wartość zastępczą albo priorytet między kilkoma polami:

SELECT COALESCE(EmailRoboczy, EmailPrywatny, 'brak@brak') AS EmailKontaktowy
FROM Dane;

Typowe zastosowanie wygląda tak: najpierw NULLIF zamienia „puste” dane na NULL, a potem COALESCE wybiera sensowną wartość rezerwową.

FunkcjaGłówne zastosowanieTypowy efekt
NULLIFUjednolicenie wartości pustych lub technicznychZamiana np. '' na NULL
COALESCEWybór pierwszej dostępnej wartościUzupełnienie braków
CASEWarunkowa logika walidacji lub korektyFlagi jakości, poprawki, klasyfikacja

TRY_CONVERT i TRY_CAST — bezpieczna konwersja typów

Jednym z najczęstszych problemów w data wrangling jest sytuacja, w której kolumna ma typ tekstowy, ale zawiera daty, liczby lub inne wartości oczekujące innego typu. Klasyczne CAST i CONVERT kończą się błędem, jeśli choć jedna wartość jest niepoprawna. To bywa kłopotliwe w dużych zbiorach.

Dlatego w procesie walidacji lepiej sprawdzają się TRY_CAST i TRY_CONVERT. Zamiast przerwać zapytanie, zwracają one NULL, gdy konwersja się nie powiedzie. Dzięki temu można bezpiecznie wykrywać błędne rekordy.

SELECT 
    WartoscTekstowa,
    TRY_CAST(WartoscTekstowa AS decimal(10,2)) AS KwotaNumeryczna
FROM Dane;

Jeżeli tekst nie da się zamienić na liczbę, wynik będzie NULL. To pozwala łatwo odsiać rekordy podejrzane lub oznaczyć je do poprawy.

TRY_CAST i TRY_CONVERT mają podobne zastosowanie. W praktyce wybór między nimi zależy głównie od preferowanego stylu zapisu oraz potrzeby użycia specyficznego formatu konwersji.

FunkcjaKiedy używaćCo dzieje się przy błędzie
CASTGdy dane są już pewne i poprawneZapytanie zgłasza błąd
CONVERTGdy potrzebna jest konwersja z kontrolą formatuZapytanie zgłasza błąd
TRY_CASTGdy dane mogą być niepoprawneZwraca NULL
TRY_CONVERTGdy dane mogą być niepoprawne i potrzebny jest konkretny formatZwraca NULL

Budowanie prostych reguł jakości danych

Samo użycie funkcji nie wystarcza, jeśli nie wiadomo, co uznajemy za wartość poprawną. Dlatego warto definiować proste reguły jakości, które można zapisać bezpośrednio w zapytaniach. Przykładowe reguły to:

  • data musi dać się przekonwertować do typu date,
  • kwota nie może być ujemna, jeśli biznesowo nie przewidujemy zwrotów lub korekt,
  • pole wymagane nie może być NULL ani pustym tekstem,
  • wartość liczbowa musi mieścić się w dopuszczalnym zakresie,
  • kod powinien należeć do określonego zbioru dopuszczalnych wartości.

Tego typu kontrolę można realizować przez dodatkowe kolumny obliczane, widoki walidacyjne albo zapytania raportujące błędy. Częstą praktyką jest tworzenie osobnych flag jakości:

SELECT 
    CASE WHEN NULLIF(LTRIM(RTRIM(Email)), '') IS NULL THEN 1 ELSE 0 END AS BrakEmail,
    CASE WHEN TRY_CONVERT(date, DataUrodzenia) IS NULL THEN 1 ELSE 0 END AS BlednaData,
    CASE WHEN TRY_CAST(Kwota AS decimal(10,2)) IS NULL THEN 1 ELSE 0 END AS BlednaKwota
FROM Dane;

Taki model jest wygodny, bo nie ukrywa problemów. Zamiast od razu nadpisywać dane, pozwala najpierw ocenić skalę błędów i zdecydować, które rekordy poprawić automatycznie, a które przekazać do ręcznej weryfikacji.

NULL nie zawsze oznacza to samo

Warto pamiętać, że NULL ma znaczenie techniczne i biznesowe jednocześnie. Technicznie oznacza brak wartości, ale biznesowo może znaczyć różne rzeczy:

  • informacja nie została podana,
  • wartość nie dotyczy danego rekordu,
  • dane nie udało się odczytać,
  • konwersja nie powiodła się,
  • wartość została celowo wyzerowana podczas czyszczenia.

Dlatego nie każdą wartość NULL należy automatycznie zastępować wartością domyślną. Czasem lepiej pozostawić NULL i dodać osobną flagę wyjaśniającą przyczynę. Pozwala to uniknąć mieszania danych rzeczywiście znanych z danymi tylko „uzupełnionymi” technicznie.

Dobra praktyka: walidować etapami

W procesie data wrangling lepiej unikać jednego, bardzo rozbudowanego wyrażenia, które jednocześnie czyści, konwertuje, naprawia i klasyfikuje dane. Znacznie bezpieczniej jest działać etapami:

  • najpierw znormalizować wartości pustych pól,
  • następnie wykonać bezpieczne konwersje,
  • potem ocenić zgodność z regułami jakości,
  • na końcu zdecydować, które wartości uzupełnić, a które pozostawić jako NULL.

Taki sposób pracy zwiększa czytelność zapytań i ułatwia kontrolę nad tym, skąd bierze się każda zmiana w danych.

CASE, COALESCE, NULLIF, TRY_CONVERT i TRY_CAST tworzą razem praktyczny zestaw narzędzi do walidacji i naprawy wartości w T-SQL. Pozwalają one bezpiecznie wykrywać błędy, ujednolicać braki danych oraz przygotowywać rekordy do dalszej analizy bez ryzyka, że pojedyncza zła wartość zaburzy cały proces.

💡 Pro tip: Najbezpieczniejszy wzorzec walidacji to: najpierw zamień wartości technicznie puste na NULL przez NULLIF, potem użyj TRY_CAST/TRY_CONVERT, a dopiero na końcu oceniaj reguły jakości przez CASE. Dzięki temu nie mieszasz błędów konwersji z faktycznym brakiem danych i łatwiej diagnozujesz źródło problemu.

Mapowanie słowników i ujednolicanie kodów: tabele referencyjne, JOIN, obsługa braków i nieznanych wartości

Jednym z najważniejszych etapów porządkowania danych jest ujednolicanie sposobu zapisu tych samych informacji. W praktyce oznacza to przypisanie wielu wariantów nazw, skrótów lub kodów do jednej, spójnej wartości biznesowej. Jeśli w źródłach pojawiają się różne wersje zapisu tej samej kategorii, regionu, statusu czy typu dokumentu, analiza staje się niespójna, a raporty mogą zwracać rozbieżne wyniki mimo pozornie identycznych danych.

Właśnie temu służy mapowanie słowników. Zamiast polegać na swobodnych wartościach tekstowych występujących w danych operacyjnych, tworzy się zestaw referencyjny zawierający zaakceptowane wartości docelowe oraz ich odpowiedniki źródłowe. Taki słownik staje się punktem odniesienia dla procesu oczyszczania i pozwala zamieniać różne warianty zapisu na jedną, kontrolowaną formę.

Najczęściej stosuje się do tego tabele referencyjne, które przechowują zależności między wartością wejściową a wartością znormalizowaną. Ich przewaga nad ręcznie wpisanymi warunkami jest duża: są łatwiejsze do utrzymania, prostsze do aktualizacji i bardziej przejrzyste dla zespołu. Gdy pojawia się nowy wariant kodu lub nazwy, zwykle wystarczy dopisać odpowiednią regułę do słownika, bez przebudowy całego procesu transformacji.

W T-SQL mapowanie tego typu opiera się zwykle na łączeniu danych roboczych z tabelą słownikową. Dzięki temu rekord źródłowy może zostać wzbogacony o wartość standardową, identyfikator kategorii albo opis odpowiadający danemu kodowi. To podejście jest szczególnie użyteczne wtedy, gdy dane pochodzą z wielu systemów i każdy z nich stosuje własne oznaczenia dla tych samych pojęć.

Warto rozróżnić dwa częste zastosowania mapowania:

  • normalizację wartości opisowych – gdy różne zapisy tekstowe mają prowadzić do jednej wspólnej etykiety,
  • translację kodów – gdy skróty, symbole lub identyfikatory z systemu źródłowego trzeba powiązać z kodem obowiązującym w modelu docelowym.

Choć oba przypadki są podobne, ich cel bywa inny. W pierwszym chodzi głównie o czytelność i spójność analityczną, a w drugim o zgodność z ustalonym standardem danych, integrację między systemami lub spełnienie reguł raportowych.

Istotnym zagadnieniem jest także obsługa braków i wartości nieznanych. W rzeczywistych zbiorach część rekordów nie znajdzie odpowiednika w słowniku: mogą zawierać literówki, przestarzałe oznaczenia, puste pola albo zupełnie nowe wartości, które nie zostały jeszcze sklasyfikowane. Tych przypadków nie należy ignorować, ponieważ często wskazują one na problemy jakościowe w źródle lub na niepełny model mapowania.

Najczęściej przyjmuje się jedną z kilku strategii postępowania:

  • pozostawienie wartości bez zmian – przydatne w analizie diagnostycznej, gdy chcemy zobaczyć, co nie zostało dopasowane,
  • przypisanie kategorii technicznej takiej jak „nieznane”, „inne” lub „brak mapowania” – użyteczne w raportach i agregacjach,
  • odrzucenie rekordu z dalszego przetwarzania – stosowane tam, gdzie zgodność ze słownikiem jest obowiązkowa,
  • skierowanie rekordu do weryfikacji – dobre rozwiązanie w procesach kontrolowanych, gdzie jakość danych jest monitorowana operacyjnie.

Dobry słownik referencyjny powinien być jednoznaczny, stabilny i zarządzalny. Oznacza to, że jeden wariant wejściowy nie powinien prowadzić do kilku różnych wyników bez wyraźnej reguły rozstrzygającej. W przeciwnym razie proces transformacji może dawać niespójne rezultaty zależnie od kontekstu, kolejności przetwarzania albo dodatkowych warunków.

W praktyce mapowanie słowników pełni więc podwójną rolę. Z jednej strony oczyszcza dane, eliminując chaos wynikający z wielu form zapisu. Z drugiej strony wprowadza warstwę semantyczną, dzięki której dane stają się porównywalne, raportowalne i gotowe do dalszego wykorzystania. To właśnie ten krok bardzo często decyduje o tym, czy końcowy zbiór będzie jedynie technicznie poprawny, czy także rzeczywiście użyteczny biznesowo.

8. Pivot/Unpivot – wprowadzenie do przekształceń kształtu danych z krótkimi przykładami zastosowań

W praktyce pracy z danymi nie zawsze problemem jest sama jakość wartości. Często wyzwaniem okazuje się również kształt danych, czyli sposób ich ułożenia w wierszach i kolumnach. Właśnie tutaj pojawiają się operacje Pivot i Unpivot, które w T-SQL służą do zmiany struktury wyniku tak, aby był wygodniejszy do analizy, raportowania albo dalszego przetwarzania.

Pivot polega na zamianie wartości z wierszy na kolumny. To podejście przydaje się wtedy, gdy dane są zapisane w formie „długiej”, a chcemy uzyskać bardziej raportowy, przekrojowy widok. Typowy przykład to sytuacja, w której kolejne kategorie, miesiące lub statusy występują jako osobne wiersze, ale końcowo wygodniej jest oglądać je jako osobne kolumny w jednym rekordzie.

Unpivot działa odwrotnie: zamienia wiele kolumn na zestaw wierszy. Jest to użyteczne wtedy, gdy dane wejściowe mają postać „szeroką”, ale do walidacji, agregacji, filtrowania lub standaryzacji lepiej sprawdza się układ bardziej pionowy. Dzięki temu łatwiej stosować jednolite reguły do wielu podobnych pól, zamiast obsługiwać każdą kolumnę osobno.

Najprościej można to ująć tak:

  • Pivot porządkuje dane pod kątem prezentacji i raportowania,
  • Unpivot porządkuje dane pod kątem przetwarzania i analizy.

W data wrangling oba podejścia są bardzo praktyczne. Pivot pomaga budować zestawienia, w których szybko widać różnice między kategoriami lub okresami. Unpivot jest z kolei przydatny, gdy trzeba ujednolicić strukturę danych pochodzących z arkuszy, eksportów lub źródeł, gdzie kolejne atrybuty zostały zapisane w osobnych kolumnach.

Krótki przegląd typowych zastosowań:

  • przekształcenie danych sprzedażowych z układu „jeden miesiąc = jeden wiersz” do układu „jeden miesiąc = jedna kolumna”,
  • zamiana zestawu kolumn opisujących różne typy kontaktu, wyniku pomiaru lub cechy rekordu na jednolitą listę wartości,
  • przygotowanie danych do wizualizacji, gdy narzędzie raportowe oczekuje konkretnego układu,
  • uproszczenie kontroli jakości, gdy wiele kolumn trzeba sprawdzić według tej samej reguły,
  • normalizacja importów z plików, w których dane zostały rozłożone zbyt szeroko.

Warto pamiętać, że zmiana kształtu danych nie poprawia jeszcze ich jakości sama w sobie, ale bardzo często umożliwia skuteczniejsze oczyszczanie. Dane po operacji Unpivot bywają łatwiejsze do filtrowania, grupowania i walidacji, a dane po Pivot lepiej nadają się do czytelnej prezentacji wyników biznesowych.

Z punktu widzenia T-SQL są to więc nie tylko techniki raportowe, ale również ważne narzędzia transformacji. Pozwalają przejść od formy wygodnej dla systemu źródłowego do formy wygodnej dla analityka, procesu jakościowego albo odbiorcy raportu.

Jeśli chcesz poznać więcej takich przykładów, zapraszamy na szkolenia Cognity, gdzie rozwijamy ten temat w praktyce.

icon

Formularz kontaktowyContact form

Imię *Name
NazwiskoSurname
Adres e-mail *E-mail address
Telefon *Phone number
UwagiComments