And also not O(1) nor intuitive for any non trivial query.
You don't need to have an explicit `JOIN` operator in your language, but any query that goes beyond unconditional tree walking will benefit from using joins under the hood.
But there is no other query, except if you count each and every traversal originating from each record. The top-level query can traverse edges to reach other vertices, so first it gets a result set, then for each result, fields across relations, etc.
In traditional join sense, a RDBMS first gets two or more result sets, then filters and matches one, both or neither to appropriate rows in the other one. It is a different concept entirely.
Suffice to say, one of these is conceptually easier to parallelize and distribute.
You seem to be stuck on the query semantic level. I can highly recomend actually building a graph database, and using it in anger in a project.
You'll realize that all these paradigms are more related than they appear on the surface, that the obvious and naive thing is also often prohibitively slow and limited, and that NoSQL doesn't mean NoJOIN ;)
I don’t care about implementation details. I care about performance and team velocity; the former is already implemented and the latter comes from being able to just define a graph data model and get a free GraphQL API for frontend developers in return.
You don’t think there is a slight difference in how those two very different ”joins” behave when the underlying storage is entirely non-local (columnar graph) or row-local (RDBMS)?
You don't need to have an explicit `JOIN` operator in your language, but any query that goes beyond unconditional tree walking will benefit from using joins under the hood.