Blog JSystems - uwalniamy wiedzę!

Szukaj
AI jako nauczyciel SQL: zrzuty z ChatGPT i SQL Server Management Studio z części 2 przewodnika AI w SQL
Część 2 przewodnika AI w SQL. Na obrazie trzy prawdziwe zrzuty z tej części.

W skrócieChatGPT dobrze tłumaczy cudze zapytanie SQL linia po linii, wyjaśnia kolejność logicznego wykonywania i czyta plan wykonania prostym językiem. Pokazujemy siedem takich rozmów na jednym zapytaniu z bazy DemoShop i to, jak sprawdzić na bazie, czy prostsza wersja od AI daje ten sam wynik.

To część 2 z 8 przewodnika AI w SQL. Wszystkie przykłady powstały na bazie DemoShop w SQL Server 2022: fikcyjnym sklepie internetowym z 2,4 mln zamówień. Polecenia wpisujemy do ChatGPT, ale te same możesz podać Microsoft Copilotowi, Claude albo Gemini. Przy skryptach korzystających z mechanizmów serwera w małej szarej ramce znajdziesz ich odpowiedniki dla Oracle i PostgreSQL.

Pliki do tej części

Skrypt bazy uruchamiasz w SSMS na serwerze SQL Server 2019 lub nowszym. Tworzy bazę DemoShop, na której powstały wszystkie przykłady.

AI jako nauczyciel SQL: wyjaśnianie cudzego zapytania

Nie zawsze piszesz SQL od zera. Częściej dostajesz zapytanie po kimś, kto już nie pracuje w firmie, albo raport, który „zawsze działał”, i musisz zrozumieć, co właściwie liczy. To zadanie, w którym AI sprawdza się wyjątkowo dobrze, bo cała potrzebna informacja jest w samym kodzie. Wzięliśmy zapytanie, które dla kogoś znającego tylko podstawy SELECT jest już trudne: cztery tabele, złączenia zewnętrzne z warunkami w ON, COUNT(DISTINCT), HAVING i ranking funkcją okienkową.

SELECT r.RegionName,
       c.Segment,
       COUNT(DISTINCT c.CustomerID)                                   AS Customers,
       COUNT(DISTINCT o.OrderID)                                      AS Orders2025,
       SUM(oi.Quantity * oi.UnitPrice * (100 - oi.DiscountPct) / 100) AS Revenue2025,
       RANK() OVER (PARTITION BY c.Segment
                    ORDER BY SUM(oi.Quantity * oi.UnitPrice * (100 - oi.DiscountPct) / 100) DESC) AS RankInSegment
FROM dbo.Customers AS c
JOIN dbo.Regions AS r ON r.RegionID = c.RegionID
LEFT JOIN dbo.Orders AS o
       ON o.CustomerID = c.CustomerID
      AND o.OrderDate >= '20250101' AND o.OrderDate < '20260101'
      AND o.Status <> 'CANCELLED'
LEFT JOIN dbo.OrderItems AS oi ON oi.OrderID = o.OrderID
WHERE c.Country = 'PL'
GROUP BY r.RegionName, c.Segment
HAVING COUNT(DISTINCT o.OrderID) > 0
ORDER BY c.Segment, RankInSegment;

Prowadzimy jedną rozmowę z siedmioma pytaniami, od ogólnego wyjaśnienia po plan wykonania. Świadomie nie załączamy schematu, bo tak zwykle wygląda prośba o wyjaśnienie: wklejasz sam kod.

Linia po linii, prostym językiem

Wyjaśnij mi to zapytanie linia po linii, prostym językiem. Znam podstawy SELECT, ale nie znam funkcji okienkowych. Baza to SQL Server 2022.

ChatGPT wyjaśnia zapytanie SQL linia po linii: COUNT DISTINCT, wartość pozycji po rabacie i sens grupowania na przykładach z małymi tabelami
Fragment odpowiedzi. ChatGPT tłumaczy każdą linię na małych przykładach: dlaczego COUNT(DISTINCT c.CustomerID) daje 1, a COUNT(c.CustomerID) dałoby 3.

Wyjaśnienie jest dobre dydaktycznie: krótkie tabelki z trzema wierszami pokazują, skąd biorą się duplikaty po złączeniu i po co jest DISTINCT. Jest w nim jednak drobiazg, który dobrze ilustruje granice AI bez schematu. Opisując kolumnę Segment, ChatGPT podaje przykładowe wartości „SMB, Enterprise, Consumer”. W DemoShop segmenty to B2C i B2B. Model nie miał skąd tego wiedzieć, więc wymyślił typowe wartości i uczciwie oznaczył je jako przykładowe. W wyjaśnieniu to nie szkodzi, ale gdybyś na tej podstawie napisał filtr WHERE c.Segment = 'Enterprise', dostałbyś pusty wynik.

Kolejność logicznego wykonywania zapytania

Najczęstsze źródło niezrozumienia SQL to przekonanie, że zapytanie wykonuje się w kolejności, w jakiej je czytamy, od SELECT. Logicznie jest inaczej: najpierw powstaje źródło danych z FROM i złączeń, potem działają filtry, grupowanie, funkcje okienkowe, a dopiero na końcu lista kolumn i sortowanie.

Animacja logicznej kolejności wykonywania zapytania SQL: FROM i JOIN, WHERE, GROUP BY, HAVING, funkcje okienkowe, SELECT, ORDER BY
Logiczna kolejność przetwarzania zapytania SELECT. Z niej wynika, dlaczego aliasu z SELECT nie użyjesz w WHERE, a w ORDER BY już tak, i dlaczego funkcja okienkowa widzi wiersze po grupowaniu.

Pokaż kolejność logicznego wykonywania tego zapytania: w jakiej kolejności SQL Server przetwarza klauzule i co jest dostępne na każdym etapie.

ChatGPT rozpisuje logiczną kolejność wykonywania zapytania: FROM, JOIN, WHERE, GROUP BY, HAVING, funkcje okienkowe, SELECT i ORDER BY z kolumnami dostępnymi na każdym etapie
ChatGPT zaczyna od ważnego zastrzeżenia: to kolejność logiczna, a nie fizyczna, bo optymalizator może wykonać zapytanie inaczej, byle wynik był ten sam. Przy każdym etapie wypisuje, które kolumny już istnieją, a których jeszcze nie ma.

Najbardziej wartościowa część odpowiedzi to przykłady tego, czego nie da się zrobić na danym etapie, na przykład WHERE Revenue2025 > 100000. Alias Revenue2025 powstaje dopiero w SELECT, a suma dopiero po GROUP BY, więc taki warunek musi trafić do HAVING. Tę samą regułę pokazujemy w praktyce w sekcji o błędach składniowych, gdzie alias użyty w WHERE kończy się błędem 207.

Dlaczego LEFT JOIN, a nie INNER JOIN

Dlaczego jest tu LEFT JOIN do dbo.Orders, a nie INNER JOIN? Co by się zmieniło w wyniku, gdyby warunki o dacie i statusie przenieść z ON do WHERE?

ChatGPT wyjaśnia różnicę między LEFT JOIN z warunkami w ON a warunkami w WHERE i wpływ na liczbę klientów w grupie
ChatGPT wyłapuje subtelność, której łatwo nie zauważyć: kolumna Customers liczy wszystkich polskich klientów w regionie i segmencie, także tych bez zamówień w 2025 roku, a Orders2025 tylko zamówienia. Przeniesienie warunków do WHERE zamieniłoby LEFT JOIN w INNER JOIN.

To odpowiedź, która zmienia sposób czytania raportu. Kolumna Customers nie oznacza „klientów, którzy kupili w 2025 roku”, tylko „wszystkich polskich klientów w grupie, o ile w grupie było choć jedno zamówienie”. Jeśli raport trafia do zarządu podpisany „liczba klientów 2025”, to podpis kłamie. Takie odkrycia są najcenniejszym efektem rozmowy z AI o cudzym kodzie: nie składnia, tylko znaczenie liczb.

