有没有办法对事件列表进行随机排序并让它只在当天保持这种状态?涉及分页,因此缓存并不是一个好的选择。
我知道我可以按 NEWID()
进行随机排序,但是如果它从未被缓存并且在第 1 页上包含相同的项目,则会在第 100 页上显示不同的顺序。如果是按日期,那么它会显示排序,无论页面缓存如何,并在第二天重置。
WITH PagedResults AS
(
SELECT CASE WHEN @SortOrder = 'Name' AND @SortDirection = 'DESC' THEN ROW_NUMBER() OVER (ORDER BY ep.Name DESC, ev.Id ASC)
ELSE ROW_NUMBER() OVER (ORDER BY ev.Id ASC) END AS [Row],
CASE WHEN @SortOrder = 'Name' AND @SortDirection = 'DESC' THEN ROW_NUMBER() OVER (ORDER BY ep.Name ASC, ev.Id DESC)
ELSE ROW_NUMBER() OVER (ORDER BY ev.Id DESC)
END AS [RowReverse],
ev.Id,
ep.Name,
)
SELECT
[Row] + RowReverse - 1 AS Total,
[Row],
[RowReverse],
Id,
Name,
FROM PagedResults
WHERE [Row] BETWEEN (((@Page - 1) * @PageSize) + 1) AND (@Page * @PageSize)
ORDER BY [Row], [RowReverse] DESC
答案 0 :(得分:4)
在下面我将使用表 sortme
定义为:
CREATE TABLE sortme
(id integer
IDENTITY (1, 1),
PRIMARY KEY(id));
将 ORDER BY rand(<seed>)
与源自当天的 <seed>
一起使用可能是想到的第一种方法。
DECLARE @today datetime = '2021-01-01 01:01:01';
SELECT *
FROM sortme
ORDER BY rand(convert(integer,
convert(varchar(8),
@today,
112)));
rand()
保证生成的值相同,如果 <seed>
相同。所以我们检查了这一点。有点......因为每一行的值也将相同。因此,将 rand(<seed>)
用于固定的 <seed>
将有效地什么都不做。
我们可以尝试通过将随机值绑定到结果的键来克服这个问题。随机值对于 day 和 key,即 key 标识的行,将在一天内保持稳定。
DECLARE @today datetime = '2021-01-01 01:01:01';
SELECT *
FROM sortme
ORDER BY rand(id * 100000000
+
convert(integer,
convert(varchar(8),
@today,
112)));
但不幸的是,将密钥和我想出的日期相结合的每个(简单)公式确实会产生足够接近每一天的随机值,因此每天的顺序都相同。它没有很好地分散。
现在,如果我们考虑一下,我们想要一个可以很好地分散甚至单调增加的值的函数。这就是哈希函数的领域。
所以我们可以使用 hashbytes()
。
DECLARE @today datetime = '2021-01-01 01:01:01';
SELECT *
FROM sortme
ORDER BY hashbytes('SHA2_512',
concat(convert(varchar(8),
@today,
112),
id));
散列将全天保持稳定,行的键仅取决于这些值。并且(某些)散列函数散布良好的事实使结果“看起来随机”。
从表中删除或插入当然会导致行出现或消失在其他“旧”行或剩余行之间。但是,如果我们使用的键是稳定的,比如不填充间隙的自动增量,那么“旧”或剩余行之间的顺序无论如何都会在一天中保持稳定。
当然,请注意,就不可预测而言,这不是随机的!
但我认为它的目的只是为了改善用户体验,每天呈现一个“感觉”随机的结果,使内容更加有趣和令人兴奋。应该足够了。