SQL-запрос для получения значения последнего заказа вместе с данными из других таблиц

#sql #sql-server #tsql #left-join #sql-order-by

Вопрос:

Я пишу SQL — запрос, чтобы получить данные из более чем 3 таблиц, но для упрощения вопроса здесь я использую аналогичный сценарий с 3 таблицами.

Таблица 1 Заказчик (PK-Идентификатор клиента, имя)

Идентификатор клиента Имя
1 Джон
2 Тина
3 Сэм

Таблица 2 Продажи (FK-Id, цена продажи)

ID Цена продажи
1 200.00
2 300.00
3 400.00

Таблица 3 Заказ (PK-Id, FK-Идентификатор клиента, Дата, Сумма)

ID Идентификатор клиента Дата Сумма
101 1 25-09-2021 30.0
102 1 27-09-2021 40.0
103 2 19-09-2021 60.0

В выходных данных Дата и сумма должны быть от самого последнего заказа (последняя дата) для клиента

Мой подход был

     Select c.CustomerID, c.Name, s.SalePrice, RecentOrder.Date, RecentOrder.Amount from 
    Customer as c
    LEFT JOIN Sales s ON c.CustomerID = s.ID
    LEFT JOIN (SELECT top 1 o.Date, o.Amount, o.CustomerID  
    FROM Order o, Customer c1 WHERE c1.CustomerID = o.CustomerID ORDER BY o.Date DESC) 
    RecentOrder ON c.CustomerID = RecentOrder.CustomerID
 

Вывод, который я получаю

Идентификатор клиента, Имя, Место продажи, Дата, Сумма

Идентификатор клиента Имя Цена продажи Дата Сумма
1 Джон 200.00 27-09-2021 40.0
2 Тина 300.00 нулевой нулевой
3 Сэм 400.00 нулевой нулевой

Вывод, который я получаю, включает в себя самый последний заказ из всех заказов. Но я хочу получить последний заказ из заказов, сделанных этим клиентом

Требуемая Производительность

Идентификатор клиента, Имя, Место продажи, Дата, Сумма

Идентификатор клиента Имя Цена продажи Дата Сумма
1 Джон 200.00 27-09-2021 40.0
2 Тина 300.00 19-09-2021 60.0
3 Сэм 400.00 нулевой нулевой

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

1. Вероятно, пришло время избавиться от этого устаревшего синтаксиса 30-летней давности! Ваш запрос также должен привести к ошибке с таблицей с именем order — она должна быть [order] — однако этого можно полностью избежать, вызвав ее orders — предположительно, она содержит больше, чем один порядок?

2. Некоторые люди предпочитают называть имена объектов «одноэлементными» именами, @Stu , поэтому проблема на самом деле в том, что это зарезервированное ключевое слово. Возможно CustomerOrder , это был бы лучший выбор, если бы ОП хотела получить имя синглтона.

Ответ №1:

Вместо подзапроса в левом соединении вы можете проверить с помощью внешнего приложения.

Проверьте следующим образом

 Select c.CustomerID, c.Name, s.SalePrice, RecentOrder.Date, RecentOrder.Amount 
from Customer c
LEFT JOIN Sales s ON c.CustomerID = s.ID
OUTER APPLY (
SELECT top 1 o.Date, o.Amount, o.CustomerID  
FROM [Order] o 
WHERE o.CustomerID = c.CustomerID ORDER BY o.Date DESC) RecentOrder`   
 

Ответ №2:

Вам необходимо предварительно агрегировать или идентифицировать самый последний заказ для каждого заказа клиента, ваш запрос выбирает 1 строку для всех заказов.

Попробуйте следующее (непроверенное!)

 select c.CustomerID, c.Name, s.SalePrice, o.Date, o.Amount 
from Customer c
left join Sales s on c.CustomerID = s.ID
outer apply (
    select top (1) date, amount
    from [order] o
    where o.CustomerId=c.CustomerId
    order by Id desc
)o