【问题标题】:Having trouble finding the right join statement for my query无法为我的查询找到正确的连接语句
【发布时间】:2010-12-07 04:28:11
【问题描述】:

我正在尝试从数据库中导出数据并将“客户”表与“订单”表连接起来。这是一对多的关系,客户可以有多个订单。我正在尝试编写一个查询,该查询从客户表中返回基本客户信息 - 电子邮件地址、名字、姓氏,但还包括他们最后一次下订单的日期。

customers as c
 - customer_id
 - firstname
 - lastname
 - email_address

orders as o
 - orders_id
 - customers_id
 - purchase_date

我希望结果为购买日期是客户最后一次购买的每个客户返回一个结果。

c.firstname、c.lastname、c.email_address、o.purchase_date

实现这一点的正确 SQL 语法是什么?

【问题讨论】:

  • 如果您找不到合适的右连接,也许您应该尝试使用左连接?
  • 客户没有下单怎么办?是否有与客户无关的订单?
  • 您的意思是“RIGHT JOIN”还是“正确连接”?

标签: sql


【解决方案1】:
select c.*, o.LastOrderDate
from customers c
LEFT JOIN
(select customers_id, max(purchase_date) as LastOrderDate
from orders
group by customers_id) o on o.customers_id=c.customers_id

将获取所有客户和最后一个订单的日期(如果存在)。

【讨论】:

    【解决方案2】:

    怎么样:

    SELECT c.firstname, c.lastname, c.email_address, MAX(o.purchase_date)
      FROM customers AS c
      JOIN orders    AS o ON o.customers_id = c.customer_id
     GROUP BY c.firstname, c.lastname, c.email_address
    

    这仅列出至少下过一份订单的客户。如果您想要所有客户,那么您应该能够使用 LEFT JOIN 而不是简单的 (INNER) JOIN,如图所示。

    【讨论】:

      【解决方案3】:

      这将返回所有客户,无论他们是否有任何订单:

      SQL> select c.name
        2         , c.email_address
        3         , ( select max (o.order_date) from orders o
        4             where o.customer_no = c.customer_no )as last_order
        5  from   customers c
        6  /
      
      NAME                 EMAIL_ADDRESS             LAST_ORDE
      -------------------- ------------------------- ---------
      ACME Industries      info@acme.com             07-APR-10
      Tyrell Corporation   accounts@tyrellcorp.com   26-MAR-10
      Lorax Textiles Co    the.lorax@hotmail.com
      
      SQL>
      

      相当于LEFT OUTER JOIN:

      SQL> select c.name
        2         , c.email_address
        3         , o.last_order_date
        4  from   customers c
        5         left join ( select o.customer_no
        6                          , max (o.order_date) as last_order_date
        7                     from orders o
        8                     group by o.customer_no ) o
        9                 on o.customer_no = c.customer_no
       10  /
      
      NAME                 EMAIL_ADDRESS             LAST_ORDE
      -------------------- ------------------------- ---------
      ACME Industries      info@acme.com             07-APR-10
      Tyrell Corporation   accounts@tyrellcorp.com   26-MAR-10
      Lorax Textiles Co    the.lorax@hotmail.com
      
      SQL>
      

      RIGHT OUTER JOIN 只会返回带有订单的客户的行。假设一个订单必须有一个客户(即强制外键),那么这与 INNER JOIN 相同。

      如果您的数据库支持分析函数,那么 RANK() 提供了另一种解决方法...

      SQL> select name
        2         , email_address
        3         , order_date
        4  from (
        5      select c.name
        6             , c.email_address
        7             , o.order_date
        8             , rank () over (partition by c.customer_no
        9                              order by o.order_date desc ) as rnk
       10      from   customers c
       11             join orders o
       12                 on ( o.customer_no = c.customer_no)
       13  )
       14  where rnk = 1
       15  /
      
      NAME                 EMAIL_ADDRESS             ORDER_DAT
      -------------------- ------------------------- ---------
      ACME Industries      info@acme.com             07-APR-10
      Tyrell Corporation   accounts@tyrellcorp.com   26-MAR-10
      
      SQL>
      

      这也只返回带有订单的客户的行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-08
        • 2020-11-13
        • 1970-01-01
        • 2019-10-15
        • 2019-10-19
        • 1970-01-01
        相关资源
        最近更新 更多