Запросы к графовой базе данных

Запросы к графовой базе данных

Восстановить вид исходной таблицы Utb можно с помощью обычного SQL-запроса:

select B.b_datetime, Q.q_id b_q_id, V.v_id b_v_id, B.b_vol
from utbG B join utqG Q on B.$to_id = Q.$node_id
join utvG V on B.$from_id = V.$node_id;

Однако для облегчения навигации по графу в SQL Server добавлена функция MATCH, которая задает шаблон для поиска узлов в соответствии со связями. Синтаксис шаблона напоминает образцы, используемые в языке Cypher, графовой базы данных Neo4j.

В упрощенной форме шаблон имеет вид:

<узел, откуда исходит ребро> - (<ребро>) -> <узел, в который входит ребро>

Узел представляется именем таблицы или алиасом (псевдонимом). Алиас необходим, когда одна таблица используется в образце несколько раз, например, в случае самосоединений.  Шаблоны в функции MATCH можно соединять при помощи оператора AND. Перейдем к примерам. Для начала перепишем предыдущий запрос в «графовом» стиле:

select B.b_datetime, Q.q_id b_q_id, V.v_id b_v_id, B.b_vol
from utbG B, utqG Q, utvG V
where match(V-(B)->Q);

Здесь мы используем алиасы только для сокращения записи. Мы можем поменять местами узлы, но направление связи должно сохраниться (от баллончика к квадрату):

select B.b_datetime, Q.q_id b_q_id, V.v_id b_v_id, B.b_vol
from utbG B, utqG Q, utvG V
where match(Q<-(B)-V);

В отличие от Cypher направление связи является обязательным, т.е. использование функции

match(V-(B)-Q);

будет вызывать ошибку. Cypher более гибок в этом отношении; направление можно не указывать, если оно может быть однозначно определено, например, если связь данного типа есть в одном направлении, но нет в другом.

Найти квадраты, которые окрашивались красной краской. Вывести идентификатор квадрата и объем красной краски.

Реляционная схема

Select b_q_id, SUM(b_vol) qty
from utB join utV on B_V_ID =V_ID
where V_COLOR ='R'
group by b_q_id;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Графовая схема

Select q_id, SUM(b_vol) qty
from utbG B, utvG V, utqG Q
where match(V-(B)->Q) AND V_COLOR ='R'
group by q_id;
Найти квадраты, которые окрашивались как красной, так и синей краской. Вывести: название квадрата.

Реляционная схема

select q_name from utQ join (
select b_q_id from utB join utV on B_V_ID =V_ID
where V_COLOR ='R'
intersect
select b_q_id from utB join utV on B_V_ID =V_ID
where V_COLOR ='B'
) X on Q_ID=b_q_id;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Графовая схема

select distinct q_name
from utbG B1,utbG B2, utvG VR, utvG VB, utqG Q
where
match(VR-(B1)->Q<-(B2)-VB) AND VR.V_COLOR ='R' AND VB.V_COLOR ='B';

Обратите внимание, что для в общем случае разных узлов, используемых в шаблоне, требуется добавлять соответствующую таблицу в предложение FROM (как и таблицу связи). Если же подразумевается один и тот же узел, как в нашем случае с квадратом, то мы можем использовать этот узел для двусторонней связи. Предикат

match(VR-(B1)->Q<-(B2)-VB)

можно было также записать в таком виде

match(VR-(B1)->Q) AND match(VB-(B2)->Q)

или в таком

match(VR-(B1)->Q AND VB-(B2)->Q)

DISTINCT в этих запросах необходим, поскольку возможны дубликаты, если квадрат окрашивался несколькими красными (и/или синими) баллончиками.

Найти квадраты, которые окрашивались всеми тремя цветами.

Реляционная схема

Можно было бы добавить еще один запрос к предыдущему решению с помощью INTERSECT, однако давайте представим здесь более эффективное решение, опирающееся на тот факт, что количество уникальных цветов, которыми окрашивался квадрат, равно 3:

select q_name from utQ join (
select b_q_id
from utB join utV on B_V_ID =V_ID
group by b_q_id
having count(distinct v_color)=3
) X on q_id=b_q_id;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Графовая схема

select distinct Q.q_name
from utbG B1,utbG B2,utbG B3, utvG VR, utvG VB, utvG VG, utqG Q
where
match(VR-(B1)->Q<-(B2)-VB and VG-(B3)->Q)
AND VG.V_COLOR ='G' AND VR.V_COLOR ='R' AND VB.V_COLOR ='B';
Найти баллончики, которыми окрашивали более одного квадрата.

Реляционная схема

select v_name from
utB join utV on B_V_ID =V_ID
group by b_v_id,v_name
having count(distinct b_q_id)>1;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Графовая схема

select distinct v_name
from utbG B1,utbG B2, utvG V, utqG Q,utqG Q2
where
match(Q2<-(B2)-V-(B1)->Q) and Q.q_id <> Q2.q_id;

Условие match(Q2<-(B2)-V-(B1)->Q) утверждает, что один баллон участвовал в двух окрасках, в то время как условие Q.q_id <> Q2.q_id говорит о том, что при этом окрашивались разные квадраты.

Предварительные выводы

На первый взгляд, запросы к реляционной и графовой схемам не так уж радикально отличаются. Более того, синтаксиса графовой базы данных можно не придерживаться, оставаясь в рамках языка SQL. Однако не стоит судить по рассмотренным примерам, поскольку преимущество графовых баз данных проявляется для тех предметных областей, которые характеризуются сложными связями между данными.