Filtrowanie i agregowanie danych grafu w Microsoft Fabric

Filtrowanie powoduje zawężenie wyników do wierszy, które mają znaczenie. Agregacja podsumowuje te wiersze w liczby, sumy i średnie. W tym artykule pokazano, jak zastosować obie techniki w zapytaniach GQL względem grafu w Microsoft Fabric.

W przykładach użyto przykładowego zestawu danych sieci społecznościowej. Szczegółowe wyjaśnienie przepływu zapytań i instrukcji można znaleźć w przewodniku językowym GQL.

Użyj tego artykułu do filtrowania wierszy i wzorców, agregacji grupowanej i niegrupowanej, filtrów specyficznych dla agregatu oraz routingu warunkowego. Aby tworzyć wzorce wieloprzeskokowe i wybierać ścieżki, zobacz Pisanie zapytań wzorców grafowych. Informacje o przykładowych zadaniach biznesowych, które można łatwo dostosować, znajdują się w sekcji Tworzenie typowych zapytań GQL.

Wymagania wstępne

Filtrowanie wierszy za pomocą filtru

Użyj polecenia FILTER , aby zachować tylko wiersze spełniające warunek. Umieść FILTER po MATCH, aby zawęzić dopasowane wyniki.

Następujące zapytanie zwraca wszystkie kobiety z ich nazwiskiem i urodzinami:

MATCH (p:Person)
FILTER p.gender = 'female'
RETURN p.firstName, p.lastName, p.birthday

Połącz wiele warunków z AND i OR. Na przykład następujące zapytanie zwraca nazwy wszystkich kobiet urodzonych przed 1990 r.:

MATCH (p:Person)
FILTER p.gender = 'female' AND p.birthday < 19900101
RETURN p.firstName, p.lastName

Wskazówka

Użyj wbudowanej klauzuli WHERE, gdy warunek definiuje, który węzeł lub krawędź może brać udział w dopasowaniu. Używaj FILTER, jeśli warunek dotyczy wiersza utworzonego przez wcześniejszą instrukcję. Umiejscowienie predykatów może zmienić wyniki wyznaczania najkrótszej ścieżki; zobacz Umieść predykaty przed lub po wyborze ścieżki.

Filtrowanie podczas dopasowywania wzorca

Klauzule włożone WHERE wewnątrz wzorca MATCH ograniczają, które węzły i krawędzie kwalifikują się do dopasowania. Optimalizator zapytań może stosować równoważne predykaty podczas skanowania, więc składnia inline nie jest z natury szybsza niż osobna FILTER. Wybierz formę wyrażającą zamierzoną semantykę.

Aby na przykład znaleźć osoby urodzone przed 1994 r. wraz z firmą, w której pracują, ograniczając wyniki do firm, których nazwa zaczyna się od "A":

MATCH (p:Person WHERE p.birthday < 19940101)-[:workAt]->(c:Company WHERE c.name STARTS WITH 'A')
RETURN p.firstName, p.lastName, c.name

Filtruj właściwości krawędzi w taki sam sposób. Aby na przykład zwrócić tylko osoby, które rozpoczęły pracę w firmie w 2000 roku lub nowszym:

MATCH (p:Person)-[w:workAt WHERE w.workFrom >= 2000]->(c:Company)
RETURN p.firstName, p.lastName, c.name, w.workFrom

Aby uzyskać więcej informacji na temat wyboru między filtrowaniem inline a post-match, zobacz Optymalizacja wydajności zapytań GQL.

Obsługa wartości null w filtrach

GQL używa trójwartościowej logiki: predykaty przyjmują wartość TRUE, FALSE lub UNKNOWN. Gdy wartość właściwości ma wartość null, porównania zwracają wartość UNKNOWN. FILTER uznaje UNKNOWN za niezgodny, więc wiersz jest wykluczony.

Użyj IS NULL i IS NOT NULL , aby jawnie przetestować wartości null:

-- Only include people whose browser is known
MATCH (p:Person)
FILTER p.browserUsed IS NOT NULL
RETURN p.firstName, p.browserUsed

Użyj coalesce(), aby zastąpić wartość domyślną, gdy właściwość może być pusta.

MATCH (p:Person)
RETURN p.firstName, coalesce(p.browserUsed, 'Unknown browser') AS browser

Caution

NULL = NULL daje wynik UNKNOWN, a nie TRUE. Zawsze używaj IS NULL do testowania wartości pustych, a nie równości.

Agregowanie wyników za pomocą funkcji RETURN

Użyj funkcji agregujących w RETURN, aby podsumować wyniki. Graf obsługuje następujące funkcje agregatywne: COUNT, , SUMAVG, MIN, MAX, COLLECT_LIST, COLLECT_ONE, oraz COLLECT_ELEMENTS.

Aby na przykład zliczyć wszystkie osoby na wykresie:

MATCH (p:Person)
RETURN count(*) AS totalPeople

Aby zliczyć unikalne wartości, takie jak liczba różnych firm zatrudniających osoby:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN count(DISTINCT c) AS companyCount

Filtrowanie wejściowe dla jednego agregatu

Dodaj FILTER (WHERE predicate) po agregacie, aby filtrować tylko dane wejściowe. Inne agregaty w tym samym RETURN nadal otrzymują wszystkie wiersze wejściowe.

MATCH (p:Person)
RETURN count(*) AS allPeople,
       count(*) FILTER (WHERE p.birthday < 19900101) AS peopleBornBefore1990

Dodaj LIMIT wewnątrz filtra agregującego, aby użyć co najwyżej tylu wierszy spełniających kryteria. Zapytanie stosuje predykat przed limitem specyficznym dla agregatu.

MATCH (p:Person)
RETURN count(*) FILTER (WHERE p.birthday < 19900101 LIMIT 100) AS sampleCount

Specyficzne dla agregatu FILTER i LIMIT nie usuwają wierszy z reszty zapytania. Użyj instrukcji FILTER lub klauzuli WHERE na poziomie dopasowania, gdy chcesz filtrować strumień wierszy.

Zbierz wartości

Użyj COLLECT_LIST, aby zwrócić jeden element listy dla każdej wartości wejściowej, w tym wartości null. Dodaj DISTINCT, aby usunąć duplikaty.

MATCH (p:Person)
RETURN collect_list(DISTINCT p.browserUsed) AS browsers

COLLECT_ONE zwraca jedną wartość wejściową niebędącą null. Wybrana wartość nie jest deterministyczna, więc używaj jej tylko wtedy, gdy dowolna wartość z grupy jest akceptowalna.

COLLECT_ELEMENTS przyjmuje dane wejściowe będące listami i łączy ich elementy w jedną listę:

MATCH (p:Person)
RETURN collect_elements([p.firstName, p.lastName]) AS names

Bez grupowania kolumn zapytanie agregujące bez wejściowych wierszy zwraca pustą listę z COLLECT_LIST i COLLECT_ELEMENTS, a wartość null z COLLECT_ONE.

Grupuj wyniki za pomocą funkcji GROUP BY

GROUP BY i RETURN służą do grupowania wierszy według wspólnych wartości i obliczania agregatów w każdej grupie. To grupowanie jest odpowiednikiem GQL języka SQL GROUP BY.

Aby na przykład policzyć pracowników na firmę:

MATCH (p:Person)-[:workAt]->(c:Company)
LET companyId = c.id, companyName = c.name
RETURN companyId, companyName, count(*) AS employeeCount
GROUP BY companyId, companyName
ORDER BY employeeCount DESC

Grupuj według wielu kolumn i oblicza kilka agregacji jednocześnie. Na przykład podziel liczbę osób i zakres urodzin według płci i przeglądarki, zwracając 10 najczęściej używanych kombinacji:

MATCH (p:Person)
LET gender = p.gender
LET browser = p.browserUsed
RETURN gender,
       browser,
       count(*) AS personCount,
       min(p.birthday) AS earliestBirthday,
       max(p.birthday) AS latestBirthday
GROUP BY gender, browser
ORDER BY personCount DESC
LIMIT 10

Note

Wszystkie wyrażenia niegregowane w pliku RETURN muszą być wyświetlane w pliku GROUP BY. Wyrażenia, które nie są zawarte w GROUP BY, muszą korzystać z funkcji agregującej.

Sortowanie i ograniczanie zagregowanych wyników

Użyj ORDER BY i LIMIT razem z GROUP BY, aby znaleźć wyniki top-N.

Aby na przykład znaleźć pięć pierwszych miast według liczby mieszkańców:

MATCH (p:Person)-[:isLocatedIn]->(city:City)
LET cityId = city.id, cityName = city.name
RETURN cityId, cityName, count(*) AS residentCount
GROUP BY cityId, cityName
ORDER BY residentCount DESC
LIMIT 5

Important

Umieść ORDER BY przed LIMIT. LIMIT zawsze ma zastosowanie do już posortowanego zestawu wyników.

Wiersze trasowania z instrukcjami warunkowymi

Użyj instrukcji warunkowej, aby przekierować każdy przychodzący wiersz do pierwszej dopasowanej gałęzi. Dane wejściowe mogą pochodzić z dowolnego etapu zapytania, nie tylko z agregacji. Na przykład następujące zapytanie kategoryzuje firmy po obliczeniu liczby pracowników:

MATCH (p:Person)-[:workAt]->(c:Company)
LET companyId = c.id, companyName = c.name
RETURN companyId, companyName, count(*) AS employeeCount
GROUP BY companyId, companyName
NEXT
WHEN employeeCount >= 100u THEN
  RETURN companyId, companyName, employeeCount, 'Large' AS category
WHEN employeeCount >= 10u THEN
  RETURN companyId, companyName, employeeCount, 'Medium' AS category
ELSE
  RETURN companyId, companyName, employeeCount, 'Small' AS category

Gałęzie mogą wykonywać pełne instrukcje zapytań i zagnieżdżone procedury, zamiast tylko zwracać wyrażenia. Poniższy przykład przesyła trzy wiersze wejściowe przez różne kształty rozgałęzień. Jedna gałąź uruchamia MATCH, inna łączy dwa agregaty za pomocą UNION ALL, a następnie agreguje ich wyniki, a gałąź rezerwowa zwraca stałą:

FOR selector IN [1, 2, 3]
RETURN selector
NEXT
WHEN selector = 1 THEN
  MATCH (:Person)-[:knows]->(:Person)
  RETURN count(*) AS total, 'Knows edges' AS category
WHEN selector = 2 THEN {
  MATCH (:Person)-[:workAt]->(:Company)
  RETURN count(*) AS partialCount
  UNION ALL
  MATCH (:Person)-[:studyAt]->(:University)
  RETURN count(*) AS partialCount
  NEXT
  RETURN sum(partialCount) AS total, 'Affiliation edges' AS category
}
ELSE
  RETURN 0u AS total, 'No selected metric' AS category

Silnik zapytań ocenia predykaty w kolejności dla każdego wiersza. Obsługuje tylko pierwszą pasującą gałąź. Jeśli predykat zwraca UNKNOWN, ewaluacja jest kontynuowana w następnej gałęzi. Bez ELSE wiersze, które nie odpowiadają gałęzi WHEN, są pomijane.

Zdania warunkowe różnią się od CASE wyrażeń. Graph obsługuje proste CASE <expression> WHEN <value> wyrażenia do wyboru wartości opartych na równości. Wyszukiwane CASE WHEN <predicate> wyrażenia nie są obsługiwane. Więcej informacji można znaleźć w Instrukcjach warunkowych.