SQL Row_Number() 不排序日期
Posted
技术标签:
【中文标题】SQL Row_Number() 不排序日期【英文标题】:SQL Row_Number() not sorting dates 【发布时间】:2017-05-08 19:35:00 【问题描述】:我有一个查询,我试图从我的ROW_NUMBER()
选择中获取最近的日期。我在ORDER BY
子句中尝试了MAX()
和DESC
。它不会将最近的日期显示为RowNum 1
。
这是我的查询:
;WITH cte3 AS
(
SELECT
o.PartNo,
o.JobNo,
MAX(tt.TicketDate) as rawr,
ROW_NUMBER() OVER (PARTITION BY o.JobNo, o.PartNo
ORDER BY tt.TicketDate DESC) as RowNum
FROM
OrderDet AS o
INNER JOIN
TimeTicketDet AS tt ON o.JobNo = tt.JobNo
WHERE
o.Status = 'Open'
GROUP BY
tt.TicketDate, o.JobNo, o.PartNo
)
SELECT *
FROM cte3
当我得到它给我正确的结果时,我会在 cte 查询中添加一个WHERE RowNum = 1
。
根据我当前的查询,结果如下:
+--------+-------+-----------+--------+
| PartNo | JobNo | rawr | RowNum |
+--------+-------+-----------+--------+
| 1234 | 20 | 5/30/2012 | 1 |
| 1234 | 20 | 5/29/2012 | 2 |
| 1234 | 20 | 5/25/2012 | 3 |
| 1234 | 20 | 5/24/2012 | 4 |
| 1234 | 20 | 5/23/2012 | 5 |
| 1234 | 20 | 5/22/2012 | 6 |
| 1234 | 20 | 5/16/2012 | 7 |
| 1234 | 20 | 5/15/2012 | 8 |
| 1234 | 20 | 5/14/2012 | 9 |
| 1234 | 20 | 5/11/2012 | 10 |
| 1234 | 20 | 5/10/2012 | 11 |
| 1234 | 20 | 5/9/2012 | 12 |
| 1234 | 20 | 3/27/2015 | 13 |
| 1234 | 20 | 1/3/2013 | 14 |
| 1234 | 20 | 1/2/2013 | 15 |
+--------+-------+-----------+--------+
RowNum = 13
是最近的日期。我是在错误地组织排序还是错误地转换了日期?
编辑:
TimeTicketDet 表示例数据:
+------------+-------+
| TicketDate | JobNo |
+------------+-------+
| 5/9/2012 | 20 |
| 5/10/2012 | 20 |
| 5/24/2012 | 20 |
| 3/27/2015 | 20 |
| 5/22/2012 | 20 |
| 5/10/2012 | 20 |
| 5/11/2012 | 20 |
| 5/9/2012 | 100 |
| 5/10/2012 | 100 |
| 5/24/2012 | 100 |
| 3/27/2015 | 100 |
| 5/22/2012 | 100 |
| 5/10/2012 | 100 |
| 5/11/2012 | 100 |
+------------+-------+
OrderDet 表示例数据:
+--------+--------+-------+
| PartNo | Status | JobNo |
+--------+--------+-------+
| 1234 | Open | 20 |
| 1234 | Open | 100 |
+--------+--------+-------+
期望的结果:
+--------+------------+-------+--------+
| PartNo | TicketDate | JobNo | RowNum |
+--------+------------+-------+--------+
| 1234 | 3/27/2015 | 20 | 1 |
| 1234 | 3/27/2015 | 100 | 1 |
+--------+------------+-------+--------+
【问题讨论】:
TicketDate
列的数据类型是什么?可以是字符串/varchar 吗?它看起来不像基于排序的日期时间。
看起来你的Group By
不应该有tt.TicketDate
。不用那个试试看。
当我将 row_number 用于这样的事情时,我不使用 group by 或聚合。我只有 where RowNum = 1
你想要的结果是什么?
@ollie 它是一个 char(8) 变量。那是一个字符串吗?如果是这样,我可以正确地将其转换为排序日期吗?
【参考方案1】:
正如我在my comment 中提到的,由于您的TicketDate
列是一个字符,您需要将convert it 转换为datetime
以便按实际日期对其进行排序。现在,您正在按不正确的字符串值对其进行排序。
我建议您将查询更改为以下内容:
;WITH cte3 AS
(
SELECT
o.PartNo,
o.JobNo,
MAX(tt.TicketDate) as rawr,
ROW_NUMBER() OVER (PARTITION BY o.JobNo, o.PartNo
ORDER BY cast(tt.TicketDate as datetime) DESC) as RowNum
FROM
OrderDet AS o
INNER JOIN
TimeTicketDet AS tt ON o.JobNo = tt.JobNo
WHERE
o.Status = 'Open'
GROUP BY
cast(tt.TicketDate as datetime), o.JobNo, o.PartNo
)
SELECT *
FROM cte3
where RowNum = 1;
这是demo。通过将char
转换为row_number
中的datetime
,您将按日期而不是字符串对数据进行排序。
此外,您实际上并不需要 max()
和 GROUP BY
,因为通过将 TicketDate
转换为日期时间,您将返回正确的行:
;WITH cte3 AS
(
SELECT
o.PartNo,
o.JobNo,
tt.TicketDate as rawr,
ROW_NUMBER() OVER (PARTITION BY o.JobNo, o.PartNo
ORDER BY cast(tt.TicketDate as datetime) DESC) as RowNum
FROM
#OrderDet AS o
INNER JOIN
#TimeTicketDet AS tt ON o.JobNo = tt.JobNo
WHERE
o.Status = 'Open'
)
SELECT *
FROM cte3
where RowNum =1;
【讨论】:
你不需要为MAX( cast(tt.TicketDate as datetime) )
too添加演员吗?
成功了!谢谢!我会在这个数据库中更好地注意奇怪的东西,比如字符串作为日期等等。非常感谢您的帮助。
@JuanCarlosOropeza 你是对的,我实际上正在将其添加到我的答案中
@ollie 我之前注意到了这一点,并在我最终运行查询之前添加了它。【参考方案2】:
正如 Ollie 建议的那样,您可以将您的字符串 CAST
DATETIME
并且您不需要额外的 Group By
SQL DEMO
;WITH cte3 AS
(
SELECT
o.PartNo,
o.JobNo,
tt.TicketDate as rawr,
ROW_NUMBER() OVER (PARTITION BY o.JobNo, o.PartNo
ORDER BY cast(tt.TicketDate as datetime) DESC) as RowNum
FROM OrderDet AS o
JOIN TimeTicketDet AS tt
ON o.JobNo = tt.JobNo
WHERE
o.Status = 'Open'
)
SELECT *
FROM cte3
WHERE RowNum = 1
输出
【讨论】:
感谢您的所有帮助和跟进每条评论。以上是关于SQL Row_Number() 不排序日期的主要内容,如果未能解决你的问题,请参考以下文章
ROW_NUMBER SQL Server 2005的LIMIT功能实现(ROW_NUMBER()排序函数)
SQL+获取具有最新日期的行+row_number()+重复时的情况