简体   繁体   中英

SQL neatly self join a table n times

I'm building a back-end for a project to construct a (purely functional) graph database system.

One operation I'm trying to implement is self joining a precomputed view to itself exactly n times (ie finding pairs of results that are exactly n instances of a particular relation away from each other in the graph)

A slightly ugly solution I've come up with is generating a big tree of joins in a style similar to exponentiation by squaring

Is there a neater/better way to do this? Perhaps using recursive queries?

Each possible pre-generated view has a left_id and right_id field, which represent indices into entity tables.

A simplified example is the following:

Given the following table representing part of the relation n -> succ(n) (in reality the relation may be much more complicated)

left_id | right_id
__________________
   1    |    2
   2    |    3
   3    |    4
   4    |    5
   5    |    6
   7    |    8

The ideal result of querying with n = 3 would be

left_id | right_id
__________________
   1    |    4
   2    |    5
   3    |    6
   4    |    7
   5    |    8

(An explanation of why I'm using SQL is that one part of this project is to demonstrate that SQL is a poor choice for such a system, followed by a more bespoke backend to solve the issues with using an underlying relational as opposed to a graph model)

Many databases support recursive CTEs, which directly support such graph walking.

Even in databases that do not, this is not particularly difficult, using dynamic SQL and a WHERE clause:

For n = 1:

select t1.left_id, t2.right_id
from t t1 join
     t t2
     on t2.left_id = t1.right_id;

For n = 2:

select t1.left_id, t3.right_id
from t t1 join
     t t2
     on t2.left_id = t1.right_id join
     t t3
     on t3.left_id = t2.right_id;

For n = 3:

select t1.left_id, t4.right_id
from t t1 join
     t t2
     on t2.left_id = t1.right_id join
     t t3
     on t3.left_id = t2.right_id join
     t t4
     on t4.left_id = t3.right_id;

Each additional value of "n" adds another join condition. These queries can readily take advantage of an index on the table, so performance should be reasonable.

Whether this is better or worse than graph databases is somewhat moot. Each type of database has different strengths. Many relational databases do support recursive CTEs (and hence graph walking). However, the performance is probably going to be better on a software system specifically designed for this purpose.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM