Làm cách nào để sử dụng ROW_NUMBER ()?


175

Tôi muốn sử dụng ROW_NUMBER()để có được ...

  1. Để có được max(ROW_NUMBER())-> Hoặc tôi đoán đây cũng sẽ là tổng số của tất cả các hàng

Tôi đã thử làm:

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

nhưng nó dường như không hoạt động ...

  1. Để có được ROW_NUMBER()bằng cách sử dụng một phần thông tin nhất định, tức là. nếu tôi có một cái tên và tôi muốn biết cái tên đó đến từ đâu.

Tôi cho rằng nó sẽ giống với những gì tôi đã cố gắng cho # 1

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

nhưng điều này cũng không hoạt động ...

Bất kỳ ý tưởng?

Câu trả lời:


150

Đối với câu hỏi đầu tiên, tại sao không chỉ sử dụng?

SELECT COUNT(*) FROM myTable 

để có được số đếm.

Và đối với câu hỏi thứ hai, khóa chính của hàng là thứ nên được sử dụng để xác định một hàng cụ thể. Đừng thử và sử dụng số hàng cho điều đó.


Nếu bạn đã trả về Row_Number () trong truy vấn chính của mình,

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

Sau đó, khi bạn muốn quay lại 5 hàng thì bạn có thể lấy số hàng hiện tại và sử dụng truy vấn sau để xác định hàng với currentrow -5

SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
     FROM User ) us 
WHERE Row = CurrentRow - 5   

Trong tình huống của tôi, tôi đã được cấp một UserId và tôi muốn nhận lại UserId đó là một số hàng nhất định. Điều gì nếu một hàng bị xóa? Trong trường hợp đó, tôi không thể chỉ sử dụng UserId - offset, vì sau đó tôi sẽ không nhận được bản ghi đúng.

Tốt hơn hết là sử dụng số đếm chọn (1) từ mytable để chọn số lượng bản ghi. Điều này rất nhanh chóng và hiệu quả
Sivajith

46

Mặc dù tôi đồng ý với những người khác rằng bạn có thể sử dụng count()để có được tổng số hàng, đây là cách bạn có thể sử dụng row_count():

  1. Để có được tổng số hàng:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp
  2. Để lấy số hàng có tên là Matt:

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

Bạn có thể sử dụng thêm min(rownum)hoặc max(rownum)để có được hàng đầu tiên hoặc cuối cùng cho Matt tương ứng.

Đây là những triển khai rất đơn giản row_number(). Bạn có thể sử dụng nó để nhóm phức tạp hơn. Kiểm tra phản hồi của tôi về nhóm nâng cao mà không sử dụng truy vấn phụ


Bạn có thể giải thích làm thế nào để chọn cột, được sử dụng trong order by X? Nói cách khác, nên Xxác định như thế nào? Cảm ơn!
Kevin Meredith

@KevinMeredith: Thứ order by Xtự bạn sẽ sử dụng để xác định thứ tự các hàng sẽ được chỉ định ROW_NUMBERS(). Hãy nhớ rằng các bảng trong cơ sở dữ liệu quan hệ, mặc dù tên của chúng, không có thứ tự chính thức, vì vậy nếu bạn muốn gọi một hàng "1" hoặc "10" hoặc "1337", trước tiên bạn cần phải đặt hàng chúng bằng cách sử dụng ORDER BYmệnh đề là một trong đó đi trong OVER (ORDER BY X)mệnh đề.
Wtrmute

25

Nếu bạn cần trả về tổng số hàng của bảng, bạn có thể sử dụng một cách khác cho SELECT COUNT(*)câu lệnh.

Bởi vì SELECT COUNT(*)thực hiện quét toàn bộ bảng để trả về số hàng, có thể mất nhiều thời gian cho một bảng lớn. Bạn có thể sử dụng sysindexesbảng hệ thống thay thế trong trường hợp này. Có một ROWScột chứa tổng số hàng cho mỗi bảng trong cơ sở dữ liệu của bạn. Bạn có thể sử dụng câu lệnh chọn sau:

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

Điều này sẽ làm giảm đáng kể thời gian truy vấn của bạn.


Bạn đã đúng về việc quét toàn bộ bảng, nhưng lưu ý rằng nó không nhất thiết phải là quét chỉ mục theo cụm, vì nó có thể sử dụng một chỉ mục không được nhóm cho điều đó
yoel halb

2
Ngoài ra, điều này chỉ đúng với Sql-Server, vì các RDMBS khác đã tối ưu hóa số lượng chọn
yoel halb

7

