gpt4 book ai didi

sql - 使用子查询和连接

转载 作者:行者123 更新时间:2023-11-29 14:12:16 25 4
gpt4 key购买 nike

我得到以下声明:

List of names and addresses from the customers who made purchases in 1997.

所以我认为以下两种方式是正确的,但它们不是;为什么?

select contactname, address from customers
inner join orders
on customers.customerid = orders.customerid
where date_part('year', orderdate) = 1997
order by contactname

select contactname, address from customers
where customerid in
(select customerid from orders
where date_part('year', orderdate) = 1997)
order by contactname

最佳答案

有许多正确的方法可以做到这一点。一个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 必须在检查条件之前为每一行计算一个值。在替代形式中,列(按原样)与两个常数项匹配。这样也可以更方便地使用索引。应该更快。

另请注意我如何使用 table aliases使查询更易于阅读。

由于 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 子句并在 SELECT 之后添加 DISTINCT

您也可以使用 DISTINCT 修复您的第二个查询,而是使用我的第一个示例。

关于sql - 使用子查询和连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13223985/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com