Как я могу использовать ROW_NUMBER ()?

175

Я хочу использовать, ROW_NUMBER()чтобы получить ...

  1. Чтобы получить max(ROW_NUMBER())-> Или я думаю, это также будет счетчик всех строк

Я пытался сделать:

SELECT max(ROW_NUMBER() OVER(ORDER BY UserId)) FROM Users

но это не сработало ...

  1. Чтобы получить ROW_NUMBER()с помощью данного куска информации, т.е. если у меня есть имя, и я хочу знать, из какой строки пришло имя.

Я предполагаю, что это будет что-то похожее на то, что я пытался для # 1

SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'

но это тоже не сработало ...

Любые идеи?

расточитель
источник

Ответы:

151

Для первого вопроса, почему бы просто не использовать?

SELECT COUNT(*) FROM myTable 

чтобы получить счет.

А для второго вопроса первичный ключ строки - это то, что следует использовать для идентификации конкретной строки. Не пытайтесь использовать для этого номер строки.


Если вы вернули Row_Number () в своем основном запросе,

SELECT ROW_NUMBER() OVER (Order by Id) AS RowNumber, Field1, Field2, Field3
FROM User

Затем, если вы хотите вернуться на 5 строк назад, вы можете взять текущий номер строки и использовать следующий запрос, чтобы определить строку с currentrow -5

SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
     FROM User ) us 
WHERE Row = CurrentRow - 5   
Даррел Миллер
источник
В моей ситуации мне дали UserId, и я хочу получить UserId, вернувший определенное количество строк. Что если строка будет удалена? В этом случае я не могу просто использовать UserId - offset, потому что тогда я не получу правильную запись.
Лучше использовать select count (1) из mytable, чтобы выбрать количество записей. Это так быстро и эффективно
Шиваджит
46

Хотя я согласен с другими, что вы можете использовать, count()чтобы получить общее количество строк, вот как вы можете использовать row_count():

  1. Чтобы получить общее количество строк:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp
  2. Чтобы получить номера строк, где имя Мэтт:

    with temp as (
        select name, row_number() over (order by id) as rownum
        from table_name
    )
    select rownum from temp where name like 'Matt'

Вы можете в дальнейшем использовать min(rownum)или, max(rownum)чтобы получить первый или последний ряд для Мэтта соответственно.

Это были очень простые реализации row_number(). Вы можете использовать его для более сложной группировки. Проверьте мой ответ на Расширенные группировки без использования подзапроса

SO User
источник
Не могли бы вы объяснить, как выбрать столбец, используемый в order by X? Другими словами, как Xопределить? Спасибо!
Кевин Мередит
@KevinMeredith: order by Xэто порядок, который вы будете использовать для определения порядка, в котором будут назначены строки ROW_NUMBERS(). Помните, что таблицы в реляционных базах данных, несмотря на их имя, не имеют формального порядка, поэтому, если вы хотите вызвать строку «1», «10» или «1337», вам нужно сначала упорядочить их, используя ORDER BYпредложение, которое это тот, который идет в OVER (ORDER BY X)пункте.
17
25

Если вам нужно вернуть общее количество строк в таблице, вы можете использовать альтернативный способ SELECT COUNT(*)выражения.

Поскольку SELECT COUNT(*)для получения количества строк выполняется полное сканирование таблицы, для большой таблицы может потребоваться очень много времени. sysindexesВместо этого вы можете использовать системную таблицу. Существует ROWSстолбец, который содержит общее количество строк для каждой таблицы в вашей базе данных. Вы можете использовать следующий оператор выбора:

SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2

Это значительно сократит время, затрачиваемое на ваш запрос.

Мухаммед Ахтар
источник
Вы правы в отношении полного сканирования таблицы, но учтите, что это не обязательно сканирование кластеризованного индекса, поскольку для этого может использоваться некластеризованный индекс
yoel halb
2
Также это верно только для Sql-Server, так как другие RDMBS оптимизировали счетчик выбора
yoel halb
7

ROW_NUMBER() возвращает уникальный номер для каждой строки, начиная с 1. Вы можете легко использовать это, просто написав:

ROW_NUMBER() OVER (ORDER BY 'Column_Name' DESC) as ROW_NUMBER

Вы можете найти разницу между Row_number(), Rank()и Dense_Rank() здесь .

Джатин Фулера
источник
7

Вы можете использовать это для получения первой записи, где есть пункт

SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum 
FROM     Users 
WHERE    UserName = 'Joe'
ORDER BY rownum ASC
Омид Фарвид
источник
4
SELECT num, UserName FROM 
 (SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
  From Users) AS numbered
WHERE UserName='Joe'
Алекс Мартелли
источник
Перечислять все строки - иначе вы просто перечисляете строки, где имя пользователя - Джо, что не является целью ;-).
Алекс Мартелли
1
@Matt: называй меня педантом; Я предпочитаю использовать термин «производная таблица» или «анонимное представление» для термина «дополнительный выбор».
mechanical_meat
1
@adam, так как я педант - разве «вложенный выбор» сделает тебя счастливее? Я не люблю использовать такие термины, как таблица или представление, когда нет TABLEили VIEWключевое слово рядом ... но это SELECTточно так! -)
Алекс Мартелли
@ Алекс: вы представляете правильную точку. «Nested select» прекрасно работает для меня :) Кстати, мне очень нравится читать анекдоты, которые вы добавляете в свои комментарии и ответы.
mechanical_meat
@ Адам, спасибо! Иногда мои ответы очень просты, как здесь, но я люблю их конкретизировать, когда у меня есть свободная минута ;-).
Алекс Мартелли
4

Может не быть связано с вопросом здесь. Но я обнаружил, что это может быть полезно при использовании ROW_NUMBER-

SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID 
FROM #Any_Table
Jyo
источник
3
select 
  Ml.Hid,
  ml.blockid,
  row_number() over (partition by ml.blockid order by Ml.Hid desc) as rownumber,
  H.HNAME 
from MIT_LeadBechmarkHamletwise ML
join [MT.HAMLE] h on ML.Hid=h.HID
Хари Лаккакула
источник
2

Если вы абсолютно хотите использовать для этого ROW_NUMBER (вместо count (*)), вы всегда можете использовать:

SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)   
FROM USERS  
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC
Ричард С
источник
2

Ты можешь использовать Row_Number для ограничения результатов запроса.

Пример:

SELECT * FROM (
    select row_number() OVER (order by createtime desc) AS ROWINDEX,* 
    from TABLENAME ) TB
WHERE TB.ROWINDEX between 0 and 10

- С вышеупомянутым запросом, я получу страницу 1 результатов TABLENAME.

Джонсон Фам
источник
2

Необходимо создать виртуальную таблицу с помощью WITH table AS , который упоминается в данном запросе.

Используя эту виртуальную таблицу, вы можете выполнить операцию CRUD в отношении row_number .

QUERY:

WITH table AS
-
(SELECT row_number() OVER(ORDER BY UserId) rn, * FROM Users)
-
SELECT * FROM table WHERE UserName='Joe'
-

Вы можете использовать INSERT, UPDATEили DELETEв последнем предложении, несмотря на SELECT.

Гаурав Чутке
источник
0

Функция SQL Row_Number () предназначена для сортировки и назначения номера заказа для строк данных в связанном наборе записей. Таким образом, он используется для нумерации строк, например, для определения первых 10 строк, которые имеют наибольшую сумму заказа, или для идентификации заказа каждого клиента, который является наибольшей суммой, и т. Д.

Если вы хотите отсортировать набор данных и пронумеровать каждую строку, разделив их на категории, мы используем Row_Number () с предложением Partition By. Например, сортировка заказов каждого клиента внутри себя, где набор данных содержит все заказы и т. Д.

SELECT
    SalesOrderNumber,
    CustomerId,
    SubTotal,
    ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY SubTotal DESC) rn
FROM Sales.SalesOrderHeader

Но, как я понимаю, вы хотите рассчитать количество строк, сгруппированных по столбцу. Чтобы визуализировать требование, если вы хотите видеть количество всех заказов связанного клиента в виде отдельного столбца, кроме информации о заказе, вы можете использовать функцию агрегирования COUNT () с предложением Partition By

Например,

SELECT
    SalesOrderNumber,
    CustomerId,
    COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader
Eralper
источник
0

Этот запрос:

SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'

вернет все строки, где UserNameесть, 'Joe'если у вас нетUserName='Joe'

Они будут перечислены в порядке UserIDи row_numberполе будет начинаться с 1 и будет увеличиваться, однако многие строки содержатUserName='Joe'

Если это не работает для вас, значит, у вашей WHEREкоманды есть проблема ИЛИ ее нет UserIDв таблице. Проверьте орфографию для обоих полей UserIDи UserName.

Кларк Вера
источник