ROW_NUMBER() trả về một số duy nhất cho mỗi hàng bắt đầu bằng 1. Bạn có thể dễ dàng sử dụng số này bằng cách viết đơn giản:

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

Bạn có thể tìm thấy sự khác biệt giữa Row_number(), Rank()Dense_Rank() ở đây .


7

Bạn có thể sử dụng điều này để có được bản ghi đầu tiên trong đó có mệnh đề

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'

Để liệt kê tất cả các hàng - nếu không, bạn chỉ liệt kê các hàng có tên người dùng là Joe, đây không phải là mục tiêu ;-).
Alex Martelli

1
@Matt: Gọi tôi là giáo viên; Tôi có xu hướng thích "bảng dẫn xuất" hoặc "chế độ xem ẩn danh" cho cụm từ "chọn phụ".
Mechanical_meat

1
@adam, vì tôi cũng là một nhà giáo - liệu "lồng nhau chọn" có làm bạn hạnh phúc hơn không? Tôi không thích sử dụng các thuật ngữ như bảng hoặc chế độ xem khi không có TABLEhoặc VIEWtừ khóa ở xung quanh ... nhưng SELECTchắc chắn là vậy! -)
Alex Martelli

@Alex: bạn trình bày một điểm hợp lệ. "Nested select" hoạt động rất tốt cho tôi :) Nhân tiện, tôi thực sự thích đọc những giai thoại bạn thêm vào nhận xét và câu trả lời của mình.
Mechanical_meat

@Adam, cảm ơn! Đôi khi câu trả lời của tôi rất đơn giản, như ở đây, nhưng tôi rất thích làm thịt chúng khi tôi có một phút rảnh rỗi ;-).
Alex Martelli

4

Có thể không liên quan đến câu hỏi ở đây. Nhưng tôi thấy nó có thể hữu ích khi sử dụng ROW_NUMBER-

SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID 
FROM #Any_Table

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

Nếu bạn hoàn toàn muốn sử dụng ROW_NUMBER cho việc này (thay vì đếm (*)), bạn luôn có thể sử dụng:

SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)   
FROM USERS  
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC

2

Bạn có thể sử dụng Row_Numbercho kết quả truy vấn giới hạn.

Thí dụ:

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

- Với truy vấn trên, tôi sẽ nhận được TRANG 1 kết quả từ TABLENAME.


2

Cần tạo bảng ảo bằng cách sử dụng WITH table AS, được đề cập trong Truy vấn đã cho.

Bằng cách sử dụng bảng ảo này, bạn có thể thực hiện thao tác CRUD wrt row_number.

TRUY VẤN:

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

Bạn có thể sử dụng INSERT, UPDATEhoặc DELETEtrong câu cuối bằng cách bất chấp SELECT.


0

Hàm SQL Row_Number () là sắp xếp và gán số thứ tự cho các hàng dữ liệu trong tập bản ghi liên quan. Vì vậy, nó được sử dụng để đánh số hàng, ví dụ để xác định 10 hàng hàng đầu có số lượng đặt hàng cao nhất hoặc xác định đơn hàng của mỗi khách hàng là số tiền cao nhất, v.v.

Nếu bạn muốn sắp xếp tập dữ liệu và đánh số mỗi hàng bằng cách tách chúng thành các danh mục, chúng tôi sử dụng Row_Number () với mệnh đề phân vùng. Ví dụ: sắp xếp các đơn đặt hàng của từng khách hàng trong chính bộ dữ liệu chứa tất cả các đơn đặt hàng, v.v.

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

Nhưng theo tôi hiểu, bạn muốn tính số lượng hàng được nhóm theo một cột. Để trực quan hóa yêu cầu, nếu bạn muốn xem tổng số đơn đặt hàng của khách hàng có liên quan dưới dạng cột riêng biệt bên cạnh thông tin đơn hàng, bạn có thể sử dụng hàm tổng hợp COUNT () với mệnh đề Phân vùng theo

Ví dụ,

SELECT
    SalesOrderNumber,
    CustomerId,
    COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader

0

Truy vấn này:

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

sẽ trở lại tất cả các hàng nơi UserName'Joe'trừ khi bạn có khôngUserName='Joe'

Chúng sẽ được liệt kê theo thứ tự UserIDrow_numbertrường sẽ bắt đầu bằng 1 và gia tăng tuy nhiên nhiều hàng chứaUserName='Joe'

Nếu nó không hoạt động với bạn thì WHERElệnh của bạn có vấn đề HOẶC không có UserIDtrong bảng. Kiểm tra chính tả cho cả hai lĩnh vực UserIDUserName.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.