简体   繁体   English

SQL Server 最大日期时间

[英]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, OrderIDOrders应该有一个以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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM