ROW_NUMBER для создания на PARTITION с повторяющимся значением Order By - PullRequest
0 голосов
/ 25 марта 2020

Я получаю доступ к представлению на 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 перезаписывает внутренний порядок строк с повторяющимися значениями. Есть ли способ обойти это, получить желаемый результат.

1 Ответ

2 голосов
/ 25 марта 2020

Во-первых, вы должны знать, что когда дело доходит до реляционных баз данных, не существует такого понятия, как «Естественный порядок». Это заблуждение.
На самом деле, это такое распространенное заблуждение, что я написал сообщение в блоге об этом, потому что, несмотря на то, что оно было опровергнуто очень многими профессионалами на многих сайтах, Есть еще слишком много разработчиков, которые становятся жертвами этого заблуждения.

Теперь, сказав, что я предполагаю, что различные статусы должны быть упорядочены по правилам порядка бизнес-логики c - и это можно сделать, используя либо таблица состояний, содержащая столбец для сортировки по ним, или с помощью выражения case в предложении order by.

Этот оператор 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...