ฉันจะใช้ 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 ได้เพราะฉันจะไม่ได้รับการบันทึกที่ถูกต้อง

มันจะดีกว่าที่จะใช้เลือกนับ (1) จาก mytable เพื่อเลือกจำนวนของบันทึก สิ่งนี้รวดเร็วและมีประสิทธิภาพ
Sivajith

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. วิธีรับหมายเลขแถวที่ชื่อ 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'

คุณสามารถใช้ต่อไปmin(rownum)หรือmax(rownum)เพื่อรับแถวแรกหรือแถวสุดท้ายสำหรับ Matt ตามลำดับ

row_number()เหล่านี้ใช้งานง่ายมากของ คุณสามารถใช้มันสำหรับการจัดกลุ่มที่ซับซ้อนมากขึ้น ตรวจสอบการตอบสนองของฉันเกี่ยวกับการจัดกลุ่มขั้นสูงโดยไม่ต้องใช้แบบสอบถามย่อย


คุณช่วยกรุณาอธิบายวิธีการเลือกคอลัมน์ที่ใช้ในการorder by X? กล่าวอีกนัยหนึ่งควรXกำหนดอย่างไร? ขอบคุณ!
เควินเมเรดิ ธ

@KevinMeredith ที่: เป็นคำสั่งที่คุณจะใช้ในการตรวจสอบการสั่งซื้อที่แถวที่จะได้รับมอบหมายorder by X ROW_NUMBERS()โปรดจำไว้ว่าตารางในฐานข้อมูลเชิงสัมพันธ์แม้จะมีชื่อของพวกเขาไม่มีการสั่งซื้ออย่างเป็นทางการดังนั้นหากคุณต้องการเรียกแถว "1" หรือ "10" หรือ "1337" คุณต้องสั่งซื้อโดยใช้ORDER BYประโยคก่อน เป็นสิ่งที่อยู่ในOVER (ORDER BY X)ข้อ
Wtrmute

25

หากคุณต้องการส่งกลับจำนวนแถวทั้งหมดของตารางคุณสามารถใช้วิธีอื่นในการSELECT COUNT(*)คำสั่ง

เนื่องจากSELECT COUNT(*)ทำให้การสแกนตารางเต็มเพื่อส่งกลับจำนวนแถวจึงอาจใช้เวลานานสำหรับตารางขนาดใหญ่ คุณสามารถใช้sysindexesตารางระบบแทนในกรณีนี้ มีROWSคอลัมน์ที่มีจำนวนแถวทั้งหมดสำหรับแต่ละตารางในฐานข้อมูลของคุณ คุณสามารถใช้คำสั่ง select ต่อไปนี้:

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'

หากต้องการระบุแถวทั้งหมด - มิฉะนั้นคุณจะต้องระบุแถวที่ชื่อผู้ใช้คือ Joe ซึ่งไม่ใช่เป้าหมาย ;-)
Alex Martelli

1
@ Matt: โทรหาฉันคนอวดรู้; ฉันมักจะชอบ "ตารางที่ได้รับ" หรือ "มุมมองที่ไม่ระบุชื่อ" กับคำว่า "เลือกย่อย"
mechanical_meat

1
@adam ในขณะที่ฉันเป็นคนอวดรู้เช่นกัน - "การเลือกซ้อนกัน" จะทำให้คุณมีความสุขมากกว่าเดิมไหม ฉันไม่ชอบกับข้อตกลงการใช้งานเช่นโต๊ะหรือมุมมองเมื่อไม่มีTABLEหรือVIEWคำหลักที่อยู่รอบ ๆ ... แต่SELECTที่แน่นอนคือ -!)
อเล็กซ์เทล

@Alex: คุณแสดงจุดที่ถูกต้อง "เลือกที่ซ้อนกัน" ใช้งานได้ดีสำหรับฉัน :) อย่างไรก็ตามฉันสนุกกับการอ่านเกร็ดเล็กเกร็ดน้อยที่คุณเพิ่มในความคิดเห็นและคำตอบของคุณ
mechanical_meat

@ อดัมขอบคุณ! บางครั้งคำตอบของฉันคือรหัสเปล่ามากเช่นที่นี่ แต่ฉันชอบที่จะเนื้อพวกเขาออกเมื่อฉันมีเวลาว่าง ;-)
Alex Martelli

4

อาจไม่เกี่ยวข้องกับคำถามที่นี่ แต่ฉันพบว่ามันจะมีประโยชน์เมื่อใช้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

หากคุณต้องการใช้ ROW_NUMBER สำหรับสิ่งนี้ (แทนการนับ (*)) คุณสามารถใช้:

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_numberWRT

ค้นหา:

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

คุณสามารถใช้INSERT, UPDATEหรือในประโยคสุดท้ายโดยทั้งๆที่DELETESELECT


0

ฟังก์ชัน SQL Row_Number ()คือการเรียงลำดับและกำหนดหมายเลขคำสั่งให้กับแถวข้อมูลในชุดระเบียนที่เกี่ยวข้อง ดังนั้นจะใช้กับแถวจำนวนตัวอย่างเช่นเพื่อระบุแถว 10 อันดับแรกที่มีจำนวนการสั่งซื้อสูงสุดหรือระบุลำดับของลูกค้าแต่ละรายซึ่งเป็นจำนวนสูงสุด ฯลฯ

หากคุณต้องการเรียงลำดับชุดข้อมูลและหมายเลขแต่ละแถวโดยแยกพวกเขาออกเป็นหมวดหมู่เราใช้ Row_Number () ด้วย Partition By clause ตัวอย่างเช่นการเรียงลำดับคำสั่งซื้อของลูกค้าแต่ละรายภายในตัวของมันเองที่ชุดข้อมูลมีคำสั่งซื้อทั้งหมดเป็นต้น

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

แต่ฉันเข้าใจว่าคุณต้องการคำนวณจำนวนแถวของการจัดกลุ่มตามคอลัมน์ หากต้องการเห็นภาพความต้องการหากคุณต้องการดูจำนวนคำสั่งซื้อทั้งหมดของลูกค้าที่เกี่ยวข้องเป็นคอลัมน์แยกต่างหากนอกเหนือจากข้อมูลการสั่งซื้อคุณสามารถใช้ฟังก์ชันการรวม COUNT () พร้อมพาร์ทิชันตามข้อ

ตัวอย่างเช่น,

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

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ในตาราง ตรวจสอบการสะกดสำหรับทั้งสองช่องและUserIDUserName

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.