获取具有与条件选择平行的最大日期值的所有记录

时间:2017-11-30 12:17:17

标签: sql sql-server tsql

我正在查询数据库并检索共享32485 ProjectNumber的所有列 我需要获得每个ChangeDateTime的最大orderId

数据库表:

OrderID     ProjectNumber     ChangeDateTime
---------------------------------------------
1                32485        30/11/2018
1                32485        29/11/2018
1                32485        28/11/2018
2                32485        30/09/2017
2                32485        29/09/2017
2                32485        28/09/2017

Desierd Result:

OrderID     ProjectNumber     ChangeDateTime
---------------------------------------------
1                32485        30/11/2018 
2                32485        30/09/2017

到目前为止我尝试了什么(但我并不惊讶它只返回最大ChangeDateTime的1条记录):

SELECT TOP 1 
Orders.OrderID,
Changes.ChangeDateTime,
Orders.ProjectNumber
FROM Orders 
INNER JOIN Changes ON Changes.ItemID = Orders.OrderID
INNER JOIN LineStatusSettings ON 
Cast( LineStatusSettings.LineStatusSettingID as varchar(max)) = Changes.NewValue 
INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID
INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID
WHERE Orders.ProjectNumber = 32485 AND Orders.Deleted=0 
GROUP BY Orders.OrderID,
Changes.ChangeDateTime,
Orders.ProjectNumber
ORDER BY Changes.ChangeDateTime DESC 

2 个答案:

答案 0 :(得分:2)

你变得太复杂了。此查询产生所需的输出:

SELECT
  Orders.OrderID,
  Orders.ProjectNumber,
  MAX(Changes.ChangeDateTime)
FROM Orders 
INNER JOIN Changes ON Changes.ItemID = Orders.OrderID
WHERE 
  Orders.ProjectNumber = 32485
GROUP BY
  Orders.OrderID,
  Orders.ProjectNumber

如果您需要JOIN区域中的其他内容,为了限制考虑输出的行,可以将其添加到

SELECT
  Orders.OrderID,
  Orders.ProjectNumber,
  MAX(Changes.ChangeDateTime)
FROM Orders 
  INNER JOIN Changes ON Changes.ItemID = Orders.OrderID
  INNER JOIN LineStatusSettings ON Cast( LineStatusSettings.LineStatusSettingID as varchar(max)) = Changes.NewValue 
  INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID
  INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID
WHERE Orders.ProjectNumber = 32485 AND Orders.Deleted=0 
GROUP BY
  Orders.OrderID,
  Orders.ProjectNumber

如果您在输出中添加更多列,并且它们不在某些聚合函数中(min / max / avg / sum / count等),那么您也需要将它们添加到组中,它将会可能会增加行数,因为它增加了唯一值组合的数量

另一种有效获取数据负载的方法,并根据几列选择" TOP x"会是这样的:

SELECT * FROM
(
 SELECT
  *,
  ROW_NUMBER() OVER(PARTITION BY Orders.OrderID, Orders.ProjectNumber ORDER BY Changes.ChangeDateTime DESC) as rown
 FROM Orders 
  INNER JOIN Changes ON Changes.ItemID = Orders.OrderID
  INNER JOIN LineStatusSettings ON Cast( LineStatusSettings.LineStatusSettingID as varchar(max)) = Changes.NewValue 
  INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID
  INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID
 WHERE Orders.ProjectNumber = 32485 AND Orders.Deleted=0 
 --ORDER BY Orders.OrderID, Orders.ProjectNumber, Changes.ChangeDateTime DESC 
)a
WHERE
  a.rown = 1

这不会对数据进行分组,它只是将所有内容连接在一起。然后,ROW_NUBMER子句有效地将数据分解为OrderID / PrijectNumber配对的每个唯一出现的块,并设置一个计数器,从每个配对的最近日期开始,并且增加1.不同的OrderID / ProjectNumber配对原因从1开始计数的计数器。这意味着(OrderID 1,ProjectNumber 1)的行号为1,(OrderID 2,Project 1)编号为1的另一行,(OrderID 1,ProjectNumber 2)编号为1的另一行)

如果你只是孤立地运行子查询,它会更容易看到它是如何工作的。我建议你在isloation中运行时取消注释ORDER BY行,因为它将确保结果以一个顺序显示很容易看到发生了什么(当配对改变时,计数器从1重新开始)

答案 1 :(得分:0)

使用TOP 1 WITH TIES

SELECT TOP (1) WITH TIES . . .