随机订单设置为特定日期

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> 将不会有效地执行任何操作。

db<>fiddle

我们可以尝试通过将随机值绑定到结果的键来克服这个问题。一天的随机值是 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)));

但不幸的是,将密钥和我想出的那一天结合起来的每个(简单)公式确实每天都会产生足够接近的随机值,因此每天的顺序都是一样的。散的不好

db<>fiddle

现在,如果我们考虑一下,我们想要一个能够很好地分散甚至单调递增值的函数。那就是散列函数的领域。

所以我们可以使用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,一行的键因为它仅取决于这些值。而且(某些)散列函数分散得很好,这使得结果“看起来很随机”。

db<>fiddle

从 table 中删除或插入当然会导致行在其他“旧”行或剩余行之间的某处出现或消失。但是如果我们使用的键是 stable,就像一个不填补空白的自动增量一样,“旧”行或剩余行之间的顺序无论如何都会是 stable .

当然,请注意,就不可预测性而言,这不是随机的table!

但我认为它的目的只是为了改善用户体验,每天呈现一个“感觉”随机的结果,使内容更加有趣和令人兴奋。它应该足够好。