خانه/ مبانی SQL/ TOP

TOP: نمایش فقط چند ردیف اول

مبتدی ۱۲ دقیقه مطالعه

حالا که با ORDER BY می‌توانی نتیجه را مرتب کنی، سوال بعدی این است: خیلی وقت‌ها فقط به چند ردیف اول این نتیجه‌ی مرتب‌شده نیاز داری — مثلاً «۵ دانش‌آموز برتر» یا «۱۰ محصول پرفروش». نوشتن کل نتیجه و بعد نگاه‌کردن به چند ردیف اولش، هم غیرضروری است و هم کند. دستور TOP دقیقاً همین محدودسازی را در خودِ پایگاه‌داده انجام می‌دهد.

ساختار پایه

sql
SELECT TOP (5) full_name, grade
FROM students
ORDER BY grade DESC;
نکته‌ی حیاتی: TOP تقریباً همیشه باید همراه ORDER BY بیاید. یادت هست در درس قبل گفتیم بدون ORDER BY، هیچ ترتیب تضمین‌شده‌ای وجود ندارد؟ پس TOP (5) بدون ORDER BY یعنی «۵ ردیف اول، به هر ترتیبی که پایگاه‌داده اتفاقی پیدایشان کرده» — نه لزوماً ۵ ردیف برتر واقعی.

TOP بر اساس درصد

به‌جای عدد ثابت، می‌توان درصدی از کل ردیف‌ها را هم خواست:

sql
SELECT TOP (50) PERCENT full_name, grade
FROM students
ORDER BY grade DESC;
-- یعنی نیمه‌ی بالای دانش‌آموزان بر اساس نمره

مدیریت تساوی با WITH TIES

فرض کن TOP (3) خواسته‌ای، اما نفر سوم و چهارم دقیقاً نمره‌ی یکسانی دارند. به‌طور پیش‌فرض، TOP دقیقاً همان عدد را برمی‌گرداند و بین نفر سوم و چهارم یکی را کاملاً اتفاقی انتخاب می‌کند. اگر بخواهی همه‌ی ردیف‌های هم‌تراز با آخرین ردیف هم در نتیجه بمانند، از WITH TIES استفاده کن:

sql
SELECT TOP (3) WITH TIES full_name, grade
FROM students
ORDER BY grade DESC;
-- اگر چند نفر آخر تراز باشند، ممکن است بیش از ۳ ردیف برگردد

صفحه‌بندی نتایج با OFFSET ... FETCH NEXT

وقتی می‌خواهی نتیجه را صفحه‌به‌صفحه نشان دهی (مثلاً «صفحه‌ی دوم لیست سفارش‌ها»)، به‌جای TOP، الگوی مدرن‌تری در SQL Server وجود دارد:

sql
-- صفحه‌ی اول: ۳ ردیف اول
SELECT full_name, grade
FROM students
ORDER BY grade DESC
OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY;

-- صفحه‌ی دوم: ۳ ردیف بعدی
SELECT full_name, grade
FROM students
ORDER BY grade DESC
OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY;

OFFSET مشخص می‌کند از ابتدا چند ردیف رد شود، و FETCH NEXT ... ROWS ONLY مشخص می‌کند بعد از آن، چند ردیف برداشته شود. برخلاف TOP، این الگو همیشه به ORDER BY نیاز دارد و نمی‌توان بدونش نوشتش.

TOP و صفحه‌بندی در Playground این سایت

این‌جا یکی دیگر از تفاوت‌های آشکار بین SQL Server و SQLite است: SQLite اصلاً TOP یا OFFSET ... FETCH NEXT ندارد. به‌جایش، از کلمه‌ی کلیدی ساده‌تر LIMIT استفاده می‌کند — که در واقع در MySQL و PostgreSQL هم همین LIMIT رایج است.

SQL ServerSQLite (این Playground)
SELECT TOP (5) * FROM t ORDER BY x;SELECT * FROM t ORDER BY x LIMIT 5;
OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLYLIMIT 3 OFFSET 3

بیا اول معادل TOP را امتحان کنیم — سه دانش‌آموز برتر بر اساس نمره:

امتحانش کن — معادل TOP با LIMIT

و حالا معادل صفحه‌بندی — صفحه‌ی دوم لیست، با فرض این‌که هر صفحه ۲ ردیف داشته باشد:

امتحانش کن — صفحه‌بندی با LIMIT/OFFSET
در پرس‌وجوی بالا، OFFSET 2 یعنی «دو ردیف اول را رد کن»، و LIMIT 2 یعنی «فقط دو ردیف بعدی را بردار» — دقیقاً همان مفهوم صفحه‌ی دوم، در قالبی ساده‌تر از OFFSET ... FETCH NEXT.

جمع‌بندی این درس

  • TOP (n) فقط n ردیف اول نتیجه را برمی‌گرداند و تقریباً همیشه باید همراه ORDER BY بیاید.
  • TOP (n) PERCENT درصدی از کل ردیف‌ها را برمی‌گرداند.
  • WITH TIES ردیف‌های هم‌تراز با آخرین ردیف را هم نگه می‌دارد.
  • برای صفحه‌بندی در SQL Server از OFFSET ... ROWS FETCH NEXT ... ROWS ONLY استفاده می‌شود.
  • در SQLite (و MySQL/PostgreSQL)، معادل ساده‌تری به نام LIMITLIMIT ... OFFSET ...) وجود دارد.

با این درس، فصل ۲ (مبانی SQL) تقریباً تمام شد. در آخرین درس این فصل، سراغ CASE می‌رویم: یاد می‌گیریم چطور داخل یک پرس‌وجو، منطق شرطی «اگر... آنگاه...» بنویسیم.