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
| Typ | Kontrolka | Wzorzec w SQL | Szczegóły |
|---|---|---|---|
| Tekst | Pole tekstowe | kolumna ILIKE '%' || @fraza || '%' | §3 |
| Liczba całkowita | Pole liczbowe | kolumna = @rok | §4 |
| Liczba dziesiętna | Pole liczbowe | kolumna >= @prog | §4 |
| Data | Kalendarz | kolumna >= @data_od | §5 |
| Data i czas | Kalendarz z godziną | kolumna >= @od_kiedy | §5 |
| Tak/Nie | Przełącznik | czy_aktywny = @tylko_aktywne | §6 |
| Lista wyboru | Lista z wyszukiwarką | kolumna = @status | §7 |
| Lista wielokrotna | Lista wielu wartości | kolumna IN @statusy (bez nawiasów) | §8 |
| Miesiąc | Wybór miesiąca | date_trunc('month', kolumna) = @miesiac | §9 |
| Drzewo miesięcy | Drzewo rok → miesiąc | jak Miesiąc + SQL zakresu danych | §10 |
| Zakres dat | Od–do z presetami | kolumna 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 @statusy —
bez 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
Cel: miesięczny raport sprzedaży wg produktów z filtrem kategorii i szukaniem po nazwie.
Parametry (zakładka „Filtry i parametry"):
| Kod | Nazwa | Typ | Wymagany | Ustawienia |
|---|---|---|---|---|
miesiac | Miesiąc | Drzewo miesięcy | tak | Wartość domyślna: {CURRENT_MONTH}; SQL zakresu danych jak w §10 |
kategorie | Kategorie | Lista wielokrotna | nie | Opcje SQL ze słownika kategorii (§7), z @SEARCH |
fraza | Nazwa produktu | Tekst | nie | — |
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.
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
| Objaw | Przyczyna | Rozwiązanie |
|---|---|---|
| Filtr widoczny, wynik bez zmian | W SQL brak @kod parametru | Dopisz warunek z @kod (niewymagany — w [[ ]]). |
| Błąd składni po wyczyszczeniu filtra | Parametr niewymagany poza klauzulą [[ ]] | Obejmij cały warunek: [[ AND kolumna = @kod ]]. |
| Pusta lista wielokrotna = pusty raport | IN @lista poza [[ ]] rozwija się do IN (NULL) | Niewymagane listy wielokrotne zawsze w [[ ]]. |
Dziwne fragmenty :rp_… w błędzie SQL | Kod 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 @zakres | Placeholder użyty poza pozycją BETWEEN @zakres | Pisz dokładnie kolumna BETWEEN @zakres (§11). |
| Zakres dat gubi ostatni dzień | Kolumna z godziną porównywana wprost | Porównuj datę: kolumna::date BETWEEN @zakres / CAST(kolumna AS date) BETWEEN @zakres. |
Raport na MSSQL: błąd przy CURRENT_DATE | Token {TODAY} w zapytaniu T-SQL | Użyj {NOW} albo CAST(GETDATE() AS date) (§1). |
| Miesiąc „nie łapie" żadnych wierszy | Poró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 opcji | W 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 frazy | Jedno 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 zapytania | Token działa tylko w polu „Wartość domyślna" (§9). |