Требуется помощь с запросом объединения

#sql #oracle #plsql

#sql #Oracle #plsql

Вопрос:

У меня есть две очень простые таблицы в Oracle 9G:

Клиент

 userid | firstName | lastName | email 
------- ----------- ---------- ---------------------
  1      user1       User1      user1@mail.in
  2      user2       User2      user2@mail.in
  

Порядок

 orderiD | userId | OrderType | Order_Date | Amount
-------- -------- ----------- ------------ -------
1          1          0         12/12/2009    1
2          1          1         13/12/2009    2
3          1          1         14/12/2009    3
4          2          0         12/12/2009    4
5          2          1         16/12/2009    2
6          1          0         14/12/2009    5
7          2          1         17/12/2009    4
8          2          0         10/12/2010    2
  

Я хочу выбрать всех пользователей, у которых есть заказы типа 0

 select *    
from Customer c 
inner join Order o on c.userid = o.userid 
where o.orderType = '0'
  

Результатом является:

 orderiD | userId | OrderType | Order_Date | Amount
-------- -------- ----------- ------------ --------
1          1          0         12/12/2009    1
4          2          0         12/12/2009    4
6          1          0         14/12/2009    5
8          2          0         10/12/2010    2
  

Теперь мне нужно изменить этот запрос, чтобы указать только дату последней покупки для каждого идентификатора пользователя и получить результат, подобный этому:

 orderiD | userId | OrderType | Order_Date | Amount
-------- -------- ----------- ------------ --------
6          1          0         14/12/2009    5
8          2          0         10/12/2010    2
  

Как я должен изменить свой запрос, чтобы получить этот результат?

Ответ №1:

 SELECT * 
FROM order o
WHERE o.orderType ='0'
  AND o.order_date = 
      ( SELECT MAX(o2.order_date)
        FROM order o2
        WHERE o2.userid = o.userid
          AND o2.orderType = '0'
      )
  

или

 SELECT o.* 
FROM order o
  JOIN
    ( SELECT userid
           , MAX(order_date) AS lastPurchaseDate
      FROM order 
      WHERE o.orderType ='0'
      GROUP BY userid
    ) AS grp
    ON grp.userid = o.userid
    AND grp.lastPurchaseDate = o.order_date
  

Ответ №2:

Попробуйте это:

 select * 
from   customer c
,      order o
where  c.userid = o.userid 
and    o.orderType ='0'
and    o.order_date = (
    select max(o2.order_date)
    from   order o2
    where  o2.userid = o.userid
)
  

Ответ №3:

Не требуется подзапрос, только агрегированные функции.

 select c.userId, o.OrderType, 
       max(o.Order_Date),  
       max(o.orderiD) keep (dense_rank last order by order_date),  
       max(o.Amount) keep (dense_rank last order by order_date)
from Customer c inner join Order o
on c.userid = o.userid where o.orderType ='0'
group by c.userId, o.OrderType
  

Ответ №4:

 SELECT * 
FROM Order o
INNER JOIN 
(SELECT MAX(o.id) AS maxid
FROM Customer c 
INNER JOIN Order o ON c.userid = o.userid 
WHERE o.orderType ='0'
GROUP BY c.userid) x ON x.maxid = o.id
  

Комментарии:

1. Как это позволяет получить максимальную дату?

2. В некотором смысле решение является обманом / сокращением, поскольку оно предполагает, что o.id будут упорядочены по дате (что, вероятно, соответствует действительности). Но вы могли бы представить сценарий, в котором изменяется order_date, и в этом случае этот SQL был бы не совсем правильным.

3. Это неправильно во многих отношениях. @danny: Пожалуйста, добавьте строку в таблицу заказов с помощью 9, 2, 0, 14/12/2009, 9 и запустите запрос еще раз, чтобы понять, почему.