Ramki ROWS a RANGE
Subtelna i często sprawdzana różnica między ramkami opartymi na wierszach a ramkami opartymi na wartościach
Ramki ROWS a RANGE to bezpłatna lekcja SQL Interview Prep na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Interview Prep zawiera 4 lekcji w sumie.
Rozróżnienie, o które pytają rekruterzy
Gdy potrafią już Państwo napisać sumę narastającą, naturalne pytanie dodatkowe brzmi: „Jaka jest różnica między ROWS a RANGE w ramce okna?” To precyzyjny wyznacznik poziomu średniozaawansowanego. Wielu kandydatów codziennie używa ramek, nie zauważając, że te dwa słowa kluczowe działają inaczej.
Oba określają zbiór wierszy widocznych dla agregatu, ale zasadniczo różnią się sposobem wyznaczania tego zbioru. Poprawna odpowiedź pozwala się wyróżnić.
ROWS zlicza wiersze fizyczne
ROWS działa pozycyjnie. ROWS BETWEEN 2 PRECEDING AND CURRENT ROW oznacza dosłownie bieżący wiersz oraz dwa fizyczne wiersze znajdujące się bezpośrednio przed nim w uporządkowanej sekwencji.
Nie ma znaczenia, czy sąsiednie wiersze mają tę samą wartość ORDER BY. Trzy wiersze to trzy wiersze, kropka. Taką ramkę niemal zawsze warto stosować w przypadku średnich kroczących i ścisłych sum narastających.
SELECT
sale_date,
amount,
SUM(amount) OVER (
ORDER BY sale_date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS rows_sum
FROM sales;RANGE zlicza według wartości
RANGE opiera się na wartościach. Obejmuje każdy wiersz, którego wartość ORDER BY mieści się w logicznym zakresie wartości bieżącego wiersza, a nie określoną liczbę wierszy.
Najważniejsza konsekwencja jest taka, że w przypadku RANGE wszystkie wiersze, które remisują pod względem wartości ORDER BY, są traktowane jako jedna grupa wierszy równorzędnych. Wszystkie otrzymują tę samą ramkę, a zatem również ten sam wynik.
SELECT
sale_date,
amount,
SUM(amount) OVER (
ORDER BY sale_date
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS range_sum
FROM sales;Przykład remisu ujawniający różnicę
Załóżmy, że dwie sprzedaże miały miejsce 2024-03-02 i opiewały na kwoty 30 oraz 40, a wcześniej, 2024-03-01, odnotowano sprzedaż na kwotę 100.
- Przy RANGE do bieżącego wiersza: oba wiersze z 03-02 są równorzędne, więc w obu widnieje 100 + 30 + 40 = 170.
- Przy ROWS do bieżącego wiersza: pierwszy wiersz z 03-02 pokazuje 130, a drugi 170, ponieważ każdy wiersz rozszerza ramkę o jedną pozycję.
Te same dane, inne liczby. Ta rozbieżność przy remisach jest sednem tego pytania.
Dlaczego domyślnie używane jest RANGE
Przypomnijmy, że wyrażenie OVER (ORDER BY ...) bez jawnie określonej ramki domyślnie używa RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
Oznacza to, że naiwna suma narastająca po cichu korzysta z RANGE. Przy unikalnych kluczach sortowania jest ono identyczne z ROWS, więc błąd pozostaje ukryty. Gdy tylko pojawią się zduplikowane wartości sortowania, suma narastająca po cichu łączy wiersze z remisem. Dlatego doświadczeni inżynierowie jawnie zapisują ROWS.
RANGE z przesunięciem liczbowym
RANGE może przyjmować przesunięcie wartości, a nie tylko UNBOUNDED. RANGE BETWEEN 7 PRECEDING AND CURRENT ROW zastosowane do kolumny datowej lub numerycznej obejmuje każdy wiersz, którego wartość znajduje się w odległości nie większej niż 7 jednostek od bieżącej wartości.
W przypadku dat daje to rzeczywiste okno „ostatnich 7 dni”, które poprawnie pomija brakujące dni, podczas gdy ROWS 7 PRECEDING pobrałoby poprzednie 7 wierszy, niezależnie od luk. Znajomość tego niuansu to mocny element odpowiedzi.
SELECT
sale_date,
amount,
SUM(amount) OVER (
ORDER BY sale_date
RANGE BETWEEN INTERVAL '7 days' PRECEDING AND CURRENT ROW
) AS last_7_days
FROM sales;ROWS ignoruje luki
Druga strona medalu jest taka, że ROWS nie uwzględnia luk w danych. Jeśli w tabeli sprzedaży brakuje weekendów, ROWS BETWEEN 6 PRECEDING AND CURRENT ROW obejmuje 7 zarejestrowanych dni, co w rzeczywistości może oznaczać dwa tygodnie kalendarzowe.
Wybór zależy więc od intencji: ostatnie N rekordów oznacza ROWS, a ostatnie N jednostek wartości (dni, dolarów) oznacza RANGE z przesunięciem.
Rzeczywiste wsparcie w dialektach SQL
W rzetelnej odpowiedzi na rozmowie kwalifikacyjnej warto wspomnieć o różnicach w obsłudze:
- PostgreSQL obsługuje
RANGEz przesunięciami (od wersji 11) oraz w pełni obsługujeROWS. - SQL Server obsługuje
ROWSiRANGE, aleRANGEdziała tylko zUNBOUNDED/CURRENT ROW, a nie z przesunięciami liczbowymi. - MySQL 8 obsługuje oba tryby, ale typy przesunięć dla
RANGEsą ograniczone.
Jeśli przesunięcie liczbowe w RANGE nie jest dostępne, można je zasymulować za pomocą złączenia tabeli z samą sobą albo wygenerowanego kalendarza. Wspomnienie o tym pokazuje świadomość realiów środowiska produkcyjnego.
GROUPS: trzeci tryb
Istnieje jeszcze mniej znany, trzeci tryb definiowania ramki: GROUPS. Zlicza on grupy równorzędnych wierszy, a nie wiersze ani wartości. GROUPS BETWEEN 1 PRECEDING AND CURRENT ROW obejmuje bieżącą grupę równorzędnych wierszy oraz grupę bezpośrednio przed nią.
Rzadko jest wymagany, ale wymienienie go w odpowiedzi na pytanie „czy istnieją inne tryby ramki?” pokazuje rzeczywistą biegłość. Jest obsługiwany w PostgreSQL 11+ i kilku innych systemach.
SELECT
sale_date,
amount,
SUM(amount) OVER (
ORDER BY sale_date
GROUPS BETWEEN 1 PRECEDING AND CURRENT ROW
) AS two_day_groups
FROM sales;Reguła wyboru do wyrecytowania
Sprowadźmy cały temat do jednego zdania, które można wypowiedzieć na rozmowie kwalifikacyjnej:
„Używam ROWS, gdy mam na myśli stałą liczbę fizycznych wierszy, RANGE, gdy mam na myśli logiczny zakres wartości sortowania, i pamiętam, że powtarzające się wartości powodują różnicę między nimi, ponieważ domyślne RANGE grupuje równe wartości.”
To jedno zdanie wyczerpująco i pewnie odpowiada na pytanie.
Porównanie bezpośrednie
Umieszczenie obu sposobów definiowania ramki w jednym zapytaniu uwidacznia różnicę. Należy uruchomić je na danych z powtarzającymi się datami i porównać obie kolumny wiersz po wierszu.
Przy unikalnych datach kolumny są identyczne, natomiast przy takich samych datach kolumna RANGE powtarza tę samą sumę dla równorzędnych wierszy, podczas gdy kolumna ROWS rośnie za każdym razem o jeden krok.
SELECT
sale_date,
amount,
SUM(amount) OVER (ORDER BY sale_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS rows_total,
SUM(amount) OVER (ORDER BY sale_date
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_total
FROM sales;Szybkie sprawdzenie
Dwa wiersze mają taką samą wartość używaną w ORDER BY, a ramka jest domyślna. Co się stanie?
Podsumowanie: ROWS a RANGE
ROWS zlicza fizyczne wiersze, a RANGE działa na podstawie logicznej wartości kolumny sortowania i traktuje powtarzające się wartości jako grupę równorzędnych wierszy. Domyślna ramka OVER (ORDER BY ...) to RANGE, dlatego prosta suma narastająca może łączyć wiersze o takich samych wartościach sortowania.
Należy wybrać ROWS dla „ostatnich N rekordów” oraz odpornych na luki okien kroczących, a RANGE z przesunięciem dla „ostatnich N dni/dolarów”, gdy luki mają być uwzględniane. Sama znajomość istnienia GROUPS jest dodatkowym atutem. Następnie zastosujemy ramkę ROWS do obliczania średnich kroczących.
Często zadawane pytania
Czy lekcja „Ramki ROWS a RANGE” jest bezpłatna?
Tak — pełny tekst „Ramki ROWS a RANGE” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Interview Prep, przejdź na CoddyKit PRO. Kurs SQL Interview Prep zawiera 4 lekcji w sumie.
Co nauczysz się w „Ramki ROWS a RANGE”?
Subtelna i często sprawdzana różnica między ramkami opartymi na wierszach a ramkami opartymi na wartościach Ćwiczysz SQL Interview Prep z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć SQL Interview Prep?
Nie wymagamy żadnego doświadczenia. SQL Interview Prep w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Ramki ROWS a RANGE”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji SQL Interview Prep?
Tak. Każda lekcja SQL Interview Prep zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Sumy narastające z ramkami okienkowymi
- Ramki ROWS a RANGE
- Średnie kroczące w przesuwanym oknie
- Rozkład skumulowany i procent całości