随机订单设置为特定日期
Random order set to certain date
有没有办法对事件列表进行随机排序,并且只在当天保持这种顺序?涉及分页,因此缓存并不是一个好的选择。
我知道我可以按 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
下面我将tablesortme
定义为:
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)));
如果 <seed>
相同,rand()
保证生成的值相同。所以我们检查了这一点。有点...因为每一行的值也相同。因此,将 rand(<seed>)
用于固定的 <seed>
将不会有效地执行任何操作。
我们可以尝试通过将随机值绑定到结果的键来克服这个问题。一天的随机值是 stable,一天是键,即键标识的行。
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));
全天的散列将是 stable,一行的键因为它仅取决于这些值。而且(某些)散列函数分散得很好,这使得结果“看起来很随机”。
从 table 中删除或插入当然会导致行在其他“旧”行或剩余行之间的某处出现或消失。但是如果我们使用的键是 stable,就像一个不填补空白的自动增量一样,“旧”行或剩余行之间的顺序无论如何都会是 stable .
当然,请注意,就不可预测性而言,这不是随机的table!
但我认为它的目的只是为了改善用户体验,每天呈现一个“感觉”随机的结果,使内容更加有趣和令人兴奋。它应该足够好。
有没有办法对事件列表进行随机排序,并且只在当天保持这种顺序?涉及分页,因此缓存并不是一个好的选择。
我知道我可以按 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
下面我将tablesortme
定义为:
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)));
如果 <seed>
相同,rand()
保证生成的值相同。所以我们检查了这一点。有点...因为每一行的值也相同。因此,将 rand(<seed>)
用于固定的 <seed>
将不会有效地执行任何操作。
我们可以尝试通过将随机值绑定到结果的键来克服这个问题。一天的随机值是 stable,一天是键,即键标识的行。
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));
全天的散列将是 stable,一行的键因为它仅取决于这些值。而且(某些)散列函数分散得很好,这使得结果“看起来很随机”。
从 table 中删除或插入当然会导致行在其他“旧”行或剩余行之间的某处出现或消失。但是如果我们使用的键是 stable,就像一个不填补空白的自动增量一样,“旧”行或剩余行之间的顺序无论如何都会是 stable .
当然,请注意,就不可预测性而言,这不是随机的table!
但我认为它的目的只是为了改善用户体验,每天呈现一个“感觉”随机的结果,使内容更加有趣和令人兴奋。它应该足够好。