Prostsza wersja z dowodem, że wynik jest taki sam

Pokaż prostszą wersję tego zapytania, która zwraca dokładnie ten sam wynik.

ChatGPT przepisuje zapytanie na prostszą wersję z dwoma CTE: CustomerSales z agregacją na poziomie klienta i RegionSales z podsumowaniem regionu i segmentu
Prostsza wersja dzieli pracę na etapy: najpierw jeden wiersz na klienta (CustomerSales), potem podsumowanie regionu i segmentu, na końcu ranking. COUNT(DISTINCT) nie jest już potrzebne, bo po pierwszym etapie klient występuje raz.

„Zwraca dokładnie ten sam wynik” to obietnica, którą trzeba sprawdzić, a nie przyjąć. Najprostszy dowód w SQL Server to operator EXCEPT użyty w obie strony: wiersze, które są w pierwszym wyniku, a nie ma ich w drugim, plus wiersze, które są w drugim, a nie ma ich w pierwszym. Zero wierszy oznacza, że oba wyniki są identyczne jako zbiory.

/* Szablon: dowód równoważności dwóch zapytań */
WITH Oryginal AS ( /* stare zapytanie bez ORDER BY */ ),
     Nowe     AS ( /* nowe zapytanie bez ORDER BY */ )
SELECT 'tylko w oryginale' AS Gdzie, * FROM (SELECT * FROM Oryginal EXCEPT SELECT * FROM Nowe) AS x
UNION ALL
SELECT 'tylko w nowej wersji', * FROM (SELECT * FROM Nowe EXCEPT SELECT * FROM Oryginal) AS y;
/* Dowód równoważności: wiersze, które są tylko w jednej z wersji */
WITH CustomerSales AS
(
    SELECT
        o.CustomerID,
        COUNT(DISTINCT o.OrderID) AS Orders2025,
        SUM(oi.Quantity * oi.UnitPrice * (100 - oi.DiscountPct) / 100) AS Revenue2025
    FROM dbo.Orders AS o
    LEFT JOIN dbo.OrderItems AS oi
        ON oi.OrderID = o.OrderID
    WHERE o.OrderDate >= '20250101'
      AND o.OrderDate <  '20260101'
      AND o.Status <> 'CANCELLED'
    GROUP BY o.CustomerID
),
RegionSales AS
(
    SELECT
        r.RegionName,
        c.Segment,
        COUNT(*) AS Customers,
        SUM(cs.Orders2025) AS Orders2025,
        SUM(cs.Revenue2025) AS Revenue2025
    FROM dbo.Customers AS c
    JOIN dbo.Regions AS r
        ON r.RegionID = c.RegionID
    LEFT JOIN CustomerSales AS cs
        ON cs.CustomerID = c.CustomerID
    WHERE c.Country = 'PL'
    GROUP BY r.RegionName, c.Segment
    HAVING SUM(cs.Orders2025) > 0
),
Nowe AS (
SELECT
    RegionName,
    Segment,
    Customers,
    Orders2025,
    Revenue2025,
    RANK() OVER (
        PARTITION BY Segment
        ORDER BY Revenue2025 DESC
    ) AS RankInSegment
FROM RegionSales
),
Oryginal AS (
SELECT r.RegionName,
       c.Segment,
       COUNT(DISTINCT c.CustomerID)                                   AS Customers,
       COUNT(DISTINCT o.OrderID)                                      AS Orders2025,
       SUM(oi.Quantity * oi.UnitPrice * (100 - oi.DiscountPct) / 100) AS Revenue2025,
       RANK() OVER (PARTITION BY c.Segment
                    ORDER BY SUM(oi.Quantity * oi.UnitPrice * (100 - oi.DiscountPct) / 100) DESC) AS RankInSegment
FROM dbo.Customers AS c
JOIN dbo.Regions AS r ON r.RegionID = c.RegionID
LEFT JOIN dbo.Orders AS o
       ON o.CustomerID = c.CustomerID
      AND o.OrderDate >= '20250101' AND o.OrderDate < '20260101'
      AND o.Status <> 'CANCELLED'
LEFT JOIN dbo.OrderItems AS oi ON oi.OrderID = o.OrderID
WHERE c.Country = 'PL'
GROUP BY r.RegionName, c.Segment
HAVING COUNT(DISTINCT o.OrderID) > 0
)
SELECT 'tylko w oryginale' AS Gdzie, * FROM (SELECT * FROM Oryginal EXCEPT SELECT * FROM Nowe) AS x
UNION ALL
SELECT 'tylko w nowej wersji', * FROM (SELECT * FROM Nowe EXCEPT SELECT * FROM Oryginal) AS y;
Dowód równoważności w SSMS: zapytanie z EXCEPT w obie strony zwraca zero wierszy, więc oryginał i wersja od AI dają ten sam wynik
Oryginał i prostsza wersja od AI wstawione do szablonu: zero wierszy różnicy, a każde z zapytań zwraca osobno po 32 wiersze. Ten sam test przeszła wersja z CTE z następnego pytania.
Uwaga na duplikaty. EXCEPT porównuje zbiory, więc nie zauważy, że jedna wersja zwraca wiersz dwa razy, a druga raz. Jeśli to możliwe w Twoim zapytaniu, porównaj dodatkowo liczbę wierszy obu wersji albo dodaj do obu kolumnę COUNT(*) OVER (PARTITION BY ...). Sumy kontrolne tego typu rozwijamy w sekcji o refaktoryzacji.

