aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL RANK và DENSE_RANK: đồng hạng có làm bỏ số thứ hạng tiếp theo?

Suong Nguyen by Suong Nguyen
07/11/2026
in Backend
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Bảng xếp hạng có hai người cùng 90 điểm. Người tiếp theo nên đứng hạng 4 hay hạng 3? Nếu yêu cầu chưa được chốt, đổi tên hàm trong SQL có thể âm thầm đổi số người được chọn vào danh sách trao thưởng hoặc báo cáo.

Bài đối chiếu PostgreSQL 17 và SQLite ngày 07/11/2026. Ví dụ chạy bằng Python 3.9.6 với SQLite 3.54.0 trong bộ nhớ; chưa chạy PostgreSQL server, ORM hoặc benchmark. Điểm và ID đều là dữ liệu minh họa, không phải bảng xếp hạng thực tế.

Chốt cách xử lý đồng điểm

RANK giữ cùng thứ hạng cho các hàng ngang nhau theo ORDER BY của cửa sổ, rồi để khoảng trống sau nhóm đồng hạng. DENSE_RANK cũng giữ đồng hạng nhưng số tiếp theo liên tục. ROW_NUMBER cấp số riêng cho từng hàng.

Với dãy 100, 90, 90, 70, RANK là 1, 2, 2, 4; DENSE_RANK là 1, 2, 2, 3. Nếu cần đúng hai bản ghi thay vì mọi người thuộc hai mức điểm đầu, đó là một yêu cầu khác.

1. So sánh trên cùng một bảng

Chạy file Python sau để tạo database riêng trong bộ nhớ:

import sqlite3

db = sqlite3.connect(":memory:")
db.executescript("""
    CREATE TABLE demo_scores(id INTEGER PRIMARY KEY, score INTEGER NOT NULL);
    INSERT INTO demo_scores VALUES (1, 100), (2, 90), (3, 90), (4, 70);
""")
rows = db.execute("""
    SELECT id,
           RANK() OVER (ORDER BY score DESC) AS r,
           DENSE_RANK() OVER (ORDER BY score DESC) AS d,
           ROW_NUMBER() OVER (ORDER BY score DESC, id) AS n
    FROM demo_scores
    ORDER BY score DESC, id
""").fetchall()
assert rows == [(1, 1, 1, 1), (2, 2, 2, 2),
                (3, 2, 2, 3), (4, 4, 3, 4)]
print(rows)

ORDER BY bên ngoài quyết định thứ tự trình bày kết quả. ORDER BY trong OVER quyết định nhóm ngang nhau của phép xếp hạng. Hai vị trí có thể phục vụ hai mục đích khác nhau.

ID được dùng làm tiêu chí phụ cho ROW_NUMBER để chọn thứ tự ổn định trong fixture. RANK và DENSE_RANK chỉ nhìn score, nên hai người 90 điểm vẫn là một nhóm đồng hạng.

2. Đừng thêm ID vào mọi cửa sổ theo thói quen

Nếu thêm ID vào ORDER BY của RANK, hai hàng cùng điểm nhưng khác ID không còn ngang nhau theo toàn bộ khóa sắp xếp. Nối tiếp file để thấy ảnh hưởng:

broken_ties = db.execute("""
    SELECT id, RANK() OVER (ORDER BY score DESC, id)
    FROM demo_scores ORDER BY score DESC, id
""").fetchall()
assert broken_ties == [(1, 1), (2, 2), (3, 3), (4, 4)]

top_groups = db.execute("""
    WITH ranked AS (
        SELECT id, score, DENSE_RANK() OVER (ORDER BY score DESC) AS position
        FROM demo_scores
    )
    SELECT id FROM ranked WHERE position <= ? ORDER BY score DESC, id
""", (2,)).fetchall()
assert top_groups == [(1,), (2,), (3,)]
db.close()

Hai mức điểm đầu có ba người, không phải hai người. Test cần kiểm tra số hàng và ID được chọn, không chỉ kiểm tra cột position có giá trị từ 1 đến 2.

CTE tách bước tính thứ hạng khỏi bước lọc nó. Đừng mặc định alias của window function có thể được dùng trực tiếp trong WHERE cùng cấp. Khi chuyển sang query builder, đọc SQL sinh ra để xác nhận cấu trúc tương đương.

Kiểm tra quy tắc trước khi nối vào endpoint

Thêm ca toàn bộ người cùng điểm, chỉ một người và bảng rỗng. Nếu xếp hạng riêng từng nhóm, bổ sung PARTITION BY theo khóa nhóm và fixture có ít nhất hai nhóm để phát hiện xếp hạng toàn bảng ngoài ý muốn.

Điểm trong demo NOT NULL. Với dữ liệu nullable hoặc nhiều tiêu chí nghiệp vụ, chốt cách sắp xếp và khái niệm ngang nhau trước. Không suy ra quy tắc NULL giống nhau ở mọi hệ quản trị chỉ từ fixture SQLite này.

Chọn hàm theo câu hỏi

Dùng RANK cho cách đánh số có khoảng trống sau đồng hạng. Dùng DENSE_RANK khi cần đếm các nhóm giá trị liên tiếp. Dùng ROW_NUMBER khi cần số thứ tự riêng và đã chốt tiêu chí phá hòa.

Bài chưa kiểm tra index hoặc chi phí sắp xếp trên bảng lớn. Sau khi assertions đúng với quy tắc đồng hạng, mới đo kế hoạch truy vấn của hệ quản trị thật. Một câu SQL nhanh nhưng chọn sai người vẫn không đáp ứng yêu cầu của báo cáo.

Nguồn tham khảo

  • PostgreSQL 17: window ranking functions
  • SQLite: rank, dense_rank và peer groups
  • Python: sqlite3

Tags: SQLSQLiteWindow functions
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

COUNT với CASE: vì sao ELSE 0 vẫn đếm cả dòng không khớp?

by Suong Nguyen
08/11/2026
0

Dựng dữ liệu nhỏ để phân biệt COUNT(CASE), SUM(CASE) và FILTER, rồi kiểm tra số đếm khi không có bản ghi.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQLite REPLACE: cột bị bỏ qua có thể mất giá trị cũ

by Suong Nguyen
06/11/2026
0

So sánh INSERT OR REPLACE với ON CONFLICT DO UPDATE để thấy một cột không truyền vào có được giữ lại hay không.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL AND và OR: giữ điều kiện tenant bằng dấu ngoặc đúng chỗ

by Suong Nguyen
05/11/2026
0

Tái hiện lỗi lọc trạng thái làm lọt bản ghi tenant khác và kiểm tra nhóm điều kiện bằng dữ liệu đối chứng.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL LIKE: tìm dấu % và _ như ký tự thật bằng ESCAPE

by Suong Nguyen
04/11/2026
0

Kết hợp bind parameter và ESCAPE để ô tìm kiếm chứa % hoặc _ không vô tình trở thành một mẫu wildcard khác ý định người dùng.

Next Post
Minh họa các khái niệm AI, mạng nơ-ron và lập trình trên máy tính

Log loss: vì sao dự đoán sai càng tự tin càng bị phạt nặng?

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native Platform.select: native và default được chọn theo thứ tự nào?
  • Phỏng vấn JavaScript: vì sao regex.test cùng chuỗi lại đổi kết quả?
  • Android TextView.setText(Int): số đếm có thể bị hiểu thành resource ID

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply