Sdílet prostřednictvím


SHORTEST_PATH (Transact-SQL)

Platí pro: SQL Server 2019 (15.x) a novější verze Databáze Azure SQL DatabaseAzure SQL Managed InstanceSQL v Microsoft Fabric

Určuje podmínku hledání grafu, která se prohledává rekurzivně nebo opakovaně. SHORTEST_PATH lze použít uvnitř funkce POZVYHLEDAT s grafovými uzly a hraničními tabulkami v příkazu SELECT.

Transact-SQL konvence syntaxe

Nejkratší cesta

Funkce SHORTEST_PATH umožňuje najít:

  • Nejkratší cesta mezi dvěma danými uzly a entitami
  • Nejkratší cesty pro jeden zdroj
  • Nejkratší cesta z více zdrojových uzlů k více cílovým uzlům.

Jako vstup trvá libovolný vzor délky a vrátí nejkratší cestu, která existuje mezi dvěma uzly. Tuto funkci lze použít pouze uvnitř funkce POZVYHLEDAT. Funkce vrátí pouze jednu nejkratší cestu mezi libovolnými dvěma danými uzly. Pokud existují dvě nebo více nejkratších cest stejné délky mezi libovolnou dvojicí zdrojových a cílových uzlů, vrátí funkce pouze jednu cestu, která byla nalezena jako první během procházení. Vzor libovolné délky lze zadat pouze uvnitř SHORTEST_PATH funkce.

Úplnou syntaxi najdete v POZVYHLEDAT (SQL Graph).

PRO PATH

FUNKCE PATH se musí použít s libovolným názvem uzlu nebo hraniční tabulky v klauzuli FROM, která se účastní libovolného vzoru délky. FUNKCE PATH říká modulu, že uzel nebo hraniční tabulka vrací seřazenou kolekci představující seznam uzlů nebo hran nalezených podél cesty. Atributy z těchto tabulek nelze projektovat přímo v klauzuli SELECT. Aby bylo možné projektovat atributy z těchto tabulek, musí být použity agregační funkce cesty grafu.

Vzor libovolné délky

Tento vzor zahrnuje uzly a hrany, které se musí opakovaně přecházet, dokud:

  • Byl dosažen požadovaný uzel.
  • Je splněn maximální počet iterací, jak je uvedeno ve vzoru.

Podporují se následující dva kvantifikátory vzorů:

  • +: Opakujte vzor 1 nebo vícekrát. Ukončete, jakmile se najde nejkratší cesta.
  • {1,n}: Opakováním vzoru 1 n krát. Ukončete, jakmile se najde nejkratší.

LAST_NODE

funkce LAST_NODE() umožňuje řetězení dvou vzorů pro procházení libovolné délky. Dá se použít ve scénářích, kde:

  • V dotazu se používá více než jeden nejkratší vzor cesty a jeden vzor začíná na posledním uzlu předchozího vzoru.
  • Dva nejkratší vzory cest se sloučí ve stejné LAST_NODE().

Pořadí cest grafu

Pořadí cesty grafu odkazuje na pořadí dat ve výstupní cestě. Pořadí výstupní cesty se vždy spouští v nerekurzivní části vzoru následované uzly a hrany, které se zobrazují v rekurzivní části. Pořadí, ve kterém se graf prochází během optimalizace nebo spouštění dotazů, nemá nic společného s pořadím vytištěným ve výstupu. Podobně směr šipky v rekurzivním vzoru nemá vliv také na pořadí cest grafu.

Agregační funkce cesty grafu

Vzhledem k tomu, že uzly a hrany zapojené do vzoru libovolné délky vrací kolekci (uzlů a okrajů) procházených v této cestě), uživatelé nemůžou atributy přímo promítnou pomocí syntaxe tablename.attributename. V případě dotazů, kde je nutné promítnout hodnoty atributů z průběžných uzlů nebo hraničních tabulek, použijte v cestě agregované funkce cesty grafu: STRING_AGG, LAST_VALUE, SUM, AVG, MIN, MAX a COUNT. Obecná syntaxe pro použití těchto agregačních funkcí v klauzuli SELECT je:

<GRAPH_PATH_AGGREGATE_FUNCTION>(<expression> , <separator>)  <order_clause>

    <order_clause> ::=
        { WITHIN GROUP (GRAPH PATH) }

    <GRAPH_PATH_AGGREGATE_FUNCTION> ::=
          STRING_AGG
        | LAST_VALUE
        | SUM
        | COUNT
        | AVG
         | MIN
        | MAX

STRING_AGG

Funkce STRING_AGG přebírá jako vstup výraz a oddělovač a vrací řetězec. Uživatelé mohou tuto funkci v klauzuli SELECT použít k projektování atributů z zprostředkujících uzlů nebo hran v cestě procházené.

LAST_VALUE

K projektování atributů z posledního uzlu procházení cesty je možné použít LAST_VALUE agregační funkci. Jedná se o chybu při zadávání aliasu hraniční tabulky jako vstupu této funkce, lze použít pouze názvy nebo aliasy tabulek uzlů.

poslední uzel: Poslední uzel odkazuje na uzel, který se zobrazuje naposledy v cestě procházené, bez ohledu na směr šipky v predikáte POZVYHLEDAT. Příklad: MATCH(SHORTEST_PATH(n(-(e)->p)+) ). Poslední uzel v cestě je poslední navštívený uzel P.

V MATCH(SHORTEST_PATH((n<-(e)-)+p)) vzoru je posledním navštívený uzel N.

SUM

Tato funkce vrátí součet zadaných hodnot atributů node/edge nebo výrazu, které se zobrazily v procházené cestě.

COUNT

Tato funkce vrátí počet nenulových hodnot zadaného atributu node/edge v cestě. Funkce COUNT nepodporuje operátor * – pokus o použití * způsobí chybu syntaxe.

{  COUNT( <expression> )  <order_clause>  }

AVG

Vrátí průměr zadaných hodnot atributů uzlu nebo hrany, které se zobrazily v procházené cestě.

MIN

Vrátí minimální hodnotu z zadaných hodnot atributu node/edge nebo výrazu, který se zobrazil v procházené cestě.

MAX

Vrátí maximální hodnotu z zadaných hodnot atributu node/edge nebo výrazu, které se zobrazily v procházené cestě.

Remarks

  • Funkci SHORTEST_PATH lze použít pouze uvnitř funkce POZVYHLEDAT.
  • Funkce LAST_NODE je podporována pouze uvnitř SHORTEST_PATH.
  • Funkce SHORTEST_PATH vrátí libovolnou nejkratší cestu mezi uzly. V současné době nepodporuje vracení všechny nejkratší cesty mezi uzly; Nepodporuje také vracení všechny cesty mezi uzly.
  • Implementace SHORTEST_PATH najde nevážnou nejkratší cestu.
  • V některých případech se pro dotazy s vyšším počtem segmentů směrování můžou vygenerovat chybné plány, což vede k vyšší době provádění dotazů. Vyhodnoťte, jestli nápovědu k dotazům, jako je OPTION (HASH JOIN) nebo OPTION (MAXDOP 1).

Examples

V příkladech zde zobrazených dotazů používáme uzly a hraniční tabulky vytvořené v ukázce SQL Graphu

A. Vyhledání nejkratší cesty mezi dvěma lidmi

V následujícím příkladu najdeme nejkratší cestu mezi Jacobem a Alicí. Potřebujeme uzel Person a hraniční friendOf vytvořený z ukázky SQL Graphu.

SELECT PersonName, Friends
FROM (
    SELECT
        Person1.name AS PersonName,
        STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
        LAST_VALUE(Person2.name) WITHIN GROUP (GRAPH PATH) AS LastNode
    FROM
        Person AS Person1,
        friendOf FOR PATH AS fo,
        Person FOR PATH  AS Person2
    WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
    AND Person1.name = 'Jacob'
) AS Q
WHERE Q.LastNode = 'Alice'

B. Vyhledejte nejkratší cestu z daného uzlu do všech ostatních uzlů v grafu.

Následující příklad najde všechny lidi, ke kterým je Jacob připojen v grafu, a nejkratší cestu počínaje Jacobem ke všem těmto lidem.

SELECT
    Person1.name AS PersonName,
    STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends
FROM
    Person AS Person1,
    friendOf FOR PATH AS fo,
    Person FOR PATH  AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
AND Person1.name = 'Jacob'

C. Spočítejte počet segmentů směrování a úrovní, které se procházejí z jedné osoby do jiného v grafu.

Následující příklad najde nejkratší cestu mezi Jacobem a Alicí a vytiskne počet segmentů směrování, které trvá jít z Jacobu do Alice.

 SELECT PersonName, Friends, levels
FROM (
    SELECT
        Person1.name AS PersonName,
        STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
        LAST_VALUE(Person2.name) WITHIN GROUP (GRAPH PATH) AS LastNode,
        COUNT(Person2.name) WITHIN GROUP (GRAPH PATH) AS levels
    FROM
        Person AS Person1,
        friendOf FOR PATH AS fo,
        Person FOR PATH  AS Person2
    WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
    AND Person1.name = 'Jacob'
) AS Q
WHERE Q.LastNode = 'Alice'

D. Vyhledání lidí 1–3 směrování mimo danou osobu

Následující příklad najde nejkratší cestu mezi Jacobem a všemi lidmi, ke kterým je Jacob připojen v grafu 1 až tři segmenty směrování od něj.

SELECT
    Person1.name AS PersonName,
    STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends
FROM
    Person AS Person1,
    friendOf FOR PATH AS fo,
    Person FOR PATH  AS Person2
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2){1,3}))
AND Person1.name = 'Jacob'

E. Vyhledání přesně dvou segmentů směrování od dané osoby

Následující příklad najde nejkratší cestu mezi Jacobem a lidmi, kteří jsou přesně dva segmenty směrování od něj v grafu.

SELECT PersonName, Friends
FROM (
    SELECT
        Person1.name AS PersonName,
        STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
        COUNT(Person2.name) WITHIN GROUP (GRAPH PATH) AS levels
    FROM
        Person AS Person1,
        friendOf FOR PATH AS fo,
        Person FOR PATH  AS Person2
    WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2){1,3}))
    AND Person1.name = 'Jacob'
) Q
WHERE Q.levels = 2

F. Najděte osoby 1–3 směrování mimo danou osobu, která se také líbí konkrétní restauraci.

Následující příklad najde nejkratší cestu mezi Jacobem a všemi lidmi, ke kterým je v grafu 1-3 směrování daleko. Dotaz také filtruje propojené lidi podle svých představ v dané restauraci. V následující ukázce LAST_NODE(Person2) vrátí konečný uzel pro každou nejkratší cestu. Uzel "poslední" Person získaný z LAST_NODE pak může být "zřetězený" pro další procházení a nalezení restaurací, které se jim líbí.

SELECT
    Person1.name AS PersonName,
    STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
    Restaurant.name
FROM
    Person AS Person1,
    friendOf FOR PATH AS fo,
    Person FOR PATH  AS Person2,
    likes,
    Restaurant
WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2){1,3}) AND LAST_NODE(Person2)-(likes)->Restaurant )
AND Person1.name = 'Jacob'
AND Restaurant.name = 'Ginger and Spice'

G. Vyhledání nejkratší cesty z daného uzlu do všech ostatních uzlů v grafu s výjimkou "smyček"

Následující příklad najde všechny lidi, ke kterým je Alice připojená v grafu, a nejkratší cestu od Alice ke všem těmto lidem. Příklad explicitně kontroluje smyčky, ve kterých je počáteční a koncový uzel cesty stejný.

SELECT PersonName, Friends
FROM (
    SELECT
        Person1.name AS PersonName,
        STRING_AGG(Person2.name, '->') WITHIN GROUP (GRAPH PATH) AS Friends,
        LAST_VALUE(Person2.name) WITHIN GROUP (GRAPH PATH) AS LastNode
    FROM
        Person AS Person1,
        friendOf FOR PATH AS fo,
        Person FOR PATH  AS Person2
    WHERE MATCH(SHORTEST_PATH(Person1(-(fo)->Person2)+))
    AND Person1.name = 'Alice'
) AS Q
WHERE Q.LastNode != 'Alice'

Další kroky