TOP: نمایش فقط چند ردیف اول
حالا که با ORDER BY میتوانی نتیجه را مرتب کنی، سوال بعدی این است: خیلی وقتها فقط به چند ردیف اول این نتیجهی مرتبشده نیاز داری — مثلاً «۵ دانشآموز برتر» یا «۱۰ محصول پرفروش». نوشتن کل نتیجه و بعد نگاهکردن به چند ردیف اولش، هم غیرضروری است و هم کند. دستور TOP دقیقاً همین محدودسازی را در خودِ پایگاهداده انجام میدهد.
ساختار پایه
SELECT TOP (5) full_name, grade FROM students ORDER BY grade DESC;
TOP تقریباً همیشه باید همراه ORDER BY بیاید. یادت هست در درس قبل گفتیم بدون ORDER BY، هیچ ترتیب تضمینشدهای وجود ندارد؟ پس TOP (5) بدون ORDER BY یعنی «۵ ردیف اول، به هر ترتیبی که پایگاهداده اتفاقی پیدایشان کرده» — نه لزوماً ۵ ردیف برتر واقعی.TOP بر اساس درصد
بهجای عدد ثابت، میتوان درصدی از کل ردیفها را هم خواست:
SELECT TOP (50) PERCENT full_name, grade FROM students ORDER BY grade DESC; -- یعنی نیمهی بالای دانشآموزان بر اساس نمره
مدیریت تساوی با WITH TIES
فرض کن TOP (3) خواستهای، اما نفر سوم و چهارم دقیقاً نمرهی یکسانی دارند. بهطور پیشفرض، TOP دقیقاً همان عدد را برمیگرداند و بین نفر سوم و چهارم یکی را کاملاً اتفاقی انتخاب میکند. اگر بخواهی همهی ردیفهای همتراز با آخرین ردیف هم در نتیجه بمانند، از WITH TIES استفاده کن:
SELECT TOP (3) WITH TIES full_name, grade FROM students ORDER BY grade DESC; -- اگر چند نفر آخر تراز باشند، ممکن است بیش از ۳ ردیف برگردد
صفحهبندی نتایج با OFFSET ... FETCH NEXT
وقتی میخواهی نتیجه را صفحهبهصفحه نشان دهی (مثلاً «صفحهی دوم لیست سفارشها»)، بهجای TOP، الگوی مدرنتری در SQL Server وجود دارد:
-- صفحهی اول: ۳ ردیف اول 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 Server | SQLite (این Playground) |
|---|---|
SELECT TOP (5) * FROM t ORDER BY x; | SELECT * FROM t ORDER BY x LIMIT 5; |
OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY | LIMIT 3 OFFSET 3 |
بیا اول معادل TOP را امتحان کنیم — سه دانشآموز برتر بر اساس نمره:
و حالا معادل صفحهبندی — صفحهی دوم لیست، با فرض اینکه هر صفحه ۲ ردیف داشته باشد:
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)، معادل سادهتری به نام
LIMIT(وLIMIT ... OFFSET ...) وجود دارد.
با این درس، فصل ۲ (مبانی SQL) تقریباً تمام شد. در آخرین درس این فصل، سراغ CASE میرویم: یاد میگیریم چطور داخل یک پرسوجو، منطق شرطی «اگر... آنگاه...» بنویسیم.