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() 不排序日期的主要内容,如果未能解决你的问题,请参考以下文章

sql 连续活跃天数

ROW_NUMBER SQL Server 2005的LIMIT功能实现(ROW_NUMBER()排序函数)

SQL+获取具有最新日期的行+row_number()+重复时的情况

大数据学习(二十三)sql中的排序函数 row_number() rank() dense_rank()

sql 排序函数ROW_NUMBER分页返回数据

SQL基本操作——row_number() over()