Przejdź do głównej zawartości

Zapytania do list


Język zapytań umożliwia proste odpytywanie list (także zagnieżdżonych) o agregaty wartości. Posługuje się w tym celu składnią podobną do tej dostępnej w języku C# - Language Integrated Query.

Ogólna składnia ma postać:

from iterator in lista
[where warunek]
[skip n]
[take n]
select agregacja (iterator::element)
from Clients where [IsActive] select first (Name)
from cl in Clients where cl::[IsActive] select first::(cl::Name)

Poszczególne elementy składni:

  1. Iterator - nazwa nowego drzewa danych deklarowanego na poziomie zapytania, dostępnego tylko wewnątrz, potrzebna w celu zapewnienia jednoznaczności odwołań do danych. Istnieje też składnia uproszczona (from lista …), ale wówczas nie ma możliwości prostego odwołania się do bieżącego drzewa danych, co jest sytuacją występującą chyba najczęściej.
  2. Lista - wyrażenie zwracające jakąś listę rekordów, zwykle w postaci ścieżki wychodzącej od drzewa lokalnego nienazwanego, np. Klienci lub w wariancie bardziej zaawansowanym, wielokrotnie zagnieżdżonym: Klienci\Powiązania\Produkty\Transakcje. Wszystkie elementy z tak zbudowanej listy będą przetwarzane przez pozostałą część wyrażenia.
  3. Warunek - opcjonalne wyrażenie zwracające wymagalną wartość logiczną true/false, filtrujące elementy przetwarzane przez pozostałą część zapytania.
  4. Skip n - opcjonalnie liczba rekordów do pominięcia z początku budowanej listy.
  5. Take n - opcjonalnie liczba elementów do zachowania na początku budowanej listy (w takiej kolejności). Ewentualne następne elementy nie będą brane pod uwagę.
  6. Agregacja (iterator::element) - wywołanie funkcji agregującej na wszystkich elementach zbudowanej listy. Jeśli nie podano funkcji agregującej, wynikiem zapytania będzie pierwszy element tej listy (funkcja agregująca first()). W składni uproszczonej (bez nazywania iteratora) wystarczy nazwa pola pod elementem listy.
ważne

Jeśli wynikiem zapytania będzie struktura (np. cały rekord iteratora oznaczany jako kropka .), funkcja agregująca nie jest stosowana, a wyrażenie zwraca rekord lub listę rekordów. Istnieje też możliwość samodzielnego stworzenia rekordu in-line na podstawie fragmentu odpytywanej struktury danych (patrz kolejny rozdział: Tworzenie rekordu in-line).

Przykłady

Składnia najbardziej uproszczona: from Clients select ID - wybiera pierwsze ID z listy klientów, działanie identyczne z first(Clients\ID)

Przydatność składni zapytań ujawnia się przy stosowaniu warunków i agregacji, np. from Clients where Vip select sum(Dochód)

Najczęściej stosowana jest forma uproszczona ale mamy także formę pełną zapytania.

Forma pełna daje znacznie więcej możliwości gdyż nazywa iteratory, dzięki czemu możemy sięgać i do nich i do kontekstu zewnętrznego. W tym przypadku iterator wygląda jak drzewko danych o nazwie cl, jako skrót od iterowanego rekordu Clients Z kolei ścieżka OpeningDate prowadzi do rekordu głównego z kontekstu danych. Razem pozwala nam to korelować różne dane.

image

Nie ma obowiązku zwracać z takiego zapytania wartości zagregowanych z pojedynczych pól - przykładowo można zwrócić cały pierwszy rekord z iteratora.

from Clients where [IsActive] select first (.)

Można też zwrócić wszystkie rekordy, bez żadnej agregacji, ale za to przefiltrowane.

from Clients where [IsActive] select .

Można też, tak jak w SQL, zbudować sobie i zwrócić całkiem nowy rekord, w tym wypadku zawierający ID klienta, minimalną i maksymalną datę relacji (z zagnieżdżonej w kliencie listy historii relacji), oraz np. pierwszy z brzegu kod operacji z historii operacji.

Tak będzie wtedy wyglądał fragment nowo dodanej struktury danych w drzewku.

from Clients
where [IsActive]
select
{
id = ClientId,
minRelation = min(RelationHistory\Timestamp),
maxRelation = max(RelationHistory\Timestamp),
firstOpCode = first(...\OperationHistory\OperationCode)
}

image

W tego typu zapytaniach mamy też dostępne operatory SKIP i TAKE, do pomijania pierwszych i ograniczania liczności wyniku, podobnie jak w różnych wariantach SQL mamy klauzule OFFSET, TOP, FETCH FIRST itd.

from cl in Clients
where cl::[IsActive]
skip alreadyProcessedCount
take 5
select first (cl::.)
wskazówka

Tego typu wyrażenia nie powodują żadnych zapytań do baz danych, operują wyłącznie na wartościach i listach wczytanych wcześniej.

Gramatyka pozwala na bardzo proste zastosowanie funkcji skalarnej do listy w celu uzyskania listy wartości tej funkcji dla wszystkich argumentów. Wywołujemy funkcję na liście, nawet jeśli nie mamy zdefiniowanego takiego właśnie wariantu funkcji. Jest to bardzo wygodne i nie wymaga stosowania np. rachunku lambda, domknięć czy innych tego typu rzeczy.

Zobacz również​

Brak wartości i specjalne wartości puste

Wymagalne wartości logiczne