有很多正确的方法可以做到这一点。半连接EXISTS
可能是 PostgreSQL 中最快的,如果您只想要一个不同客户的列表并且除了至少存在 1 个订单之外没有来自订单的更多详细信息:
SELECT c.contactname, c.address
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customerid = c.customerid
AND o.orderdate >= '1997-1-1'::date
AND o.orderdate < '1998-1-1'::date
)
ORDER BY contactname;
为什么使用?
WHERE o.orderdate >= '1997-1-1'::date
AND o.orderdate < '1998-1-1'::date
代替:
WHERE date_part('year', orderdate) = 1997
使用您的表达式,PostgreSQL 必须在检查条件之前为每一行计算一个值。在替代形式中,列(原样)与两个常数项匹配。这也可以更轻松地使用索引。应该更快。
还要注意我如何使用表别名使查询更易于阅读。
您的第一个查询由于JOIN
. 如果表中的一行在表中customer
有多个匹配的行,则orders
每个订单都会得到一行。您可以使用以下方法解决此问题GROUP BY
:
SELECT c.contactname, c.address
FROM customers c
JOIN orders o USING (customerid)
WHERE o.orderdate >= '1997-1-1'::date
AND o.orderdate < '1998-1-1'::date
GROUP BY c.customer_id --- or whatever is the primary key of c
ORDER BY c.contactname
..这是另一种方法。但很可能更慢。如果您还想从表中检索其他(聚合)数据,则可以使用此表单orders
..
DISTINCT
将是 的替代方案GROUP BY
,在这种简单的情况下几乎相同。删除GROUP BY
this 的子句并添加DISTINCT
after SELECT
。
您也可以使用 修复您的第二个查询DISTINCT
,而是使用我的第一个示例。