approx. 14 min updated: 2026-08-04

Filtry w Raport Studio — każdy typ na przykładach (PostgreSQL i MSSQL)

Praktyczny katalog przykładów: jak zdefiniować każdy z jedenastu typów parametrów raportu, jak wstawić go do zapytania SQL i czym różni się składnia na wewnętrznej bazie Veloryn (PostgreSQL) od raportu na połączeniu integracyjnym (MSSQL, np. WAPRO). Podstawy modułu znajdziesz w kompletnym przewodniku Raport Studio — tutaj skupiamy się wyłącznie na filtrach.

1Trzy zasady wspólne dla wszystkich typów

Parametr = kod w SQL

Parametr zdefiniowany w zakładce Filtry i parametry wstawiasz do zapytania jako @kod — dokładnie ten kod, który wpisałeś w polu Kod parametru. Wartość jest podstawiana bezpiecznie (bind po stronie bazy, nie sklejanie tekstu) — działa to identycznie na PostgreSQL i na MSSQL. Parametr, którego @kod nie występuje w SQL, jest ignorowany: filtr będzie widoczny, ale nie zmieni wyniku.

WażneKod parametru nie może być przedrostkiem innego kodu. Podmiana szuka dosłownie tekstu @kod, więc para parametrów rok i rok_od zepsuje zapytanie — @rok „wejdzie" w środek @rok_od. Nazywaj parametry tak, by żaden nie zaczynał się pełnym kodem innego (np. rok + data_od, albo rok_wybrany + rok_od).

Filtry niewymagane — zawsze w klauzuli [[ ... ]]

Fragment SQL ujęty w podwójne nawiasy kwadratowe znika z zapytania w całości, jeśli którykolwiek użyty w nim parametr nie ma wartości (ani wpisanej przez użytkownika, ani domyślnej). To podstawowy wzorzec filtra opcjonalnego — bez niego pusty parametr zostawi w SQL nieprawidłowy warunek:

WHERE f.data_wystawienia BETWEEN @zakres
  [[ AND f.status = @status ]]
  [[ AND f.contractor_id = @kontrahent ]]

Parametr z ustawioną Wartością domyślną nigdy nie „wygasi" klauzuli — liczy się wartość efektywna. Klauzule [[ ]] działają też w zapytaniach opcji list oraz w raportach na połączeniach zewnętrznych.

Dialekt SQL zależy od źródła danych

Raport na wewnętrznej bazie piszesz w dialekcie PostgreSQL. Raport na połączeniu integracyjnym z bazą MSSQL (np. WAPRO) piszesz w T-SQL — ale definicje parametrów, składnia @kod, klauzule [[ ]] i tokeny działają tak samo. Różnią się tylko funkcje SQL wokół parametru (np. daty, sklejanie tekstu) — stąd w tym artykule każdy typ ma dwa warianty przykładu.

UwagaNa MSSQL nie używaj tokenu {TODAY} — system podstawia za niego CURRENT_DATE, którego T-SQL nie zna. Bezpieczny na obu bazach jest {NOW} (CURRENT_TIMESTAMP); „dzisiejszą datę" w T-SQL wyraź jako CAST(GETDATE() AS date). Nazwy tabel w przykładach MSSQL są poglądowe — właściwe nazwy z Twojej bazy podpowiada zakładka Schemat bazy danych.

2Ściąga: 11 typów parametrów

TypKontrolkaWzorzec w SQLSzczegóły
TekstPole tekstowekolumna ILIKE '%' || @fraza || '%'§3
Liczba całkowitaPole liczbowekolumna = @rok§4
Liczba dziesiętnaPole liczbowekolumna >= @prog§4
DataKalendarzkolumna >= @data_od§5
Data i czasKalendarz z godzinąkolumna >= @od_kiedy§5
Tak/NiePrzełącznikczy_aktywny = @tylko_aktywne§6
Lista wyboruLista z wyszukiwarkąkolumna = @status§7
Lista wielokrotnaLista wielu wartościkolumna IN @statusy (bez nawiasów)§8
MiesiącWybór miesiącadate_trunc('month', kolumna) = @miesiac§9
Drzewo miesięcyDrzewo rok → miesiącjak Miesiąc + SQL zakresu danych§10
Zakres datOd–do z presetamikolumna BETWEEN @zakres§11

3Tekst

Wartość trafia do SQL jako zwykły napis. Najczęstsze użycie to szukanie po fragmencie — pamiętaj, że operator „bez rozróżniania wielkości liter" i sklejanie tekstu wyglądają w obu dialektach inaczej:

PostgreSQL (baza Veloryn):

SELECT numer, contractor_name, wartosc_netto
FROM sales.sales_invoices
WHERE tenant_id = {TENANT_ID}
  [[ AND contractor_name ILIKE '%' || @fraza || '%' ]]

MSSQL (np. WAPRO) — LIKE zwykle nie rozróżnia wielkości liter (decyduje ustawienie bazy), tekst skleja się plusem:

SELECT k.nazwa, k.nip, k.miejscowosc
FROM dbo.kontrahent k
WHERE 1 = 1
  [[ AND k.nazwa LIKE '%' + @fraza + '%' ]]

WskazówkaWzorzec WHERE 1 = 1 pozwala każdemu kolejnemu warunkowi zaczynać się od AND — klauzule [[ ]] mogą wtedy znikać w dowolnej konfiguracji bez psucia składni.

4Liczba całkowita i Liczba dziesiętna

Oba typy działają identycznie w SQL — różni je tylko walidacja w kontrolce (całkowita nie przyjmie ułamka). Typowe zastosowania: rok, próg kwotowy, minimalna ilość.

PostgreSQL — rok jako liczba całkowita, próg jako dziesiętna:

SELECT numer, data_wystawienia, wartosc_netto
FROM sales.sales_invoices
WHERE tenant_id = {TENANT_ID}
  AND EXTRACT(YEAR FROM data_wystawienia) = @rok
  [[ AND wartosc_netto >= @kwota_min ]]

MSSQL — funkcja YEAR() zamiast EXTRACT:

SELECT d.numer, d.data_dokumentu, d.wartosc_netto
FROM dbo.dokument_handlowy d
WHERE YEAR(d.data_dokumentu) = @rok
  [[ AND d.wartosc_netto >= @kwota_min ]]

5Data oraz Data i czas

Pojedyncza data najlepiej sprawdza się jako granica: „od dnia", „do dnia", „stan na dzień". Do pełnych przedziałów wygodniejszy jest typ Zakres dat.

PostgreSQL:

SELECT numer, data_wystawienia, wartosc_netto
FROM sales.sales_invoices
WHERE tenant_id = {TENANT_ID}
  AND data_wystawienia >= @data_od
  [[ AND data_wystawienia < (@data_do)::date + INTERVAL '1 day' ]]

MSSQL:

SELECT d.numer, d.data_dokumentu, d.wartosc_netto
FROM dbo.dokument_handlowy d
WHERE d.data_dokumentu >= @data_od
  [[ AND d.data_dokumentu < DATEADD(DAY, 1, @data_do) ]]

WskazówkaGdy kolumna przechowuje datę z godziną, warunek „do dnia" pisz jako < dzień + 1 (jak wyżej), a nie <= @data_do — inaczej wpisy z godziną późniejszą niż północ ostatniego dnia wypadną z wyniku. Ta sama zasada dotyczy typu „Data i czas" używanego jako granica dnia.

6Tak/Nie

Przełącznik logiczny. Najbardziej naturalny wzorzec to filtr „pokaż tylko…", w którym włączenie przełącznika zawęża wynik, a wyłączenie pokazuje wszystko:

PostgreSQL:

SELECT nazwa, is_active
FROM products.products
WHERE tenant_id = {TENANT_ID}
  [[ AND is_active = @tylko_aktywne ]]

MSSQL — kolumny logiczne to zwykle bit (0/1), zapis bez zmian:

SELECT a.nazwa, a.czy_aktywny
FROM dbo.artykul a
WHERE 1 = 1
  [[ AND a.czy_aktywny = @tylko_aktywne ]]

7Lista wyboru

Użytkownik wybiera jedną wartość z listy — do SQL trafia wartość opcji, użytkownik widzi etykietę. W SQL to zwykłe porównanie: kolumna = @status. Ciekawie robi się przy definiowaniu opcji.

Opcje statyczne

Jedna opcja na linię, w formacie wartość|Etykieta (separatorem jest pionowa kreska):

draft|Szkic
issued|Wystawiona
paid|Zapłacona
cancelled|Anulowana

Opcje z zapytania SQL

Zapytanie opcji powinno zwracać kolumny value (wartość do SQL) i label (etykieta). Lista jest ograniczona do 100 opcji, a fraza z wyszukiwarki kontrolki jest dostępna w zapytaniu jako @SEARCH (pusta fraza = wartość pusta — obsłuż ją przez coalesce).

WażneW zapytaniu opcji nie używaj tokenów kontekstowych takich jak {TENANT_ID} czy {CONTID} — w torze opcji rozwiązują się wyłącznie {TODAY}, {NOW} i {CURRENT_MONTH}; inny token zostanie w SQL dosłownie i zapytanie zakończy się błędem. Filtrować po organizacji też nie trzeba: dane na wewnętrznej bazie są ograniczane do Twojego tenanta automatycznie.

PostgreSQL — słownik kategorii z wyszukiwarką:

SELECT id AS value, nazwa AS label
FROM products.product_categories
WHERE nazwa ILIKE '%' || coalesce((@SEARCH)::text, '') || '%'
ORDER BY nazwa

MSSQL — to samo w T-SQL. Zapytanie opcji wykonuje się na tej samej bazie co raport, więc raport na WAPRO pobiera opcje prosto z WAPRO:

SELECT k.id_kontrahenta AS value, k.nazwa AS label
FROM dbo.kontrahent k
WHERE k.nazwa LIKE '%' + COALESCE(@SEARCH, '') + '%'
ORDER BY k.nazwa

Ważne@SEARCH możesz użyć w zapytaniu opcji tylko raz. Jeśli chcesz szukać w kilku kolumnach, sklej je wcześniej w jedno wyrażenie (np. nazwa || ' ' || kod ILIKE ...).

Kaskadowanie (lista zależna)

W polu Zależy od parametrów wskaż parametr nadrzędny, a w zapytaniu opcji użyj jego wartości jak zwykłego parametru. Dzięki [[ ]] lista działa też, zanim użytkownik wybierze nadrzędny:

SELECT id AS value, nazwa AS label
FROM products.product_categories
WHERE 1 = 1
  [[ AND parent_id = @kategoria ]]
ORDER BY nazwa

8Lista wielokrotna

Użytkownik zaznacza wiele wartości. W SQL piszesz kolumna IN @statusybez nawiasów. System sam rozwinie parametr do listy (wartość1, wartość2, …), każda wartość bindowana osobno. Definicja opcji (statyczne / SQL / @SEARCH / kaskadowanie) działa dokładnie jak w Liście wyboru.

PostgreSQL:

SELECT numer, status, wartosc_netto
FROM sales.sales_invoices
WHERE tenant_id = {TENANT_ID}
  [[ AND status IN @statusy ]]

MSSQL:

SELECT d.numer, d.typ_dokumentu, d.wartosc_netto
FROM dbo.dokument_handlowy d
WHERE 1 = 1
  [[ AND d.typ_dokumentu IN @typy ]]

WażneNiewymaganą listę wielokrotną zawsze obejmuj klauzulą [[ ]]. Warunek IN @lista stojący poza klauzulą przy braku zaznaczenia rozwija się do IN (NULL) — czyli raport zwróci zero wierszy, co wygląda jak błąd danych, a jest skutkiem pustego filtra.

9Miesiąc

