Parcourir les relations avec des requêtes de graphe
Conseil / Astuce
Pour plus d’informations, consultez l’onglet Texte et images !
Certaines relations de données sont naturellement représentées en tant que réseaux, notamment les connexions sociales, les hiérarchies organisationnelles, les recommandations sur les produits et les modèles de détection des fraudes. Bien que vous puissiez modéliser ces relations à l’aide de clés étrangères et de jointures, les requêtes de graphe utilisant l’opérateur MATCH fournissent un moyen plus intuitif et souvent plus efficace de parcourir les données connectées.
Visualiser les structures de données de graphe
Avant d’écrire des requêtes de graphe, il permet de visualiser la façon dont les données de graphe sont organisées. Considérez un réseau social simple où les gens se connaissent et achètent des produits :
Dans ce modèle :
- Les nœuds (zones) représentent des entités telles que des personnes et des produits
- Les arêtes (flèches) représentent les relations entre les nœuds. La direction de la flèche indique la direction de la relation (Alice connaît Bob, pas nécessairement Bob connaît Alice).
Note
Ce diagramme illustre les concepts de graphique. Les exemples de code de cette unité utilisent des données similaires mais simplifiées pour se concentrer sur des fonctionnalités spécifiques.
Comprendre les fonctionnalités de graphe
Les fonctionnalités de graphique étendent le modèle relationnel avec des tables de nœud et de périphérie dédiées. Les nœuds représentent des entités telles que des personnes, des produits et des emplacements. Les arêtes représentent des relations entre eux, telles que « knows », « purchased » ou « located in ».
L’avantage clé des requêtes de graphe est la mise en correspondance des modèles. Au lieu d’écrire des jointures multidirectionnel complexes, vous exprimez le modèle que vous recherchez à l’aide d’une syntaxe de style ASCII :
-- Traditional relational approach (multiple joins)
SELECT p1.Name, p2.Name
FROM Person AS p1
INNER JOIN Friendship AS f ON p1.PersonID = f.Person1ID
INNER JOIN Person AS p2 ON f.Person2ID = p2.PersonID;
-- Graph approach (pattern matching)
SELECT Person1.Name, Person2.Name
FROM Person AS Person1, Friendship, Person AS Person2
WHERE MATCH(Person1-(Friendship)->Person2);
Note
Les tables graphes sont entièrement compatibles avec les fonctionnalités relationnelles existantes. Vous pouvez joindre des tables de graphiques avec des tables régulières, utiliser des index et appliquer toutes les opérations T-SQL standard.
Créer des tables de nœuds
Les tables de nœuds stockent des entités dans votre graphe. Créez-les à l’aide de CREATE TABLE avec la AS NODE clause :
-- Create a Person node table
CREATE TABLE dbo.Person (
PersonID INT PRIMARY KEY,
Name NVARCHAR(100) NOT NULL,
Email NVARCHAR(200),
Department NVARCHAR(50)
) AS NODE;
-- Create a Product node table
CREATE TABLE dbo.Product (
ProductID INT PRIMARY KEY,
Name NVARCHAR(200) NOT NULL,
Category NVARCHAR(100),
Price DECIMAL(10, 2)
) AS NODE;
-- Create a Location node table
CREATE TABLE dbo.Location (
LocationID INT PRIMARY KEY,
City NVARCHAR(100) NOT NULL,
CountryRegion NVARCHAR(100) NOT NULL
) AS NODE;
SQL Server ajoute automatiquement une $node_id colonne aux tables de nœuds qui identifient de manière unique chaque nœud. Le système utilise cette colonne en interne pour les relations de graphe.
L’exemple suivant insère quatre personnes dans la table de nœuds Person, puis interroge la table pour afficher les colonnes métier et le $node_id généré par le système. Notez que l’instruction INSERT utilise uniquement les colonnes définies par l’utilisateur. SQL Server génère $node_id automatiquement pour chaque ligne :
-- Insert person data using standard INSERT syntax
INSERT INTO dbo.Person (PersonID, Name, Email, Department)
VALUES
(1, 'Alice Johnson', 'alice@contoso.com', 'Engineering'),
(2, 'Bob Smith', 'bob@contoso.com', 'Marketing'),
(3, 'Carol Davis', 'carol@contoso.com', 'Engineering'),
(4, 'David Lee', 'david@contoso.com', 'Sales');
-- Query shows the system-generated $node_id alongside user columns
SELECT $node_id, PersonID, Name FROM dbo.Person;
Créer des tables d'arêtes
Les tables edge représentent les relations entre les nœuds. Créez-les à l’aide de CREATE TABLE avec la AS EDGE clause :
-- Create a "reports to" relationship edge
CREATE TABLE dbo.ReportsTo (
StartDate DATE,
ReportType NVARCHAR(50)
) AS EDGE;
-- Create a "purchased" relationship edge
CREATE TABLE dbo.Purchased (
PurchaseDate DATE NOT NULL,
Quantity INT NOT NULL,
TotalAmount DECIMAL(10, 2)
) AS EDGE;
-- Create a "knows" relationship edge (social connection)
CREATE TABLE dbo.Knows (
ConnectionDate DATE,
ConnectionStrength INT -- 1-10 scale
) AS EDGE;
SQL Server ajoute automatiquement les colonnes $edge_id, $from_id, et $to_id aux tables de périphérie. Vous pouvez insérer des arêtes en spécifiant les valeurs $from_id et $to_id des nœuds connectés, comme suit :
-- Alice reports to Bob
INSERT INTO dbo.ReportsTo ($from_id, $to_id, StartDate, ReportType)
SELECT
(SELECT $node_id FROM dbo.Person WHERE Name = 'Alice Johnson'),
(SELECT $node_id FROM dbo.Person WHERE Name = 'Bob Smith'),
'2023-01-15',
'Direct';
-- Create social connections
INSERT INTO dbo.Knows ($from_id, $to_id, ConnectionDate, ConnectionStrength)
SELECT
(SELECT $node_id FROM dbo.Person WHERE Name = 'Alice Johnson'),
(SELECT $node_id FROM dbo.Person WHERE Name = 'Carol Davis'),
'2022-06-01',
8;
Conseil / Astuce
Les tables Edge peuvent stocker des propriétés sur la relation elle-même, telles que les dates, les pondérations ou les types. Cela est utile pour l’analyse temporelle ou les algorithmes de graphe pondérés.
Interroger des graphiques avec la MATCH clause
La MATCH clause utilise une syntaxe de modèle pour spécifier les relations que vous souhaitez rechercher. Le modèle de base utilise des flèches pour afficher la direction des relations :
-- Find who reports to whom
SELECT
Employee.Name AS Employee,
Manager.Name AS Manager,
r.StartDate
FROM dbo.Person AS Employee,
dbo.ReportsTo AS r,
dbo.Person AS Manager
WHERE MATCH(Employee-(r)->Manager);
La direction de la flèche importe :
-
(Node1)-(Edge)->(Node2): Edge passe de Node1 à Node2 -
(Node1)<-(Edge)-(Node2): Edge passe de Node2 à Node1
L’exemple suivant recherche toutes les personnes qui connaissent Alice :
SELECT
Connector.Name AS PersonWhoKnowsAlice,
k.ConnectionStrength
FROM dbo.Person AS Connector,
dbo.Knows AS k,
dbo.Person AS Target
WHERE MATCH(Connector-(k)->Target)
AND Target.Name = 'Alice Johnson';
Parcourir plusieurs relations
Les requêtes à saut unique recherchent des connexions directes, mais les bases de données graphiques excellent dans les traversées multi-sauts. Vous pouvez chaîner plusieurs motifs d'arête dans une clause unique MATCH pour suivre les chemins à travers plusieurs relations. Cette fonctionnalité vous permet de répondre à des questions telles que « qui sont mes amis » ou « quels produits mes collègues ont achetés ? » sans écrire de sous-requêtes imbriquées complexes.
L’exemple suivant recherche des amis d’amis par le chaînage de deux relations KNOWS. Le modèle Person1-(k1)->Person2-(k2)->Person3 commence à Person1, suit un bord KNOWS à Person2, puis suit un autre bord KNOWS pour atteindre Person3 :
-- Find friends of friends (2-hop connections)
SELECT DISTINCT
Person1.Name AS Person,
Person3.Name AS FriendOfFriend
FROM dbo.Person AS Person1,
dbo.Knows AS k1,
dbo.Person AS Person2,
dbo.Knows AS k2,
dbo.Person AS Person3
WHERE MATCH(Person1-(k1)->Person2-(k2)->Person3)
AND Person1.Name = 'Alice Johnson'
AND Person3.Name <> Person1.Name; -- Exclude self
Vous pouvez également combiner différents types de relation dans un seul parcours. L’exemple suivant traverse les arêtes de KNOWS à ACHETÉS pour déterminer quels produits ont été achetés par des personnes qu'une personne donnée connaît.
-- Find products purchased by people in the same department
SELECT DISTINCT
p1.Name AS Person,
p1.Department,
prod.Name AS Product
FROM dbo.Person AS p1,
dbo.Knows AS k,
dbo.Person AS p2,
dbo.Purchased AS pu,
dbo.Product AS prod
WHERE MATCH(p1-(k)->p2-(pu)->prod)
AND p1.Department = p2.Department;
Important
Chaque alias de table de bord ne peut apparaître qu’une seule fois dans un seul MATCH modèle. Pour parcourir le même type de périphérie plusieurs fois, utilisez des alias distincts.
Utiliser SHORTEST_PATH pour les traversées de longueur variable
Vous pouvez utiliser SHORTEST_PATH pour trouver la connexion la plus courte entre un nombre variable de relations. Le FOR PATH mot clé marque les tables qui participent à la correspondance de longueur variable et les quantificateurs comme + (un ou plusieurs) ou {1,3} (un à trois) contrôlent la profondeur de traversée.
L'exemple suivant recherche toutes les personnes accessibles à partir d’Alice en trois sauts et mesure la distance à chacune d'elles :
SELECT
StartPerson.Name,
LAST_VALUE(ReachablePerson.Name) WITHIN GROUP (GRAPH PATH) AS ReachablePerson,
COUNT(ReachablePerson.Name) WITHIN GROUP (GRAPH PATH) AS Distance
FROM dbo.Person AS StartPerson,
dbo.Knows FOR PATH AS k,
dbo.Person FOR PATH AS ReachablePerson
WHERE MATCH(SHORTEST_PATH(StartPerson(-(k)->ReachablePerson){1,3}))
AND StartPerson.Name = 'Alice Johnson';
Choisir entre les approches graphiques et relationnelles
Les requêtes graphes ne sont pas toujours le meilleur choix. Tenez compte de ces instructions lors de la décision entre les approches relationnelles traditionnelles et graphiques :
Utilisez des requêtes de graphe quand :
- Les relations sont le principal objectif de vos requêtes
- Vous devez parcourir des profondeurs variables ou inconnues (amis d’amis d’amis)
- Les données forment naturellement un réseau (graphiques sociaux, hiérarchies, itinéraires)
- Les modèles de requêtes nécessiteraient de nombreuses auto-jointures dans SQL relationnel.
- Vous effectuez une analyse de chemin d’accès ou de connectivité
Utilisez des requêtes relationnelles quand :
- Les relations sont simples et fixes (parent-enfant avec un niveau)
- Vous filtrez et agrégeez principalement les attributs d’entité
- Le modèle de données est principalement tabulaire avec peu de relations
- Les performances sont essentielles et les index sur les clés étrangères sont suffisants.
- Votre équipe est plus familiarisée avec les modèles SQL traditionnels
Résoudre les problèmes courants liés aux requêtes de graphe
Les requêtes Graph ont des exigences de syntaxe uniques qui peuvent entraîner des erreurs. Le tableau suivant décrit les défis courants et comment les résoudre.
| Problème | La cause | Solution |
|---|---|---|
| La requête ne retourne aucun résultat | La direction de la flèche dans MATCH le modèle ne correspond pas à la façon dont les bords ont été insérés |
Vérifiez comment les arêtes ont été insérées. Si $from_id est Employee et $to_id est Manager, la flèche doit pointer d'Employee vers Manager. |
| Erreur de syntaxe avec bord répété | Même alias de périphérie utilisé plusieurs fois dans un MATCH modèle |
Créez des alias distincts pour chaque traversée du même type d'arête. |
SHORTEST_PATH échec de la requête |
Tables de périphérie et de nœud non marquées avec FOR PATH |
Ajoutez un mot clé FOR PATH à toutes les tables participant à la correspondance de longueur variable. |
| Edge fait référence à des nœuds inexistants | Colonnes clés métier utilisées à la place des valeurs $node_id |
Utilisez des sous-requêtes pour sélectionner $node_id dans les tables de nœuds lors de l’insertion d'arêtes. |
Note
Les tables graphes et l’opérateur MATCH sont disponibles dans SQL Server 2017 et versions ultérieures, et Azure SQL Database. La SHORTEST_PATH fonction nécessite SQL Server 2019 ou version ultérieure. Consultez la documentation de votre plateforme pour connaître la disponibilité des fonctionnalités spécifiques.
Pour plus d’informations sur les fonctionnalités de graphe, consultez Traitement graph avec SQL Server et MATCH (Transact-SQL).