Как заставить ROW_NUMBER работать с дублирующимися записями?

Вопрос: У меня есть таблица с транзакционными записями, которые являются дубликатами. Это неплохие дубликаты, но им нужно присваивать значения, чтобы сделать их уникальными для таблицы. Использование записей - это смотреть на них со временем, я использую ROW_NUMBER, чтобы разделить их по ID и ORDER BY Time. Иногда это работает. Иногда это терпит неудачу. пример CASE

Вопрос:

У меня есть таблица с транзакционными записями, которые являются дубликатами. Это неплохие дубликаты, но им нужно присваивать значения, чтобы сделать их уникальными для таблицы. Использование записей – это смотреть на них со временем, я использую ROW_NUMBER, чтобы разделить их по ID и ORDER BY Time.

Иногда это работает. Иногда это терпит неудачу.

пример

CASE WHEN [Record] = ‘Start’ THEN 0 ELSE -1 + ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC END AS [RowNo]

Ожидаемые результаты

ID, Date, RowNo 2002, 12:30, 1 2002, 12:29, 2 2002, 12:29, 3 2002, 12:29, 4 2002, 12:28, 5 3212, 01:10, 1 3212, 01:09, 2 3212, 01:08, 3

Фактические результаты

ID, Date, RowNo 2002, 12:30, 1 2002, 12:29, 2 <—Right 2002, 12:29, 2 <—Wrong 2002, 12:29, 3 <—Right 2002, 12:28, 4 3212, 01:10, 1 3212, 01:09, 2 3212, 01:08, 3

Есть ли лучший подход к обеспечению точности?

Лучший ответ:

Мммм. ROW_NUMBER() работает с дублирующимися записями. (Когда есть дубликаты, это не детерминировано, какая строка получит какое значение.)

В вашем заявлении есть что-то еще, что не показано. Операция объединения, GROUP BY, некоторая дополнительная фильтрация. Мы не знаем, что это такое, но мы знаем, что ROW_NUMBER() работает с дубликатами.

РЕДАКТИРОВАТЬ

Это подозрительно:

CASE WHEN [Record] = ‘Start’ THEN 0 ELSE -1 + ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC END AS [RowNo]

Я никогда не видел аналитической функции внутри выражения CASE подобного этому раньше. Мне кажется, что ROW_NUMBER() будет оцениваться только в контексте ELSE. (Я не уверен, как SQL Server фактически обрабатывает это.)

Если бы я хотел, чтобы RowNo был 0, 1, 2,… Я бы просто вычитал 1…

ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC) — 1 AS RowNo

Если есть требование включить условие в [Record] = ‘Start’ качестве части оценки ROW_NUMBER, я бы включил это в PARTITION

OVER(PARTITION BY [ID],CASE WHEN [Record]=’Start’ THEN 0 END ORDER BY …)

Если мне нужно было манипулировать значением, возвращаемым ROW_NUMBER(), я бы нашел способ получить эту оценку в контексте встроенного представления или CTE, чтобы получить это оцениваемое и возвращенное, а затем muck with return значение во внешнем запросе.

Дело в том, что ROW_NUMBER() отлично работает с дубликатами. Если вы получаете результаты, которых вы не ожидаете, это потому, что в заявлении происходит что-то еще, например, выражение CASE или соединение или что-то в этом роде.

Ответ №1

Другой способ получить уникальный идентификатор для каждой строки – использовать виртуальный столбец %% Physloc %% (или %% lockres %% в SQL Server 2005), который позволяет идентифицировать физический адрес строки:

SELECT Id, Date, %%Physloc%% FROM [your_table]

Таким образом, вы получаете лучшие результаты для огромных таблиц, чем ROW_NUMBER.

Оцените статью
Добавить комментарий