多类查询 #

一、多类查询概述 #

1.1 OrientDB关联方式 #

text
关联方式:
├── LINK - 直接链接引用
├── EMBEDDED - 嵌入文档
├── Edge - 图边关系
└── 查询关联 - 子查询关联

1.2 与关系数据库的区别 #

特性 OrientDB 关系数据库
关联方式 LINK/EDGE 外键
JOIN性能 链接直接访问 需要JOIN操作
嵌套数据 原生支持 需要多表查询

二、链接查询 #

2.1 直接访问链接属性 #

sql
SELECT name, employer.name AS companyName FROM Person

2.2 多层链接访问 #

sql
SELECT 
    name,
    employer.name AS companyName,
    employer.address.city AS companyCity,
    employer.ceo.name AS ceoName
FROM Person

2.3 链接集合访问 #

sql
SELECT name, friends.name AS friendNames FROM Person
SELECT name, SIZE(friends) AS friendCount FROM Person

2.4 链接条件过滤 #

sql
SELECT FROM Person WHERE employer.name = 'ABC Corp'
SELECT FROM Person WHERE employer.address.city = 'Beijing'

2.5 链接聚合 #

sql
SELECT 
    employer.name AS company,
    COUNT(*) AS employeeCount,
    AVG(salary) AS avgSalary
FROM Person
GROUP BY employer

三、反向链接查询 #

3.1 使用in()函数 #

sql
SELECT 
    name AS companyName,
    in('WORKS_AT').name AS employees
FROM Company

3.2 使用out()函数 #

sql
SELECT 
    name AS personName,
    out('WORKS_AT').name AS companies
FROM Person

3.3 双向链接 #

sql
SELECT 
    name,
    in('KNOWS').name AS followers,
    out('KNOWS').name AS following
FROM Person

3.4 链接计数 #

sql
SELECT 
    name,
    SIZE(in('KNOWS')) AS followerCount,
    SIZE(out('KNOWS')) AS followingCount
FROM Person

四、LET关联查询 #

4.1 使用LET定义关联 #

sql
SELECT 
    p.name,
    $company.name AS companyName
FROM Person p
LET $company = (SELECT FROM Company WHERE @rid = p.employer)

4.2 多表关联 #

sql
SELECT 
    p.name AS personName,
    $company.name AS companyName,
    $department.name AS departmentName
FROM Person p
LET $company = (SELECT FROM Company WHERE @rid = p.employer),
    $department = (SELECT FROM Department WHERE @rid = p.department)

4.3 条件关联 #

sql
SELECT 
    p.name,
    $orders AS orders
FROM Person p
LET $orders = (SELECT FROM Order WHERE customer = p.@rid AND status = 'completed')
WHERE $orders.size() > 0

五、子查询关联 #

5.1 WHERE子查询 #

sql
SELECT FROM Person WHERE employer IN (
    SELECT FROM Company WHERE industry = 'Technology'
)

5.2 FROM子查询 #

sql
SELECT p.name, o.totalAmount
FROM (
    SELECT FROM Person WHERE status = 'active'
) p
LET o = (SELECT FROM Order WHERE customer = p.@rid)
WHERE $o.size() > 0

5.3 投影子查询 #

sql
SELECT 
    name,
    (SELECT COUNT(*) FROM Order WHERE customer = @rid) AS orderCount,
    (SELECT SUM(totalAmount) FROM Order WHERE customer = @rid) AS totalSpent
FROM Person

5.4 关联子查询 #

sql
SELECT 
    p.name,
    (SELECT name FROM Company WHERE @rid = p.employer)[0] AS companyName
FROM Person p

六、UNWIND展开 #

6.1 展开集合 #

sql
SELECT name, hobby FROM Person 
UNWIND hobbies AS hobby

6.2 展开链接集合 #

sql
SELECT 
    p.name AS personName,
    f.name AS friendName
FROM Person p
UNWIND p.friends AS friendRid
LET f = (SELECT FROM Person WHERE @rid = $friendRid)

6.3 展开后聚合 #

sql
SELECT hobby, COUNT(*) AS personCount
FROM Person
UNWIND hobbies AS hobby
GROUP BY hobby
ORDER BY personCount DESC

七、图关系查询 #

7.1 查询边 #

sql
SELECT 
    out.name AS fromPerson,
    in.name AS toPerson,
    since
FROM KNOWS
WHERE since > 2020

7.2 查询顶点的边 #

sql
SELECT 
    name,
    outE('KNOWS').since AS knowSince,
    inE('KNOWS').since AS knownSince
FROM Person

7.3 遍历关联 #

sql
SELECT 
    name,
    out('WORKS_AT').name AS companies,
    out('WORKS_AT').out('LOCATED_IN').name AS locations
FROM Person

八、嵌入文档查询 #

8.1 访问嵌入属性 #

sql
SELECT name, address.city, address.street FROM Person
SELECT name, phoneNumbers[0].number AS primaryPhone FROM Person

8.2 嵌入文档条件 #

sql
SELECT FROM Person WHERE address.city = 'Beijing'
SELECT FROM Person WHERE phoneNumbers CONTAINSALL [{'type': 'mobile'}]

8.3 嵌入文档聚合 #

sql
SELECT 
    address.city AS city,
    COUNT(*) AS count
FROM Person
GROUP BY address.city

九、多类JOIN模拟 #

9.1 INNER JOIN效果 #

sql
SELECT 
    p.name AS personName,
    c.name AS companyName
FROM Person p
LET c = (SELECT FROM Company WHERE @rid = p.employer)
WHERE $c.size() > 0

9.2 LEFT JOIN效果 #

sql
SELECT 
    p.name AS personName,
    IF($c.size() > 0, $c[0].name, NULL) AS companyName
FROM Person p
LET $c = (SELECT FROM Company WHERE @rid = p.employer)

9.3 RIGHT JOIN效果 #

sql
SELECT 
    IF($p.size() > 0, $p[0].name, NULL) AS personName,
    c.name AS companyName
FROM Company c
LET $p = (SELECT FROM Person WHERE employer = c.@rid)

9.4 FULL JOIN效果 #

sql
SELECT name, 'Person' AS type FROM Person
UNION ALL
SELECT name, 'Company' AS type FROM Company
WHERE @rid NOT IN (SELECT employer FROM Person WHERE employer IS NOT NULL)

十、复杂关联示例 #

10.1 订单-客户-产品关联 #

sql
SELECT 
    o.orderNumber,
    c.name AS customerName,
    p.name AS productName,
    oi.quantity,
    oi.price
FROM Order o
LET $customer = (SELECT FROM Customer WHERE @rid = o.customer),
    $items = (SELECT FROM OrderItem WHERE orderId = o.@rid)
UNWIND $items AS oi
LET $product = (SELECT FROM Product WHERE @rid = oi.productId)
LET c = $customer,
    p = $product

10.2 组织架构查询 #

sql
SELECT 
    e.name AS employeeName,
    $manager.name AS managerName,
    $department.name AS departmentName
FROM Employee e
LET $manager = (SELECT FROM Employee WHERE @rid = e.manager),
    $department = (SELECT FROM Department WHERE @rid = e.department)

10.3 社交网络查询 #

sql
SELECT 
    p.name AS personName,
    $friends.name AS friendNames,
    $mutual.size() AS mutualFriendCount
FROM Person p
LET $friends = (SELECT FROM Person WHERE @rid IN p.out('KNOWS')),
    $mutual = (
        SELECT FROM Person 
        WHERE @rid IN $friends.out('KNOWS') 
          AND @rid IN p.out('KNOWS')
    )

十一、性能优化 #

11.1 使用索引 #

sql
CREATE INDEX Person.employer LINK
CREATE INDEX Order.customer LINK

11.2 限制关联深度 #

sql
SELECT name, employer.name FROM Person
SELECT name, employer.name, employer.address.city FROM Person

11.3 使用LET缓存 #

sql
LET $companies = SELECT FROM Company WHERE industry = 'Tech'
SELECT p.name, $c.name AS companyName
FROM Person p
LET $c = (SELECT FROM $companies WHERE @rid = p.employer)
WHERE $c.size() > 0

11.4 避免N+1问题 #

sql
SELECT 
    p.name,
    p.employer.name AS companyName
FROM Person p

十二、实际应用示例 #

12.1 订单详情查询 #

sql
SELECT 
    o.id AS orderId,
    o.orderNumber,
    o.status,
    c.name AS customerName,
    c.email AS customerEmail,
    SUM(oi.quantity * oi.price) AS totalAmount,
    COUNT(oi) AS itemCount
FROM Order o
LET $customer = (SELECT FROM Customer WHERE @rid = o.customer),
    $items = (SELECT FROM OrderItem WHERE orderId = o.@rid)
LET c = $customer,
    oi = $items
GROUP BY o

12.2 员工信息查询 #

sql
SELECT 
    e.name AS employeeName,
    e.email,
    d.name AS departmentName,
    m.name AS managerName,
    c.name AS companyName,
    AVG(s.amount) AS avgSalary
FROM Employee e
LET $department = (SELECT FROM Department WHERE @rid = e.department),
    $manager = (SELECT FROM Employee WHERE @rid = e.manager),
    $company = (SELECT FROM Company WHERE @rid = e.company),
    $salaries = (SELECT FROM Salary WHERE employeeId = e.@rid)
LET d = $department,
    m = $manager,
    c = $company,
    s = $salaries

12.3 产品销售分析 #

sql
SELECT 
    p.name AS productName,
    p.category,
    COUNT(DISTINCT o) AS orderCount,
    SUM(oi.quantity) AS totalQuantity,
    SUM(oi.quantity * oi.price) AS totalRevenue
FROM Product p
LET $orderItems = (SELECT FROM OrderItem WHERE productId = p.@rid)
UNWIND $orderItems AS oi
LET $order = (SELECT FROM Order WHERE @rid = oi.orderId)
LET o = $order
GROUP BY p
ORDER BY totalRevenue DESC

十三、总结 #

多类查询要点:

方式 说明 示例
链接访问 直接访问链接属性 employer.name
反向链接 in()/out()函数 in(‘WORKS_AT’)
LET关联 定义关联变量 LET $c = …
子查询 嵌套查询关联 (SELECT FROM …)
UNWIND 展开集合 UNWIND hobbies

下一步,让我们学习子查询与嵌套!

最后更新:2026-03-27