我知道以前有人问过这类问题,但我找不到一个和我的问题完全一样的问题。我试着举个夸张的例子。
假设我们希望找到至少有一名员工年龄大于40岁,至少有一名客户年龄小于20岁的公司。
我的同事为这个问题写的查询如下:
SELECT DISTINCT(c.NAME) FROM COMPANY c
LEFT JOIN EMPLOYEE e ON c.COMPANY_ID = e.COMPANY_ID
LEFT JOIN CUSTOMER u ON c.COMPANY_ID = u.COMPANY_ID
WHERE e.AGE > 40 and u.AGE < 20
我不熟悉数据库。但是看看这个查询(就像一个时间复杂性问题),它将创建一个不必要的巨大临时表。每个公司都有employeeamount x customeramount行。
因此,我重新编写了查询:
SELECT c.NAME FROM COMPANY c
WHERE EXISTS (SELECT * FROM EMPLOYEE e WHERE e.AGE > 40 AND c.COMPANY_ID = e.COMPANY_ID )
OR EXISTS (SELECT * FROM CUSTOMER u WHERE u.AGE < 20 AND c.COMPANY_ID = u.COMPANY_ID )
我不知道这个查询是否会更糟,因为它将为每个公司运行2个子查询。
我知道有更好的方法来写这个。例如,为两个年龄条件编写两个不同的子查询,然后合并它们可能会更好。但是我真的很想知道两个查询中的一个或两个是否有问题。
注意:您可以增加联接/子查询的数量。例如,“我们希望找到至少有一名员工年龄大于40岁,至少有一名客户年龄小于20岁,并且至少有一个订单金额大于1000美元的公司。”
谢谢。
2条答案
按热度按时间au9on6nz1#
这个
exists
一般来说,版本应该有更好的性能,特别是当您在上有索引时company_id
在每个子表中。为什么?这个
JOIN
版本创建一个中间结果,所有客户超过40岁,所有员工低于20岁。如果这些团体对某一特定公司来说规模很大,那么规模可能会相当大。然后,查询执行额外的工作来删除重复项。可能存在一些边缘情况,其中第一个版本具有良好的性能。举例来说,如果两个小组都是空的——没有20岁以下的员工,也没有40岁以上的顾客,我会想到这一点。然后中间结果集为空,不需要删除重复项。不过,对于一般情况,我建议
exists
.k4emjkb12#
要了解当前环境中实际发生的情况,需要使用数据库设置和数据来比较实际的执行计划(而不仅仅是解释计划,它只给出估计的计划)。除了oracle使用的详细步骤(全表扫描、连接等),只有真正的执行计划才能给出查询使用的详细资源,如cpu和io。
尝试:
不要假设,只是测试。