今天遇到一個新需求,某個案件由於希望列表各物件的露出是公平的,也就是說,按照編號、時間等方式排序都不公平,希望能夠用亂數隨機排序。
環境是 SQL SERVER 配合 ASP.NET,分頁使用 AspNetPager 控制項。
這個需求看似相當容易,使用 ORDER BY NEWID() 就好了呀,但列表還要分頁呢,使用者若按下一頁,第二頁又不該出現第一頁的物件。
想到很多方法 … 可以用臨時表作、也或許可以做一隻已經亂數排好的資料 xml 以 jQuery 方式載入呈現 …
不過在拜請 Google 大神後發現一個相當有趣的作法,以 T-SQL 將某個種子值以 md5 方式編碼,並作為排序的依據。此種子值可在使用者進入頁面後給予,並塞入 Session 中,確保此使用者翻頁時還是同一種子值。
如同 StackOverflow 上 ccook 前輩所提供的範例 Code:
[code language=”SQL”]
–宣告一種子值,實際在 ASP.NET 中使用,可以將此值塞入 Session 中,確保使用者翻頁時是使用同一種子值
declare @seed as int;
–可試著將 @seed 值改變,可發現每一種 @seed 值都各有固定排序
set @seed = 10;
–建立一範例使用的表
create table temp (
id int,
date datetime)
–塞入幾筆資料
insert into temp (id, date) values (1,’20090119′)
insert into temp (id, date) values (2,’20090118′)
insert into temp (id, date) values (3,’20090117′)
insert into temp (id, date) values (4,’20090116′)
insert into temp (id, date) values (5,’20090115′)
insert into temp (id, date) values (6,’20090114′)
–將種子值以 md5 方式編碼,並以此作為排序依據
select *, HASHBYTES(‘md5’,cast(id+@seed as varchar)) r
from temp order by r
–1 2009-01-19 00:00:00.000 0x6512BD43D9CAA6E02C990B0A82652DCA
–5 2009-01-15 00:00:00.000 0x9BF31C7FF062936A96D3C8BD1F8F2FF3
–4 2009-01-16 00:00:00.000 0xAAB3238922BCC25A6F606EB525FFDC56
–2 2009-01-18 00:00:00.000 0xC20AD4D76FE97759AA27A0C99BFF6710
–3 2009-01-17 00:00:00.000 0xC51CE410C124A10E0DB5E4B97FC2AF39
–6 2009-01-14 00:00:00.000 0xC74D97B01EAE257E44AA9D5BADE97BAF
–將範例表刪掉
drop table temp
[/code]
資料來源:http://stackoverflow.com/questions/458175/pseudo-random-sort-in-ms-sql-not-newid-and-not-rand