ROW_NUMBER 在具有重复排序依据值的 PARTITION 上生成
ROW_NUMBER to generate on PARTITION with duplicate Order By value
我正在访问 SQL 服务器中的视图,该视图从应用程序中存储如下
SELECT *
FROM
(
VALUES
(1, 'Open', { ts '2020-01-10 23:56:12' }),
(1, 'Started', { ts '2020-01-10 23:56:12' }),
(1, 'Hold', { ts '2020-01-10 23:56:12' }),
(1, 'Sent', { ts '2020-01-11 15:33:22' }),
(1, 'Complete', { ts '2020-01-11 15:36:22' }),
(1, 'Closed', { ts '2020-01-13 16:43:33' }),
(2, 'Open', { ts '2020-02-22 06:43:33' }),
(2, 'Started', { ts '2020-02-22 06:43:33' }),
(2, 'Clarify', { ts '2020-03-23 08:33:53' }),
(2, 'Closed', { ts '2020-03-24 08:33:53' })
) t (WO, WO_Status, WO_Status_Date)
这会生成以下内容
| WO | WO_Status | WO_Status_Date |
+----+-----------+-------------------------+
| 1 | Open | 2020-01-10 23:56:12.000 |
| 1 | Started | 2020-01-10 23:56:12.000 |
| 1 | Hold | 2020-01-10 23:56:12.000 |
| 1 | Sent | 2020-01-11 15:33:22.000 |
| 1 | Complete | 2020-01-11 15:36:22.000 |
| 1 | Closed | 2020-01-13 16:43:33.000 |
| 2 | Open | 2020-02-22 06:43:33.000 |
| 2 | Started | 2020-02-22 06:43:33.000 |
| 2 | Clarify | 2020-03-23 08:33:53.000 |
| 2 | Closed | 2020-03-24 08:33:53.000 |
我只想根据行的固有顺序创建一个行号/WO。
所以我想要的输出是
| WO | WO_Status | WO_Status_Date | Order |
+----+-----------+-------------------------+-------+
| 1 | Open | 2020-01-10 23:56:12.000 | 1 |
| 1 | Started | 2020-01-10 23:56:12.000 | 2 |
| 1 | Hold | 2020-01-10 23:56:12.000 | 3 |
| 1 | Sent | 2020-01-11 15:33:22.000 | 4 |
| 1 | Complete | 2020-01-11 15:36:22.000 | 5 |
| 1 | Closed | 2020-01-13 16:43:33.000 | 6 |
| 2 | Open | 2020-02-22 06:43:33.000 | 1 |
| 2 | Started | 2020-02-22 06:43:33.000 | 2 |
| 2 | Clarify | 2020-03-23 08:33:53.000 | 3 |
| 2 | Closed | 2020-03-24 08:33:53.000 | 4 |
为此,我尝试了以下方法
SELECT
a.*,
ROW_NUMBER() OVER (PARTITION BY (a.[WO]) ORDER BY a.[WO_Status_Date] ASC) AS [Natural Order]
FROM
(SELECT *
FROM
(VALUES
(1, 'Open', { ts '2020-01-10 23:56:12' }),
(1, 'Started', { ts '2020-01-10 23:56:12' }),
(1, 'Hold', { ts '2020-01-10 23:56:12' }),
(1, 'Sent', { ts '2020-01-11 15:33:22' }),
(1, 'Complete', { ts '2020-01-11 15:36:22' }),
(1, 'Closed', { ts '2020-01-13 16:43:33' }),
(2, 'Open', { ts '2020-02-22 06:43:33' }),
(2, 'Started', { ts '2020-02-22 06:43:33' }),
(2, 'Clarify', { ts '2020-03-23 08:33:53' }),
(2, 'Closed', { ts '2020-03-24 08:33:53' })
) t (WO, WO_Status, WO_Status_Date)
) a
生成此结果:
| WO | WO_Status | WO_Status_Date | Natural Order |
+----+-----------+-------------------------+---------------+
| 1 | Started | 2020-01-10 23:56:12.000 | 1 |
| 1 | Hold | 2020-01-10 23:56:12.000 | 2 |
| 1 | Open | 2020-01-10 23:56:12.000 | 3 |
| 1 | Sent | 2020-01-11 15:33:22.000 | 4 |
| 1 | Complete | 2020-01-11 15:36:22.000 | 5 |
| 1 | Closed | 2020-01-13 16:43:33.000 | 6 |
| 2 | Started | 2020-02-22 06:43:33.000 | 1 |
| 2 | Open | 2020-02-22 06:43:33.000 | 2 |
| 2 | Clarify | 2020-03-23 08:33:53.000 | 3 |
| 2 | Closed | 2020-03-24 08:33:53.000 | 4 |
ORDER BY
正在覆盖具有重复值的行的固有顺序。有没有办法通过这个得到想要的结果。
首先,您应该知道,就关系数据库而言,没有所谓的“自然顺序”。这是一种误解。
事实上,这是一个非常普遍的误解,我已经写了一篇关于它的文章 blog post 因为尽管它在这么多网站上被这么多专业人士反驳了这么多次,但仍然有太多的开发人员成为这种误解的受害者.
现在,话虽如此,我假设不同的状态应该按照业务逻辑顺序规则进行排序 - 这可以使用 table 来完成,状态包含一个列来排序,或者通过在 order by
子句中使用 case 表达式。
这个 SQL 语句会给你想要的结果(假设我已经正确地得到了不同状态的顺序):
SELECT WO,
WO_Status,
WO_Status_Date,
ROW_NUMBER() OVER(PARTITION BY WO ORDER BY
WO_Status_Date,
CASE WO_Status
WHEN 'Open' Then 1
WHEN 'Started' Then 2
WHEN 'Hold' Then 3
WHEN 'Clarify' Then 4
WHEN 'Sent' Then 5
WHEN 'Complete' Then 6
WHEN 'Closed' Then 7
END) As [Natural Order]
FROM
(
VALUES
(1, 'Open', { ts '2020-01-10 23:56:12' }),
(1, 'Started', { ts '2020-01-10 23:56:12' }),
(1, 'Hold', { ts '2020-01-10 23:56:12' }),
(1, 'Sent', { ts '2020-01-11 15:33:22' }),
(1, 'Complete', { ts '2020-01-11 15:36:22' }),
(1, 'Closed', { ts '2020-01-13 16:43:33' }),
(2, 'Open', { ts '2020-02-22 06:43:33' }),
(2, 'Started', { ts '2020-02-22 06:43:33' }),
(2, 'Clarify', { ts '2020-03-23 08:33:53' }),
(2, 'Closed', { ts '2020-03-24 08:33:53' })
) t (WO, WO_Status, WO_Status_Date)
我正在访问 SQL 服务器中的视图,该视图从应用程序中存储如下
SELECT *
FROM
(
VALUES
(1, 'Open', { ts '2020-01-10 23:56:12' }),
(1, 'Started', { ts '2020-01-10 23:56:12' }),
(1, 'Hold', { ts '2020-01-10 23:56:12' }),
(1, 'Sent', { ts '2020-01-11 15:33:22' }),
(1, 'Complete', { ts '2020-01-11 15:36:22' }),
(1, 'Closed', { ts '2020-01-13 16:43:33' }),
(2, 'Open', { ts '2020-02-22 06:43:33' }),
(2, 'Started', { ts '2020-02-22 06:43:33' }),
(2, 'Clarify', { ts '2020-03-23 08:33:53' }),
(2, 'Closed', { ts '2020-03-24 08:33:53' })
) t (WO, WO_Status, WO_Status_Date)
这会生成以下内容
| WO | WO_Status | WO_Status_Date |
+----+-----------+-------------------------+
| 1 | Open | 2020-01-10 23:56:12.000 |
| 1 | Started | 2020-01-10 23:56:12.000 |
| 1 | Hold | 2020-01-10 23:56:12.000 |
| 1 | Sent | 2020-01-11 15:33:22.000 |
| 1 | Complete | 2020-01-11 15:36:22.000 |
| 1 | Closed | 2020-01-13 16:43:33.000 |
| 2 | Open | 2020-02-22 06:43:33.000 |
| 2 | Started | 2020-02-22 06:43:33.000 |
| 2 | Clarify | 2020-03-23 08:33:53.000 |
| 2 | Closed | 2020-03-24 08:33:53.000 |
我只想根据行的固有顺序创建一个行号/WO。
所以我想要的输出是
| WO | WO_Status | WO_Status_Date | Order |
+----+-----------+-------------------------+-------+
| 1 | Open | 2020-01-10 23:56:12.000 | 1 |
| 1 | Started | 2020-01-10 23:56:12.000 | 2 |
| 1 | Hold | 2020-01-10 23:56:12.000 | 3 |
| 1 | Sent | 2020-01-11 15:33:22.000 | 4 |
| 1 | Complete | 2020-01-11 15:36:22.000 | 5 |
| 1 | Closed | 2020-01-13 16:43:33.000 | 6 |
| 2 | Open | 2020-02-22 06:43:33.000 | 1 |
| 2 | Started | 2020-02-22 06:43:33.000 | 2 |
| 2 | Clarify | 2020-03-23 08:33:53.000 | 3 |
| 2 | Closed | 2020-03-24 08:33:53.000 | 4 |
为此,我尝试了以下方法
SELECT
a.*,
ROW_NUMBER() OVER (PARTITION BY (a.[WO]) ORDER BY a.[WO_Status_Date] ASC) AS [Natural Order]
FROM
(SELECT *
FROM
(VALUES
(1, 'Open', { ts '2020-01-10 23:56:12' }),
(1, 'Started', { ts '2020-01-10 23:56:12' }),
(1, 'Hold', { ts '2020-01-10 23:56:12' }),
(1, 'Sent', { ts '2020-01-11 15:33:22' }),
(1, 'Complete', { ts '2020-01-11 15:36:22' }),
(1, 'Closed', { ts '2020-01-13 16:43:33' }),
(2, 'Open', { ts '2020-02-22 06:43:33' }),
(2, 'Started', { ts '2020-02-22 06:43:33' }),
(2, 'Clarify', { ts '2020-03-23 08:33:53' }),
(2, 'Closed', { ts '2020-03-24 08:33:53' })
) t (WO, WO_Status, WO_Status_Date)
) a
生成此结果:
| WO | WO_Status | WO_Status_Date | Natural Order |
+----+-----------+-------------------------+---------------+
| 1 | Started | 2020-01-10 23:56:12.000 | 1 |
| 1 | Hold | 2020-01-10 23:56:12.000 | 2 |
| 1 | Open | 2020-01-10 23:56:12.000 | 3 |
| 1 | Sent | 2020-01-11 15:33:22.000 | 4 |
| 1 | Complete | 2020-01-11 15:36:22.000 | 5 |
| 1 | Closed | 2020-01-13 16:43:33.000 | 6 |
| 2 | Started | 2020-02-22 06:43:33.000 | 1 |
| 2 | Open | 2020-02-22 06:43:33.000 | 2 |
| 2 | Clarify | 2020-03-23 08:33:53.000 | 3 |
| 2 | Closed | 2020-03-24 08:33:53.000 | 4 |
ORDER BY
正在覆盖具有重复值的行的固有顺序。有没有办法通过这个得到想要的结果。
首先,您应该知道,就关系数据库而言,没有所谓的“自然顺序”。这是一种误解。
事实上,这是一个非常普遍的误解,我已经写了一篇关于它的文章 blog post 因为尽管它在这么多网站上被这么多专业人士反驳了这么多次,但仍然有太多的开发人员成为这种误解的受害者.
现在,话虽如此,我假设不同的状态应该按照业务逻辑顺序规则进行排序 - 这可以使用 table 来完成,状态包含一个列来排序,或者通过在 order by
子句中使用 case 表达式。
这个 SQL 语句会给你想要的结果(假设我已经正确地得到了不同状态的顺序):
SELECT WO,
WO_Status,
WO_Status_Date,
ROW_NUMBER() OVER(PARTITION BY WO ORDER BY
WO_Status_Date,
CASE WO_Status
WHEN 'Open' Then 1
WHEN 'Started' Then 2
WHEN 'Hold' Then 3
WHEN 'Clarify' Then 4
WHEN 'Sent' Then 5
WHEN 'Complete' Then 6
WHEN 'Closed' Then 7
END) As [Natural Order]
FROM
(
VALUES
(1, 'Open', { ts '2020-01-10 23:56:12' }),
(1, 'Started', { ts '2020-01-10 23:56:12' }),
(1, 'Hold', { ts '2020-01-10 23:56:12' }),
(1, 'Sent', { ts '2020-01-11 15:33:22' }),
(1, 'Complete', { ts '2020-01-11 15:36:22' }),
(1, 'Closed', { ts '2020-01-13 16:43:33' }),
(2, 'Open', { ts '2020-02-22 06:43:33' }),
(2, 'Started', { ts '2020-02-22 06:43:33' }),
(2, 'Clarify', { ts '2020-03-23 08:33:53' }),
(2, 'Closed', { ts '2020-03-24 08:33:53' })
) t (WO, WO_Status, WO_Status_Date)