Recorrer las relaciones con consultas de grafos
Algunas relaciones de datos se representan naturalmente como redes, incluidas las conexiones sociales, las jerarquías organizativas, las recomendaciones de productos y los patrones de detección de fraudes. Aunque puede modelar estas relaciones mediante claves externas y combinaciones, las consultas de grafos mediante el MATCH operador proporcionan una manera más intuitiva y a menudo más eficaz de atravesar los datos conectados.
Visualización de estructuras de datos de grafos
Antes de escribir consultas de grafos, ayuda a visualizar cómo se organizan los datos del grafo. Considere una red social sencilla donde las personas se conocen entre sí y compran productos:
En este modelo:
- Los nodos (cuadros) representan entidades como personas y productos
- Los bordes (flechas) representan relaciones entre nodos. La dirección de la flecha indica el sentido de la relación (Alice conoce a Bob, no necesariamente él conoce a Alice).
Nota:
En este diagrama se muestran los conceptos del grafo. Los ejemplos de código de esta unidad usan datos similares pero simplificados para centrarse en características específicas.
Descripción de las funcionalidades del grafo
Las funcionalidades del grafo amplían el modelo relacional con tablas perimetrales y nodos dedicados. Los nodos representan entidades como personas, productos y ubicaciones. Los bordes representan relaciones entre ellos, como "conoce", "comprado" o "ubicado en".
La ventaja clave de las consultas de grafos es la coincidencia de patrones. En lugar de escribir combinaciones complejas de múltiples vías, expresas el patrón que buscas mediante una sintaxis de estilo 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);
Nota:
Las tablas de grafos son totalmente compatibles con las características relacionales existentes. Puede combinar tablas de grafos con tablas normales, usar índices y aplicar todas las operaciones estándar de T-SQL.
Creación de tablas de nodos
Las tablas de nodo almacenan entidades en el grafo. Créelos utilizando CREATE TABLE con la cláusula AS NODE:
-- 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 agrega automáticamente una $node_id columna a las tablas de nodos que identifican de forma única cada nodo. El sistema usa esta columna internamente para las relaciones de grafos.
En el ejemplo siguiente se insertan cuatro personas en la tabla de personas y, a continuación, se consulta la tabla para mostrar tanto las columnas de negocio como las generadas por el sistema $node_id. Observe que la instrucción INSERT solo usa las columnas definidas por el usuario. SQL Server genera automáticamente $node_id para cada fila:
-- 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;
Creación de tablas de bordes
Las tablas perimetrales representan relaciones entre nodos. Créelas usando CREATE TABLE con la cláusula AS EDGE.
-- 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 añade automáticamente las columnas $edge_id, $from_id, y $to_id a las tablas de vínculos. Puede insertar bordes especificando los $from_id valores y $to_id de los nodos conectados, de la siguiente manera:
-- 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;
Sugerencia
Las tablas perimetrales pueden almacenar propiedades sobre la propia relación, como fechas, pesos o tipos. Esto es útil para el análisis temporal o los algoritmos de gráfico ponderados.
Consulta de gráficos con la cláusula MATCH
La MATCH cláusula usa una sintaxis de patrón para especificar las relaciones que desea buscar. El patrón básico usa flechas para mostrar la dirección de la relación:
-- 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 dirección de la flecha importa:
-
(Node1)-(Edge)->(Node2): Edge va de Node1 a Node2 -
(Node1)<-(Edge)-(Node2): Edge va de Node2 a Node1
En el ejemplo siguiente se encuentran todas las personas que conocen a 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';
Recorrer varias relaciones
Las consultas de un solo salto buscan conexiones directas, pero las bases de datos de grafos se destacan en los recorridos de varios saltos. Puede encadenar varios patrones de borde en una sola cláusula MATCH para recorrer varias relaciones. Esta funcionalidad le permite responder a preguntas como "¿quiénes son los amigos de mis amigos?" o "¿qué productos adquirieron mis compañeros?" sin escribir subconsultas anidadas complejas.
En el ejemplo siguiente se buscan amigos de amigos mediante el encadenamiento de dos relaciones KNOWS. El patrón Person1-(k1)->Person2-(k2)->Person3 comienza en Person1, sigue un borde KNOWS a Person2 y, a continuación, sigue otro borde KNOWS para llegar a 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
También puede combinar diferentes tipos de relación en un solo recorrido. En el ejemplo siguiente se cruzan los bordes KNOWS a PURCHASED para encontrar qué productos compraron las personas que conoce una persona determinada:
-- 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;
Importante
Cada alias de tabla perimetral solo puede aparecer una vez en un único MATCH patrón. Para recorrer varias veces el mismo tipo de arista, use alias independientes.
Uso SHORTEST_PATH para recorridos de longitud variable
Puede usar SHORTEST_PATH para buscar la conexión más corta entre un número variable de relaciones. La FOR PATH palabra clave marca las tablas que participan en la coincidencia de longitud variable y cuantificadores como + (uno o más) o {1,3} (uno a tres) controlan la profundidad de recorrido.
En el ejemplo siguiente se busca a todas las personas a las que se puede acceder desde Alice en tres saltos y se cuenta la distancia a cada una:
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';
Elección entre los enfoques relacionales y gráficos
Las consultas de grafos no siempre son la mejor opción. Tenga en cuenta estas directrices al decidir entre los enfoques relacionales tradicionales y gráficos:
Use consultas de grafos cuando:
- Las relaciones son el enfoque principal de las consultas.
- Debes recorrer profundidades variables o desconocidas (amigos de amigos de amigos)
- Los datos forman naturalmente una red (gráficos sociales, jerarquías, rutas)
- Los patrones de consulta requerirían muchas autocombinaciones en SQL relacional
- Está realizando análisis de búsqueda de rutas o de conectividad
Use consultas relacionales cuando:
- Las relaciones son simples y de profundidad fija (relación padre-hijo con un nivel)
- Está filtrando y agregando atributos de entidad principalmente
- El modelo de datos es principalmente tabular con pocas relaciones
- El rendimiento es crítico y los índices de las claves externas son suficientes.
- El equipo está más familiarizado con los patrones de SQL tradicionales
Solución de problemas de los desafíos comunes de las consultas de grafos
Las consultas de Graph tienen requisitos de sintaxis únicos que pueden provocar errores. En la tabla siguiente se describen los desafíos comunes y cómo resolverlos.
| Desafío | Causa | Solución |
|---|---|---|
| La consulta no devuelve ningún resultado | La dirección de las flechas no coincide con cómo se insertaron los bordes en el patrón MATCH |
Compruebe cómo se insertaron los bordes. Si $from_id es Employee y $to_id es Administrador, la flecha debe apuntar de Employee a Manager. |
| Error de sintaxis con borde repetido | Mismo alias de borde usado varias veces en un patrón MATCH |
Cree alias separados para cada tránsito del mismo tipo de arista. |
SHORTEST_PATH error de consulta |
Tablas perimetrales y de nodo no marcadas con FOR PATH |
Agregue FOR PATH una palabra clave a todas las tablas que participan en la coincidencia de longitud variable. |
| Edge hace referencia a nodos inexistentes | En lugar de valores de $node_id, se usan columnas de claves empresariales |
Use subconsultas para seleccionar $node_id de las tablas de nodos al insertar bordes. |
Nota:
Las tablas de grafos y el MATCH operador están disponibles en SQL Server 2017 y versiones posteriores, y Azure SQL Database. La SHORTEST_PATH función requiere SQL Server 2019 o posterior. Consulte la documentación de la plataforma para obtener una disponibilidad específica de características.
Para obtener más información sobre las características del grafo, vea Procesamiento de grafos con SQL Server y MATCH (Transact-SQL).