You do joins when you traverse schema type paths in EdgeQL, it's just that the actual joins are implicit (well, compared to SQL):
SELECT User {
email,
preferences: {
name,
value
}
} FILTER .id = '...'
E.g. in the above example we'd join the underlying User and Preferences tables for you.You can also do cross joins and all other funky stuff.