【问题标题】:Is there a SQL Server function for displaying pseudo-random database records?是否有用于显示伪随机数据库记录的 SQL Server 函数?
【发布时间】:2010-07-09 21:59:01
【问题描述】:

有没有办法从数据库表中显示一定数量的随机记录,但受创建日期和时间的影响很大。

例如:

  • 随机显示 10 条记录,但是
  • 显示最新的频率高于最早的频率

  • 假设news 表中有 100 个条目

  • 最新(按日期时间)记录将有几乎 100% 的机会被选中
  • 第一个(按日期时间)记录被选中的几率几乎为 0%
  • 第 50 条(按日期时间)记录将有 50% 的机会被选中

mssql中直接有这样的东西吗?或者我可以在 c# 中使用一些函数(最佳实践)吗?

thnx

** edit:我知道这个标题真的很糟糕。如果您有更具描述性的内容,请进行编辑。 thnx

【问题讨论】:

  • 我们在谈论多少条记录?是否附加了数字 ID?
  • 一个简单的方法是根据您希望有多少机会选择该元素,为集合中的每个元素分配一个“权重”。然后你总结所有这些权重,并在该范围内选择一个随机数。然后您再次遍历所有元素以找出您实际选择的元素。例如,3 个元素,权重分别为 25、25 和 50。您随机选择 37,它位于第 2 个元素(25-49,包括)内。
  • @aronchick 记录可以从 1 到最大 int 我猜:P
  • @Lasse V. Karlsen 我不得不读了几次那个答案,但现在我明白了。它似乎真的很好。你能以某种方式帮助挑选重量吗?在我的例子中,第一个、第 50 个和最后一个的重量是多少?非常感谢一个好主意

标签: c# sql-server visual-studio random


【解决方案1】:

一种非常简单的方式可能类似于以下内容。或者至少它可能会给你一个开始的基础。

WITH N AS
(
SELECT id,
       headline,
       created_date,
       POWER(ROW_NUMBER() OVER (ORDER BY created_date ASC),2) * /*row number squared*/
          ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [Weight] /*Random Number*/
  FROM news
  )
  SELECT TOP 10 
       id,
       headline,
       created_date FROM N 
  ORDER BY [Weight] DESC

【讨论】:

  • +1 那是要走的路,但为什么要用 NEWID() 让自己复杂化而不使用 RAND()? msdn.microsoft.com/en-us/library/ms177610.aspx
  • @Remus。我认为 Rand() 只评估一次,因此将始终返回同一组结果sql-server-helper.com/tips/generate-random-numbers.aspx
  • 我明白了。我想你总是可以强制它依赖于一个列,例如:select rand(binary_checksum(getdate(), object_id)), * from sys.tables,但与使用 newid() 并没有太大区别
  • 喜欢这个想法,但没有完全理解。为什么权重是随机数?
  • @b0x0rz 不是。 row number squared multiplied by a random number 是我所说的重量,也许我应该称之为分数或其他东西。我不确定我给出的公式是否一定合适,但您可以对其进行调整。
【解决方案2】:

有关随机样本,请参阅Limiting Result Sets by Using TABLESAMPLE。例如。从表中选择 100 行的样本:

SELECT FirstName, LastName
FROM Person.Person 
TABLESAMPLE (100 ROWS);

对于加权样本,优先考虑最近的记录(我第一次阅读问题时错过了这一点),那么 Martin 的解决方案更好。

【讨论】:

    【解决方案3】:

    您可以使用指数分布(例如)选择 N,然后按日期排序 SELECT TOP(N),然后选择最后一行。 您可以根据现有行数选择指数。

    【讨论】:

    • @Michael - 我说只选择最后一行。
    • 对不起,你是对的。那么您是否建议一遍又一遍地重复此操作以获得所需数量的最近结果?听起来很贵。
    【解决方案4】:

    很遗憾我不懂MSSQL,但我可以给出一个高级建议。

    1. 以 UNIX 时间(或其他一些递增的整数表示)获取日期
    2. 将此值除以每列的最大值以获得百分比。
    3. 获取一个随机数并乘以上述百分比。
    4. 按此值对列进行排序,并取顶部N

    这将赋予最新结果更多的权重。如果要调整较早结果与较晚结果的相对频率,可以在获取比率之前对这些值应用指数或对数函数。如果您有兴趣,请告诉我,我可以提供更多信息。

    【讨论】:

      【解决方案5】:

      如果您可以在访问数据库后过滤结果,或者您可以使用order by 提交查询并使用阅读器处理结果,那么您可以为选择添加概率偏差。您会看到偏差越高,if 内的测试越难,过程越随机。

      var table = ...  // This is ordered with latest records first
      int nItems = 10;  // Number of items you want
      double bias = 0.5;  // The probabilistic bias: 0=deterministic (top nItems), 1=totally random
      Random rand = new Random();
      
      var results = new List<DataRow>();  // For example...
      
      for(int i=0; i<table.Rows.Count && results.Count < nItems; i++) {
          if(rand.NextDouble() > bias)
              // Pick the current item probabilistically
              results.Add(table.Rows[i]);  // Or reader.Next()[...]
      }
      

      【讨论】:

      • 如果表大于您的客户端进程可行地址空间怎么办?
      • 好点。它也可以通过阅读器进行顺序访问。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-30
      • 2017-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多