برای گرفتنِ آخرین ردیفِ هر پرونده در SQL،صرفِ MAXِ زمان کافی نیست که تمامِ ستونهای همان ردیف با قاعدهٔ روشن انتخاب شوند. تساویِ زمان را باید تعیین تکلیف کنیم. در این تمرین، ROW_NUMBERباPARTITION BYوORDER BYِ کامل یک ردیفِ معلوم برای هر گروه برمیگزیند؛ نتیجه با مرجعِ مستقل سنجیده میشود و تاریخچه باقی میماند.
«آخرین» طبق کدام کلید؟
دادهٔ اصیلِ ما دو موجودیتِ AوBدارد. برایAشناسهٔ۱درزمان۱۰و۲و۳درزمان۲۰هستند؛ برایBشناسهٔ۴درزمان۵و۵و۶درزمان۸قرار دارند. payloadِ ردیفهای همزمان متفاوت است. ستونِ tفقط کلیدِ عددیِ ساختهشده برای ترتیب است؛ زمانِ وقوعِ معتبر یا تاریخِ حکمِ واقعی نیست.
قراردادِ انتخاب این است:بزرگترینtو در تساوی،بزرگترینid. این سیاست ردیفِ۳برایAو۶برایBرا تعیین میکند. بزرگتر بودنِidدلیلِ واقعیِ جدیدتر بودنِ رویداد نیست؛ فقط تساوی را قطعی میشکند. اگر دامنهٔ شما ترتیبِ دیگری لازم دارد،همان قرارداد را پیش از queryمشخص کنید.
مشکلِ ستونِ بیرون از aggregate را دقیق بگوییم
یک queryآزمایشی entity،id،payloadوMAX(t)را با GROUP BY entityمیخواند. idوpayloadدرaggregateیاGROUP BYنیستند و bare columnنام دارند. رفتارِ این queryرا برای همهٔ پایگاههای SQLیکسان معرفی نمیکنیم؛ SQLiteبرای یک MINیاMAXِ داخلی استثنایِ مشخص دارد.
طبقِ مستندِ SQLite،در حالتِ یکMIN/MAXِ داخلی،مقدارهای bareاز ردیفی با همان کمینه/بیشینه میآیند؛ اما اگر بیشینه در چند ردیف تکرار شده باشد،انتخاب میانِ آنها تضمینِ قاعدهٔ idِ ما را ندارد. بنابراین نمیگوییم MAXهمیشه payloadِ بیربط میدهد؛ مسئلهٔ این داده تساویِ واقعیِ بیشینه و نبودِ قراردادِ انتخابِ دلخواه است.
شمارهٔ ردیف را در هر گروه بسازیم
در CTEِ rankedاز ROW_NUMBER() OVER(PARTITION BY entity ORDER BY t DESC,id DESC)استفاده میکنیم. هر گروه جدا شماره میگیرد و بزرگترین زوجِ ترتیب،rn=۱میشود. سپس در SELECTِ بیرونی فقطrn=۱را انتخاب میکنیم؛ فیلتر را در همان مرحلهٔ محاسبهٔ windowحدس نمیزنیم.
| گروه | نامزدهای بیشترینt | قراردادِ تساوی | شناسهٔ منتخب |
|---|---|---|---|
| A | ۲و۳،هردوt=۲۰ | idبزرگتر | ۳ |
| B | ۵و۶،هردوt=۸ | idبزرگتر | ۶ |
خروجی شاملِ id،entity،tوpayloadِ همان ردیف است؛ فقط عددِ زمان را جدا برنمیداریم. تابعِ مستقلِ Pythonبرای هر گروه maxِ زوجِ(t,id)را از فهرستِ اولیه میگیرد و برابریِ تمامِ ستونها را assert میکند. این کنترل از ROW_NUMBERاستفاده نمیکند.
ترتیبِ window،ترتیبِ خروجیِ نهایی نیست
ORDER BYداخلِ OVERشمارهگذاریِ هر گروه را تعیین میکند. ترتیبِ نمایشِ نتیجهٔ کل را SELECTِ بیرونی باید معلوم کند. نمونه ابتدا ORDER BY entity ASCدارد و شناسههای۳و۶را میدهد؛ با همان windowوORDER BY entity DESCبیرونی،۶و۳میآیند. ردیفهای برنده عوض نشدهاند،فقط ترتیبِ نتیجه تغییر کرده است.
بدونِ ORDER BYنهایی،از شکلِ اتفاقیِ یک اجرای کوچک ترتیبِ همیشگی نسازید. همچنین اگر کلیدِ تساویِ یکتا در windowنباشد،شمارهٔ یک برای ردیفهای همرتبه میتواند مطابقِ انتظارِ شما تعیین نشود. عددِ یک نشانهٔ درستبودنِ قراردادِ کسبوکار نیست؛ باید ستونهای مرتبسازی درست انتخاب شده باشند.
تاریخچه را حذف نکردیم
در پایان،COUNTِ جدول هنوز۶است. این queryفقط یک نمایِ منتخب میسازد؛ ردیفهای قدیمی را پاک یا بهروزرسانی نمیکند. یک پرونده ممکن است برای سؤالِ تاریخی به وضعیتِ قبلی نیاز داشته باشد. آخرین ردیفِ ثبتشده هم لزوماً حکمِ معتبرِ امروز نیست؛ زمانِ ورود،وقوع و اعتبار را با هم یکی نکنید.
فیلترِ نسخه و تاریخِ اجرا میگوید سندِ تازهتر ممکن است هنوز لازمالاجرا نباشد. مدلِ تلاش و مکالمه هم معنایِ موجودیت و زمان را جدا میکند. این صفحه فقط انتخابِ یک ردیفِ کامل با سیاستِ صریحِ تساوی را اجرا کرده است.
چه چیزهایی در تمرین نیست؟
NULLدر کلیدِ زمان،collationِ متن،دادهٔ دیررس،تراکنشِ همزمان و اعتبارِ معناییِ payloadآزموده نشدهاند. همهٔ شش ردیف در SQLiteِ حافظهای هستند و نسخه در گزارش ثبت شده است. هیچ پایگاهِ واقعی،تماس یا پروندهٔ مشتری خوانده و تغییر داده نمیشود؛ خروجی یک benchmarkهم نیست.
برای بررسیِ گزارشِ اپرابین یا اتصالِ وضعیتِ درخواست،تعریفِ «آخرین» و شاهدِ معتبر را با تیمِ فنی روشن کنید. استفاده ازSQLiteیاwindowfunctionدر محصول از این مثال نتیجه نمیشود. یک جدولِ کوچک با دو زمانِ مساوی میتواند پیش از اتصالِ عملی،ابهامِ قرارداد را آشکار کند.
فایل تمرین و منبع
کدِ کاملِ محلی و کنترلهای اصیلِ تمرین · دادهٔ ساختگی و خروجیِ اجرای واقعی
- SQLite Window Functions؛ مثالِROW_NUMBERو تفاوتِwindow orderباfinalorder،بخشPARTITION BY؛ فقط قسمتهای مرتبط خوانده شدند
- SQLite SELECT،بخش۲٫۵؛ bare columnو استثنایِ یکMIN/MAXِ داخلی و محدودیتِ تساوی
منابع در 2026-11-04 خوانده شدند؛ این تاریخ، تاریخ انتشار منبع نیست. مثالها و فایلهای این راهنما آموزشی و ساختهٔ تحریریهاند.