我有一个Customers
表,其中有CustomerID
和CustomerName
。
然后我有一个Orders
表,其中包含CustomerID
,datetime OrderPlaced
和datetime OrderDelivered
。
考虑到并非所有客户都下订单,我想获得CustomerName
,OrderPlaced
和OrderDelivered
的列表,但仅针对已下订单且其订单的客户已交付,每个客户只有最新的OrderPlaced
。
我从开始做起(完全意识到这还没有实现OrderDelivered
的限制,但是还没有做我想做的事):
SELECT CustomerID,
(SELECT TOP 1 OrderDelivered
FROM Orders ORDER BY OrderDelivered DESC) AS OrderDelivered
FROM Customer
WHERE OrderDelivered IS NOT NULL
但是MS SQL已经不喜欢这样,它说它不知道OrderDelivered
子句中的WHERE
是什么。
我该怎么做?
答案 0 :(得分:2)
个人而言,我会将您的子查询移至FROM
并使用CROSS APPLY
。然后,您可以更轻松地参考该列:
SELECT C.CustomerID,
O.OrderDelivered
FROM Customer C
CROSS APPLY (SELECT TOP 1 OrderDelivered
FROM Orders oa
WHERE oa.CustomerID = C.CustomerID --Guess column name for orders
AND O.OrderDelivered IS NOT NULL
ORDER BY O.OrderDelivered DESC) O;
但是,由于它是CROSS APPLY
,因此结果已经被过滤;因此不需要WHERE
。
答案 1 :(得分:1)
如果您要获取最近交付的订单,则一种方法使用apply
:
select c.*, o.OrderPlaced, o.OrderDelivered
from customer c cross apply
(select top (1) o.*
from orders o
where o.CustomerID = c.CustomerID and
o.OrderDelivered is not null
order by o.OrderPlaced desc
) o;
答案 2 :(得分:0)
您可以使用OVER
子句(https://docs.microsoft.com/en-us/sql/t-sql/queries/select-over-clause-transact-sql)来实现。
DECLARE @customers TABLE (CustomerId INT, CustomerName NVARCHAR(20))
DECLARE @orders TABLE (CustomerId INT, OrderPlaced DATETIME, OrderDelivered DATETIME)
INSERT INTO @customers VALUES
(1, 'a'),
(2, 'b')
INSERT INTO @orders VALUES
(1, '2019-01-01', null),
(2, '2019-01-03', '2019-02-01'),
(2, '2019-01-05', null)
SELECT
c.CustomerName,
-- Latest OrderPlaced
FIRST_VALUE(o.OrderPlaced)
OVER(PARTITION BY c.CustomerId ORDER BY o.OrderPlaced DESC) AS OrderPlaced,
-- The matching OrderDelivered
FIRST_VALUE(o.OrderDelivered)
OVER(PARTITION BY c.CustomerId ORDER BY o.OrderPlaced DESC) AS OrderDelivered
FROM @customers c
INNER JOIN @orders o ON o.CustomerId = c.CustomerId
WHERE o.OrderDelivered IS NOT NULL