[英]SQL Server max Datetime
I am a bit new to SQL Server and I am trying to execute a really simple query that goes like:我对 SQL Server 有点陌生,我正在尝试执行一个非常简单的查询,如下所示:
SELECT
ProductID, o.OrderID, o.CustomerID, CompanyName,OrderDate, Quantity
FROM
o
JOIN
[Order Details] od on o.OrderID = od.OrderID
JOIN
Customers c on c.CustomerID = o.CustomerID
WHERE
orderdate = (select max(OrderDate)
from o
where ProductID = od.ProductID)
And then I got this.然后我得到了这个。
ProductID OrderID CustomerID CompanyName OrderDate Quantity
2 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 24
3 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 4
4 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1
6 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1
7 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1
8 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2
10 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1
12 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2
13 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 4
14 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1
16 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2
20 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1
23 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 2
32 11077 RATTC Rattlesnake Canyon Grocery 1998-05-07 09:50:47.000 1
but I want to get the newest orderdate for every productID.但我想获得每个产品 ID 的最新订单日期。 Like this:像这样:
So what should I do to get that?那么我该怎么做才能得到它?
This should get you started.这应该让你开始。 I'm assuming that Order Details
has order line items.我假设Order Details
具有订单行项目。
SELECT
p.ProductID,
o.OrderID,
o.CustomerID,
o.CompanyName,
o.OrderDate
FROM
dbo.Products p
CROSS APPLY (
SELECT TOP 1 *
FROM dbo.Orders o
WHERE EXISTS (
SELECT *
FROM dbo.[Order Details] od
WHERE
o.OrderID = od.OrderID
AND p.ProductID = od.ProductID
)
ORDER BY o.OrderDate DESC
) o
INNER JOIN dbo.Customers c
ON o.CustomerID = c.CustomerID
;
I assumed that [Order Details]
rows can have the same OrderID
twice, which makes things a bit more complicated to get the Quantity
(which I left out).我假设[Order Details]
行可以有两次相同的OrderID
,这使得获取Quantity
(我省略了它)变得有点复杂。 Would you want that quantity summed, or to show two rows?你想要这个数量的总和,还是显示两行? Depending on what result you want and how that table is implemented, this could be the solution you want:根据您想要的结果以及该表的实施方式,这可能是您想要的解决方案:
SELECT
p.ProductID,
odq.OrderID,
odq.CustomerID,
odq.CompanyName,
odq.OrderDate,
odq.Quantity
FROM
dbo.Products p
CROSS APPLY (
SELECT TOP 1 *
FROM dbo.Orders o
CROSS APPLY (
SELECT TotalQuantity = Sum(Quantity)
FROM dbo.[Order Details] od
WHERE
o.OrderID = od.OrderID
AND p.ProductID = od.ProductID
) odq
ORDER BY o.OrderDate DESC
) odq
INNER JOIN dbo.Customers c
ON o.CustomerID = c.CustomerID
;
This query should perform well as long as you have appropriate indexes on your tables ( Order Details
should have index ProductID, OrderID
and Orders
should have an index starting with ProductID, OrderDate
).只要您的表上有适当的索引( Order Details
应该有索引ProductID, OrderID
和Orders
应该有一个以ProductID, OrderDate
开头的索引) ProductID, OrderDate
这个查询应该会执行得很好。 Its performance should remain steady as the system's data grows.随着系统数据的增长,其性能应该保持稳定。
I did assume that you have a dbo.Products
table, and by changing from CROSS APPLY
to OUTER APPLY
(the first one), you can show products that have no orders.我确实假设您有一个dbo.Products
表,并且通过从CROSS APPLY
更改为OUTER APPLY
(第一个),您可以显示没有订单的产品。 Alternately, there's another possible query:或者,还有另一个可能的查询:
WITH OrderSequences AS (
SELECT
Sequence = Rank() OVER (PARTITION BY od.ProductID ORDER BY o.OrderDate DESC),
o.*,
od.ProductID,
od.Quantity
FROM
dbo.Orders o
INNER JOIN dbo.[Order Details] od
ON o.OrderID = od.OrderID
)
SELECT
o.OrderID,
o.CustomerID,
o.CompanyName,
o.OrderDate,
o.ProductID,
o.Quantity
FROM
OrderSequences o
INNER JOIN dbo.Customers c
ON o.CustomerID = c.CustomerID
WHERE
Sequence = 1
;
Again, if you can have the same OrderID
on more than one line in an order (a very likely thing in my opinion), then you'll need to do some kind of summing, or tolerate the duplicate rows that this will generate (as it will show BOTH rows on the same order if they were, together, the last time that ProductID was ordered).同样,如果您可以在一个OrderID
的多个行上使用相同的OrderID
(在我看来这很可能),那么您将需要进行某种求和,或容忍这将生成的重复行(如如果它们是最后一次订购 ProductID 时,它将以相同的顺序显示两行)。
This second query is likely to get slower and slower as the system ages and accumulates data, because it is forced to perform the windowing function on every row in the entire table (it can never be sure it has found the highest date and has found every ProductID
until the end).随着系统老化和数据积累,这第二个查询可能会变得越来越慢,因为它被迫对整个表中的每一行执行加窗函数(它永远无法确定它找到了最高日期,并且找到了每个ProductID
直到结束)。
WITH X AS
(SELECT ProductID
, o.OrderID
, o.CustomerID
, CompanyName
,OrderDate
, Quantity
,ROW_NUMBER() OVER (PARTITION BY od.productid ORDER BY o.OrderDate DESC) rn
FROM [Orders] o
JOIN [Order Details] od on o.OrderID = od.OrderID
join Customers c on c.CustomerID=o.CustomerID
)
SELECT ProductID
, OrderID
, CustomerID
, CompanyName
, OrderDate
, Quantity
FROM X
WHERE rn = 1
OR或者
SELECT ProductID
, OrderID
, CustomerID
, CompanyName
, OrderDate
, Quantity
FROM
(SELECT ProductID
, o.OrderID
, o.CustomerID
, CompanyName
,OrderDate
, Quantity
,ROW_NUMBER() OVER (PARTITION BY od.productid ORDER BY o.OrderDate DESC) rn
FROM [Orders] o
JOIN [Order Details] od on o.OrderID = od.OrderID
join Customers c on c.CustomerID=o.CustomerID
)x
WHERE rn = 1
Using MAX(OrderDate)
in a subquery, there is nothing to correlate the max(date) with the productID in the parent query.在子查询中使用MAX(OrderDate)
,没有什么可以将 max(date) 与父查询中的 productID 关联起来。 So you will always get all orders that have the Max(Date) of the first ProductID from the Order-Product join.因此,您将始终从 Order-Product 连接中获得具有第一个ProductID 的 Max(Date) 的所有订单。
The best way to do this kind of filter is to join the o
order table to itself.执行这种过滤器的最佳方法是将o
order 表加入到自身中。
SELECT ProductID, o.OrderID, o.CustomerID, CompanyName,OrderDate, Quantity
FROM o
LEFT JOIN o2 ON o.ProductID = o2.ProductID AND o2.OrderDate > o.OrderDate
JOIN [Order Details] od on o.OrderID = od.OrderID
join Customers c on c.CustomerID=o.CustomerID
WHERE o2.OrderDate IS NULL
So here we are joining all orders of a product with all other orders of the same product that have a greater OrderDate, and then filtering for the one that has no greater order date, so that o.OrderDate
will be the MAX(OrderDate)
for each ProductID所以在这里我们将一个产品的所有订单与具有更大 OrderDate 的同一产品的所有其他订单连接起来,然后过滤没有更大订单日期的订单,以便o.OrderDate
将是MAX(OrderDate)
每个产品ID
(Disclaimer: The above SQL is not tested and may require modification in order to run properly on your database, but the idea should work for your needs.) (免责声明:上述 SQL 未经测试,可能需要修改才能在您的数据库上正常运行,但该想法应该适合您的需要。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.