SQL Row_Number() (Partition by... Order By...) IGNORES Order 语句

SQL Row_Number() (Partition by… Order By…) IGNORES Order statement

我找不到支持我尝试实现的功能的函数。

假设我们有以下 table,其中包含字段排序顺序和某些重复项

+----------+----------+-----+-------------+-----------+
| UniqueId |    Id    | Qty | RetailPrice | SortOrder |
+----------+----------+-----+-------------+-----------+
|     3124 | 92361725 |  25 |      269.99 |         1 |
|     2627 | 92361725 |  25 |      269.99 |         2 |
|     7635 | 92361725 |  25 |      269.99 |         3 |
|     8732 | 92361725 |  25 |      269.99 |         4 |
|     3791 | 92361725 |  20 |      269.99 |         5 |
|     4328 | 92361725 |  25 |      269.99 |         6 |
+----------+----------+-----+-------------+-----------+

我想枚举我的行,在发现重复项时增加它们的值,如果没有,则重置行号。如果 Qty 是要评估的列,则结果必须显示在以下 table 列 rn 中:

+----------+----------+-----+-------------+-----------+----+
| UniqueId |    Id    | Qty | RetailPrice | SortOrder | rn |
+----------+----------+-----+-------------+-----------+----+
|     3124 | 92361725 |  25 |      269.99 |         1 |  1 |
|     2627 | 92361725 |  25 |      269.99 |         2 |  2 |
|     7635 | 92361725 |  25 |      269.99 |         3 |  3 |
|     8732 | 92361725 |  25 |      269.99 |         4 |  4 |
|     3791 | 92361725 |  20 |      269.99 |         5 |  1 |
|     4328 | 92361725 |  25 |      269.99 |         6 |  1 |
+----------+----------+-----+-------------+-----------+----+

我尝试使用 ROW_NUMBER() 函数,但无法得到我想要的结果

;WITH Table1 AS(
SELECT 3124 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 1 SortOrder UNION ALL
SELECT 2627 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 2 SortOrder UNION ALL
SELECT 7635 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 3 SortOrder UNION ALL 
SELECT 8732 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 4 SortOrder UNION ALL
SELECT 3791 UniqueId,92361725 Id, 20 Qty, 269.99 RetailPrice, 5 SortOrder UNION ALL
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 6 SortOrder
)

SELECT UniqueId, Id, Qty, RetailPrice, SortOrder,
ROW_NUMBER() OVER (PARTITION BY Qty ORDER BY SortOrder) rn
FROM Table1
+----------+----------+-----+-------------+-----------+----+
| UniqueId |    Id    | Qty | RetailPrice | SortOrder | rn |
+----------+----------+-----+-------------+-----------+----+
|     3791 | 92361725 |  20 |      269.99 |         5 |  1 |
|     3124 | 92361725 |  25 |      269.99 |         1 |  1 |
|     2627 | 92361725 |  25 |      269.99 |         2 |  2 |
|     7635 | 92361725 |  25 |      269.99 |         3 |  3 |
|     8732 | 92361725 |  25 |      269.99 |         4 |  4 |
|     4328 | 92361725 |  25 |      269.99 |         6 |  5 |
+----------+----------+-----+-------------+-----------+----+

Order By 完全被忽略了,有人可以帮忙吗?

给你。因为你是在 2008 年,所以我通过在 SortOrder +/- 1 上自我加入这个 table 来复制 Lead 和 Lag。我还更新了你的样本集以说明数量为 25 的新岛屿。

抱歉文字太长,但我必须更新您的示例集以向岛屿 3 添加 2 行并创建 2 个 CTE 以获得岛屿范围。

--Updates Sample Set with 3 Islands.
WITH Table1 AS(
SELECT 3124 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 1 SortOrder UNION ALL --Island 1
SELECT 2627 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 2 SortOrder UNION ALL --Island 1
SELECT 7635 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 3 SortOrder UNION ALL --Island 1
SELECT 8732 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 4 SortOrder UNION ALL --Island 1
SELECT 3791 UniqueId,92361725 Id, 20 Qty, 269.99 RetailPrice, 5 SortOrder UNION ALL --Island 2
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 6 SortOrder UNION ALL --Island 3
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 7 SortOrder UNION ALL --Island 3
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 8 SortOrder           --Island 3
),

--Creating a CTE to get the Lead and Lag since this is 2008. This will allow us to determine if a row is the first or last row of an island.
LeadLagTable AS(
SELECT
    Table1.UniqueId,
    Table1.Id,
    Table1.Qty,
    Table1.RetailPrice,
    Table1.SortOrder,
    LeadTable.SortOrder AS LeadSortOrder,
    LagTable.SortOrder AS LagSortOrder,
    CASE
        WHEN LagTable.SortOrder IS NULL THEN 1
        ELSE 0
        END AS StartRowFlag,
    CASE
        WHEN LeadTable.SortOrder IS NULL THEN 1
        ELSE 0
        END AS LastRowFlag
FROM Table1
LEFT JOIN Table1 LeadTable ON
    Table1.SortOrder = LeadTable.SortOrder - 1
    AND Table1.Qty = LeadTable.Qty
LEFT JOIN Table1 LagTable ON
    Table1.SortOrder = LagTable.SortOrder + 1
    AND Table1.Qty = LagTable.Qty
),

--With the LeadLagTable we can now get the ranges for each island, as well as a unique ID for each island.
Ranges AS (
SELECT
    RangeStart,
    RangeEnd,
    ROW_NUMBER() OVER (ORDER BY RangeStart) AS RangeRowNum
FROM (
    SELECT
        StartRow.SortOrder AS RangeStart,
        EndRow.SortOrder RangeEnd,
        ROW_NUMBER() OVER (PARTITION BY StartRow.SortOrder ORDER BY EndRow.SortOrder) AS rn
    FROM LeadLagTable StartRow
    JOIN LeadLagTable EndRow ON
        StartRow.StartRowFlag = 1
        AND EndRow.LastRowFlag = 1
        AND StartRow.SortOrder <= EndRow.SortOrder
        AND StartRow.Qty = EndRow.Qty
    ) tbl
WHERE rn = 1
)

这是实际的查询。

--We now join on the island ranges, and partition by the Island ID.
SELECT
    UniqueId,
    Id,
    Qty,
    RetailPrice,
    SortOrder,
    ROW_NUMBER() OVER (PARTITION BY RangeRowNum ORDER BY SortOrder) AS rn
FROM Table1
LEFT JOIN Ranges ON
    Table1.SortOrder >= Ranges.RangeStart
    AND Table1.SortOrder <= Ranges.RangeEnd