Как получить позицию записи в таблице (SQL Server)

#sql #sql-server-2008

#sql #sql-server-2008

Вопрос:

Следующая проблема:

Мне нужно получить позицию записи в таблице. Допустим, у меня есть пять записей в таблице:

 Name: john doe, ID: 1
Name: jane doe, ID: 2
Name: Frankie Boy, ID: 4
Name: Johnny, ID: 9
  

Сейчас «Фрэнки Бой» находится на третьей позиции в таблице. Но как получить эту информацию с SQL Server? Я мог бы посчитать идентификаторы, но они ненадежны, у Фрэнки идентификатор 4, но он находится на третьей позиции, потому что запись с идентификатором ‘3’ была удалена.

Есть ли способ? Я знаю о ROW_RANK, но это было бы дорого, потому что мне нужно сначала выбрать в основном весь набор, прежде чем я смогу их ранжировать row_rank.

Я использую MS SQL Server 2008 R2.

Комментарии:

1. Зачем вам нужна позиция записи? Есть ли конкретный запрос, который вы пытаетесь выполнить?

Ответ №1:

В таблицах нет ‘position’. Строки в таблице (=set) идентифицируются по значению их первичного ключа. Только результирующие строки имеют ‘position’, которая может быть детерминированной при наличии ORDER BY предложения. Предположение, что таблицы (= наборы) имеют позицию, приведет только к проблемам и является неправильным мышлением.

Комментарии:

1. Не всегда я понимаю, что вы пытаетесь сказать, но в некоторых случаях, особенно с тем, над чем я работаю, где я экспортирую таблицу ячеек в таблицу результатов. Я хочу выделить число, основанное на условии, которое относится к определенному адресу ячейки. Мне нужно определить адрес этой ячейки перед экспортом в таблицу SQL

2. @EddyJawed: задавайте вопросы как вопросы, а не как комментарий.

Ответ №2:

Вы можете использовать row_number() для «пометки» строк. Вы должны указать способ упорядочивания строк:

 select  row_number() over (order by id) as PositionInTable
,       *
from    YourTable
  

Если производительность является проблемой, вы могли бы сохранить позицию в новом столбце:

 update  yt1
set     PositionInTable = rn
from    YourTable yt1
join    (
        select  row_number() over (order by id) as rn
        ,       id
        from    YourTable
        ) yt2
on      yt1.id = yt2.id
  

С включенным индексом PositionInTable это было бы молниеносно. Но вам пришлось бы обновлять это после каждой вставки в таблицу.

Ответ №3:

Таблицы [концептуально] не упорядочены. Если вы не укажете ORDER BY в инструкции select для упорядочения набора результатов, результаты могут быть возвращены в любом порядке. Повторяющиеся выполнения одного и того же SQL могут возвращать результаты, установленные в разных порядках для каждого выполнения.

Чтобы получить номер строки в определенном результирующем наборе, используйте функцию row_number():

 select row = row_number() over( order by id ) , *
from sysobjects
  

Это позволит присвоить номер строки каждой строке в sysobjects, как если бы таблица была упорядочена по идентификатору.

Ответ №4:

Простым способом сделать это без использования ROW_NUMBER было бы просто подсчитать, сколько строк в таблице имеют индекс, меньший или равный выбранному индексу, это дало бы номер строки.

 SELECT COUNT(*) FROM YourTable WHERE ID <= 4 -- Frankie Boy, Result = 3
  

Возможно, это не самый эффективный способ сделать это для вашего конкретного сценария, но это простой способ добиться этого.