Zależności między tabelami jako diagram

Narysuj zależności między tabelami użytymi w tym zapytaniu jako diagram Mermaid (erDiagram) z kluczami i licznościami relacji.

ChatGPT rysuje diagram relacji Mermaid dla tabel REGIONS, CUSTOMERS, ORDERS i ORDERITEMS z kluczami i licznościami jeden do wielu
Mermaid to język opisu diagramów, który ChatGPT od razu wyświetla jako rysunek. Liczności są poprawne, ale typy kolumn (int, varchar, date) AI zgadło: w DemoShop OrderDate to datetime2(0), a RegionName to nvarchar.

Diagram jest poprawny co do relacji, bo te wynikają z warunków złączeń w kodzie. Typy kolumn AI dopisało z założenia i samo o tym uprzedza w odpowiedzi („zakładam typowe klucze”). Jeśli diagram ma trafić do dokumentacji, poproś o niego z załączonym opisem schematu, a nie z samego zapytania.

Przepisanie na CTE z komentarzem przy każdym kroku

Przepisz to zapytanie z użyciem CTE tak, żeby każdy etap obliczeń był osobnym, nazwanym krokiem z komentarzem.

ChatGPT przepisuje zapytanie na siedem nazwanych kroków CTE z komentarzami: polscy klienci, zamówienia 2025, wartość pozycji, złączenie, grupowanie, filtr grup i ranking
Pierwsze z siedmiu kroków CTE, każdy z komentarzem w stylu „KROK 3: liczymy wartość każdej pozycji zamówienia po rabacie”. Ta wersja jest dłuższa od oryginału, ale da się ją czytać od góry do dołu i testować kawałkami.

Wersję z CTE przepuściliśmy przez ten sam test EXCEPT. Wynik: zero różnic. Takie przepisanie to dobry pierwszy krok przy przejmowaniu cudzego kodu. Każdy etap możesz uruchomić osobno (zamieniając końcowe SELECT na SELECT * FROM NazwaKroku) i zobaczyć dane pośrednie.

Plan wykonania „po ludzku”

Ostatnie pytanie dotyczy już nie tego, co zapytanie liczy, ale jak serwer to robi. Plan wykonania to opis operacji, które SQL Server wykonuje, żeby zwrócić wynik. Jak go pobrać i zapisać do pliku, pokazujemy szczegółowo w sekcji o planie wykonania. Tu załączamy gotowy plik .sqlplan z rzeczywistego wykonania zapytania.

Oracle i PostgreSQL: ten sam skrypt dla innych baz znajdziesz w plikach oracle_plan_wykonania_i_pomiar.sql i postgresql_plan_wykonania_i_pomiar.sql (plan rzeczywisty zapisany do pliku dla AI: część 4).

Załączam plik z rzeczywistym planem wykonania tego zapytania (raport_regiony_2025.sqlplan, zapisany w SSMS). Wyjaśnij go po ludzku: co serwer robi krok po kroku, który operator kosztuje najwięcej i dlaczego, i czy coś w planie jest niepokojące.

ChatGPT wyjaśnia rzeczywisty plan wykonania z pliku sqlplan: równoległość, skanowanie tabel Orders i OrderItems, złączenia Hash Match, brakujący indeks i nadmierny przydział pamięci
ChatGPT czyta plan od tabel źródłowych do wyniku. Wskazuje dwa skany odpowiedzialne za 85% szacowanego kosztu, sugestię brakującego indeksu na Orders i przydział pamięci niemal 9 razy większy niż faktyczne zużycie.

Każdą liczbę z tej odpowiedzi porównaliśmy z plikiem planu i wszystkie się zgadzają: stopień równoległości 4, 696 ms czasu i 2697 ms czasu procesora, 723 421 z 2,4 mln zamówień po filtrze, 1 960 873 wiersze po złączeniu z pozycjami, 994 MB przydzielonej pamięci przy 116 MB użytych. Co ważne, ChatGPT nie poprzestał na słowie „skan”, tylko policzył, jaką część kosztu planu stanowi każdy operator, i zaznaczył, że sugestii brakującego indeksu nie należy kopiować bez sprawdzenia innych zapytań. To dokładnie ten sposób pracy, który rozwijamy w części o optymalizacji.

Polecenia, które warto mieć pod ręką, gdy uczysz się z cudzego kodu: „wyjaśnij linia po linii dla osoby, która zna tylko SELECT”, „pokaż logiczną kolejność wykonywania”, „co by się zmieniło, gdyby...”, „pokaż prostszą wersję zwracającą ten sam wynik”, „narysuj zależności tabel”, „rozbij na nazwane kroki CTE”, „wyjaśnij plan po ludzku”. Wszystkie znajdziesz w bibliotece poleceń na końcu artykułu.
✕Powiększony zrzut ekranu z przewodnika AI w SQL
Szkolenie Język SQL ze wsparciem AI

Szkolenie Język SQL ze wsparciem AI

Najbliższy termin gwarantowany: 28.10.2026

Sprawdź terminy

Najczęściej zadawane pytania

Czy ChatGPT może nauczyć mnie SQL?
Tak, jako cierpliwy korepetytor do konkretnego kodu: wyjaśnia zapytanie linia po linii, kolejność wykonywania klauzul i różnice między złączeniami. Każde wyjaśnienie warto sprawdzić, uruchamiając zapytanie i jego wersje na bazie.
W jakiej kolejności SQL Server wykonuje klauzule zapytania?
Logicznie najpierw FROM i złączenia, potem WHERE, GROUP BY, HAVING, SELECT, DISTINCT i ORDER BY na końcu. Dlatego aliasu z listy SELECT nie użyjesz w WHERE, a warunek na wyniku agregacji musi trafić do HAVING.
Jak sprawdzić, że uproszczone przez AI zapytanie daje ten sam wynik?
Zapisz wyniki obu wersji do tabel tymczasowych i porównaj je operatorem EXCEPT w obie strony. Zero wierszy różnicy w obu kierunkach plus ta sama liczba wierszy oznacza, że wyniki są identyczne.
Czy AI potrafi wyjaśnić plan wykonania zapytania?
Tak, jeśli dostanie plik planu rzeczywistego zapisany w SSMS, a nie zrzut ekranu. Z pliku odczytuje operatory, liczby wierszy, ostrzeżenia i przydział pamięci, a potem tłumaczy, który krok kosztuje najwięcej i dlaczego.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...