理解这个MySQL查询

时间:2014-05-11 21:33:35

标签: mysql sql

我理解这是如何运作但需要更多帮助

原始问题:

使用相关子查询为每个客户返回一行,表示客户最早的订单(具有最早日期的订单)。每行应包括这些 三列:email_address,order_id和order_date。

我的回答:

select email_address, order_id, order_date
from customers as T natural join orders
where order_date = 
  (select min(order_date)
  from orders as S
  where T.customer_id = S.customer_id
)

这些是架构:

客户:customer_id,email_address,password,first_name,last_name

订单:order_id,customer_id,order_date,ship_amount

我的理解是,我首先自然加入客户和订单。这只给了我实际订单的客户。然后我进入哪里。我接受订单表,并只选择customer_id与父项匹配的元组(但这部分对我来说似乎是多余的,因为父和子查询应该具有完全相同的customer_id)

然后从这些元组中选择min(order_date),然后检查父order_date是否等于(子查询只返回一个元组)。这意味着(根据我的理解)我的结果中只应该有一个元组(因为只有一个元组将与order_date完全匹配)

我不明白我是如何产生7个元组的(注意,我的答案显然是正确的)

感谢您的帮助

4 个答案:

答案 0 :(得分:1)

因此,除了每个人的回答之外,我认为这有助于理解OP的问题I don't understand how having the subquery return a single tuple allows me to get more than one tuple in my final result.

想到这样......你在一个日期有多个订单。

+-------+----------------+----------------+----------------+
|  id   |   order_date   | order_quantity |  email_address |
+-------+----------------+----------------+----------------+
|   1   |      5/16      |       5        |bill@win.ing    |
|   2   |      5/16      |       6        |jim@win.ing     |
|   3   |      5/16      |       6        |stinky@win.ing  |
|   4   |      5/12      |       1        |tom@win.ing     |
|   5   |      5/12      |       7        |jeremy@win.ing  |
|   6   |      5/12      |       3        |silly@win.ing   |
+-------+----------------+----------------+----------------+

在最近的日期有三个订单....所以当你SELECT这样的时候。

select email_address, order_id, order_date
from customers as T natural join orders
where order_date = 
  (select min(order_date)
  from orders as S
  where T.customer_id = S.customer_id
)

这实际上说的是这个

SELECT 
    email_address, 
    order_id, 
    order_date
FROM customers AS T 
NATURAL JOIN orders
WHERE order_date = "5/16"

正如您所看到的,5月16日表格中有多个最近日期的记录一个元组,因此将返回与其匹配的所有记录。

使用我的示例数据查询的结果将如下所示

+-------+----------------+----------------+----------------+
|  id   |   order_date   | order_quantity |  email_address |
+-------+----------------+----------------+----------------+
|   1   |      5/16      |       5        |bill@win.ing    |
|   2   |      5/16      |       6        |jim@win.ing     |
|   3   |      5/16      |       6        |stinky@win.ing  |
+-------+----------------+----------------+----------------+

KEY注意: 将返回该特定日期的所有记录

希望有助于澄清:)

答案 1 :(得分:0)

以下是对正在发生的事情的分解。

这些是您希望获得的数据列:     选择email_address,order_id,order_date

从customers表中选择数据:    来自客户的T

仅匹配已下订单的客户:    自然连接订单

以上可能更好地代表如下:    内联接订单为O ON O.customer_id = T.customer_id

这是为了获得与特定日期相匹配的订单,在这种情况下是他们的第一个订单,如果他们在同一天发出多个订单,他们会出现多次。     其中order_date =     (选择min(order_date)         从订单作为S.         其中T.customer_id = S.customer_id     )

如果您想通过执行以下任一操作来消除重复项:

(1)添加关键字" DISTINCT"选择后没有引号。

select DISTINCT email_address, order_id, order_date
from customers as T natural join orders
where order_date = 
  (select min(order_date)
  from orders as S
  where T.customer_id = S.customer_id
)

OR

(2)在WHERE子句

之后添加GROUP BY子句
select email_address, order_id, order_date
from customers as T natural join orders
where order_date = 
  (select min(order_date)
  from orders as S
  where T.customer_id = S.customer_id
)
GROUP BY email_address, order_id, order_date

但是,您可能会发现多个order_id会获得多个customer_id,这可能是因为它们具有相同的order_date。

假设您的order_id是连续的,您可以像下面这样重写查询。

select email_address, order_id, order_date
from customers as T natural join orders
where order_id = 
  (select min(order_id)
  from orders as S
  where T.customer_id = S.customer_id
)

希望这有帮助。

答案 2 :(得分:0)

我认为这种编写方式更容易理解并以更少的冗余实现相同的结果,关键是group by子句。

select T.email_address, S.order_id, S.order_date
from customers as T 
inner join orders as S
on T.customer_id = S.customer_id
where S.order_date = (select min(S.order_date))
group by T.customer_id

为sakila示例架构格式化:

select T.email, S.rental_id, S.rental_date
from customer as T 
inner join rental as S
on T.customer_id = S.customer_id
where S.rental_date = (select min(S.rental_date))
group by T.customer_id

结果集:

'MARY.SMITH@sakilacustomer.org', '76', '2005-05-25 11:30:37'
'PATRICIA.JOHNSON@sakilacustomer.org', '320', '2005-05-27 00:09:24'
[...]
599 row(s) returned

答案 3 :(得分:0)

试试这个......

select cust.email_address, o.order_id, o.order_date
from customers cust
join orders o
on cust.customer_id = o.customer_id
where order_date = 
  (select min(order_date)
  from orders o
  where cust.customer_id = o.customer_id
)
相关问题