Kontrolka wyboru miesiąca. Do SQL trafia zawsze pierwszy dzień wybranego miesiąca (np. „sierpień 2026" → 2026-08-01) — warunek pisz więc „na cały miesiąc":

PostgreSQL — najprościej przez date_trunc:

SELECT numer, data_wystawienia, wartosc_netto
FROM sales.sales_invoices
WHERE tenant_id = {TENANT_ID}
  AND date_trunc('month', data_wystawienia) = @miesiac

Na bardzo dużych tabelach szybszy jest zapis przedziałowy (pozwala użyć indeksu na kolumnie daty):

WHERE data_wystawienia >= @miesiac
  AND data_wystawienia < (@miesiac)::date + INTERVAL '1 month'

MSSQL — starsze wersje SQL Servera nie mają date_trunc, uniwersalny jest zapis przedziałowy z DATEADD:

SELECT d.numer, d.data_dokumentu, d.wartosc_netto
FROM dbo.dokument_handlowy d
WHERE d.data_dokumentu >= @miesiac
  AND d.data_dokumentu < DATEADD(MONTH, 1, @miesiac)

WskazówkaW polu Wartość domyślna parametru typu Miesiąc (i Drzewo miesięcy) wpisz token {CURRENT_MONTH} — raport zawsze wystartuje z bieżącym miesiącem. Token działa wyłącznie w tym polu; użyty w treści SQL zakończy się błędem „nieznany token".

10Drzewo miesięcy + SQL zakresu danych

Rozbudowany wariant filtra miesiąca: użytkownik dostaje rozwijane drzewo rok → miesiące i jednym kliknięciem wybiera miesiąc. Nagłówek roku nie jest opcją — zawsze wybierasz jeden konkretny miesiąc (rok pokazuje tylko, ile miesięcy z danymi zawiera). Wartość i warunki SQL są identyczne jak w typie Miesiąc (§9): pierwszy dzień miesiąca, date_trunc na PostgreSQL, przedział z DATEADD na MSSQL.

Po co „SQL zakresu danych"

Domyślnie drzewo pokazuje 5 lat wstecz od dziś — także miesiące, w których nie ma żadnych danych. Pole SQL zakresu danych (opcjonalnie) w definicji parametru pozwala to ograniczyć: podajesz zapytanie zwracające jeden wiersz z pierwszym i ostatnim okresem, w którym są dane (kolumny min i max), a drzewo wyszarza miesiące spoza tego zakresu. Użytkownik od razu widzi, które okresy mają sens.

PostgreSQL — zakres z faktur (dane ograniczają się do Twojej organizacji automatycznie, warunku po tenancie nie dopisujesz):

SELECT MIN(data_wystawienia) AS min,
       MAX(data_wystawienia) AS max
FROM sales.sales_invoices

MSSQL — zakres z dokumentów handlowych WAPRO:

SELECT MIN(d.data_dokumentu) AS min,
       MAX(d.data_dokumentu) AS max
FROM dbo.dokument_handlowy d

WskazówkaW SQL zakresu — inaczej niż w zapytaniu opcji — działają tokeny encji: w raporcie przypiętym do karty kontrahenta możesz zawęzić zakres do dokumentów tego kontrahenta, np. WHERE contractor_id = {CONTID}. Wtedy każdy klient widzi w drzewie tylko „swoje" miesiące. Działają też {TODAY}, {NOW} i {CURRENT_MONTH}; token {TENANT_ID} i parametry @kod innych filtrów nie są tu dostępne.

UwagaZakres danych możesz zdefiniować także dla typów Miesiąc, Data, Data i czas oraz Zakres dat — kalendarze wyszarzą wtedy okresy spoza min/max tak samo jak drzewo miesięcy.

11Zakres dat

Jedna kontrolka „od–do" z podręcznymi presetami (bieżący miesiąc, kwartał, rok…). W SQL używasz jednego placeholdera w stałej pozycji: kolumna BETWEEN @zakres — system sam rozwinie go do pary „data od AND data do". Nie piszesz osobnych parametrów @od/@do i nie rozdzielasz ich własnym AND.

PostgreSQL:

SELECT numer, data_wystawienia, wartosc_netto
FROM sales.sales_invoices
WHERE tenant_id = {TENANT_ID}
  AND data_wystawienia BETWEEN @zakres

MSSQL:

SELECT d.numer, d.data_dokumentu, d.wartosc_netto
FROM dbo.dokument_handlowy d
WHERE d.data_dokumentu BETWEEN @zakres

Ważne@zakres działa wyłącznie bezpośrednio po słowie BETWEEN — w innym miejscu zapytania rozwinięta para wartości nie złoży się w poprawną składnię. Gdy kolumna zawiera datę z godziną, porównuj samą datę, inaczej ostatni dzień zakresu obejmie tylko północ: PostgreSQL — data_utworzenia::date BETWEEN @zakres, MSSQL — CAST(d.data_utworzenia AS date) BETWEEN @zakres.

12Kompletny przykład — od definicji do SQL

Przykład 1 — sprzedaż wg produktów (PostgreSQL, baza Veloryn)

Cel: miesięczny raport sprzedaży wg produktów z filtrem kategorii i szukaniem po nazwie.

Parametry (zakładka „Filtry i parametry"):

KodNazwaTypWymaganyUstawienia
miesiacMiesiącDrzewo miesięcytakWartość domyślna: {CURRENT_MONTH}; SQL zakresu danych jak w §10
kategorieKategorieLista wielokrotnanieOpcje SQL ze słownika kategorii (§7), z @SEARCH
frazaNazwa produktuTekstnie

Zapytanie raportu:

SELECT p.nazwa            AS produkt,
       COUNT(*)           AS liczba_pozycji,
       SUM(i.wartosc_netto) AS sprzedaz_netto
FROM sales.invoice_items i
JOIN sales.sales_invoices f ON f.id = i.invoice_id
JOIN products.products p    ON p.id = i.product_id
WHERE f.tenant_id = {TENANT_ID}
  AND f.data_wystawienia >= @miesiac
  AND f.data_wystawienia < (@miesiac)::date + INTERVAL '1 month'
  [[ AND p.category_id IN @kategorie ]]
  [[ AND p.nazwa ILIKE '%' || @fraza || '%' ]]
GROUP BY p.nazwa
ORDER BY sprzedaz_netto DESC

Użytkownik zawsze wybiera miesiąc (parametr wymagany, startuje z bieżącym), a kategorie i frazę może zostawić puste — te warunki po prostu znikną z zapytania.

Przykład 2 — ten sam raport na WAPRO (MSSQL, połączenie integracyjne)

Identyczne definicje parametrów; zmienia się tylko dialekt zapytania. Opcje listy kategorie również czytasz z WAPRO (zapytanie opcji wykonuje się na bazie raportu):

SELECT a.nazwa               AS produkt,
       COUNT(*)              AS liczba_pozycji,
       SUM(p.wartosc_netto)  AS sprzedaz_netto
FROM dbo.pozycja_dokumentu p
JOIN dbo.dokument_handlowy d ON d.id_dokumentu = p.id_dokumentu
JOIN dbo.artykul a           ON a.id_artykulu = p.id_artykulu
WHERE d.data_dokumentu >= @miesiac
  AND d.data_dokumentu < DATEADD(MONTH, 1, @miesiac)
  [[ AND a.id_kategorii IN @kategorie ]]
  [[ AND a.nazwa LIKE '%' + @fraza + '%' ]]
GROUP BY a.nazwa
ORDER BY sprzedaz_netto DESC

Zapytanie opcji dla kategorie (T-SQL): SELECT id_kategorii AS value, nazwa AS label FROM dbo.kategoria_artykulu WHERE nazwa LIKE '%' + COALESCE(@SEARCH, '') + '%' ORDER BY nazwa. Nazwy tabel są poglądowe — sprawdź je w zakładce Schemat bazy danych swojego połączenia.

13Najczęstsze błędy przy filtrach

ObjawPrzyczynaRozwiązanie
Filtr widoczny, wynik bez zmianW SQL brak @kod parametruDopisz warunek z @kod (niewymagany — w [[ ]]).
Błąd składni po wyczyszczeniu filtraParametr niewymagany poza klauzulą [[ ]]Obejmij cały warunek: [[ AND kolumna = @kod ]].
Pusta lista wielokrotna = pusty raportIN @lista poza [[ ]] rozwija się do IN (NULL)Niewymagane listy wielokrotne zawsze w [[ ]].
Dziwne fragmenty :rp_… w błędzie SQLKod parametru jest przedrostkiem innego kodu (np. rok i rok_od)Zmień nazwy tak, by żaden kod nie zaczynał innego (§1).
Zakres dat: błąd składni przy @zakresPlaceholder użyty poza pozycją BETWEEN @zakresPisz dokładnie kolumna BETWEEN @zakres (§11).
Zakres dat gubi ostatni dzieńKolumna z godziną porównywana wprostPorównuj datę: kolumna::date BETWEEN @zakres / CAST(kolumna AS date) BETWEEN @zakres.
Raport na MSSQL: błąd przy CURRENT_DATEToken {TODAY} w zapytaniu T-SQLUżyj {NOW} albo CAST(GETDATE() AS date) (§1).
Miesiąc „nie łapie" żadnych wierszyPorównanie kolumna = @miesiac (dzień, nie miesiąc)Warunek na cały miesiąc: date_trunc / przedział z DATEADD (§9).
Lista opcji zwraca błąd przy otwarciu{TENANT_ID}/{CONTID} w zapytaniu opcjiW torze opcji rozwiązują się tylko {TODAY}/{NOW}/{CURRENT_MONTH}; filtr organizacji jest automatyczny (§7).
Wyszukiwarka listy nie działa@SEARCH użyty dwa razy albo brak coalesce dla pustej frazyJedno użycie @SEARCH + coalesce((@SEARCH)::text, '') (§7).
Lista statyczna pusta lub „sklejona"Zły separator opcji (dwukropek, przecinek)Format wartość|Etykieta, jedna opcja na linię (§7).
Błąd „nieznany token" mimo poprawnego SQL{CURRENT_MONTH} wpisany w treści zapytaniaToken działa tylko w polu „Wartość domyślna" (§9).