【问题标题】:Limiting records in a random select限制随机选择中的记录
【发布时间】:2014-03-31 08:47:09
【问题描述】:

我到处搜索,似乎无法在任何地方找到答案,所以我寻求帮助。

我正在尝试随机选择 5 个人。有点像画。每个人都可以输入自己想输入的次数,但只能考虑其中的 3 个条目。所以... 5 个不同的人将获胜,但所有条目(包括重复)都需要考虑最多 3 个条目。

例如:

Adam,1
Adam,2
Adam,1
Adam,1
Sally,2
Timmy,3
John,1
John,1
Jenny,2
Wendy,3
Wendy,3
Wendy,3
Wendy,5
Wendy,5

这是我目前得到的代码:

select top 5 
    name, vote 
from 
    (SELECT 
         name, vote 
     FROM 
         Entries 
     GROUP BY 
          name, vote) winners 
ORDER BY
    NEWID();

我的问题是 (1) 我没有将它们限制为 3 次以供考虑,因为我对如何做到这一点一无所知,并且 (2) Distinct 不起作用,因为它们可以输入 100 次并投票每次都有不同的条目。

【问题讨论】:

  • vote 代表什么?
  • 对于多条用户记录的问题,没有办法解决。您可以努力预防,但这会缩小问题的范围。
  • 您使用的是什么版本的 SQL Server?
  • 我使用的是 SQL Server 2000
  • @user3361687 你能解释一下vote 代表什么吗?你是按名字和投票来分组的,是“Wendy”即使她参加了 5 次也有 3 次获胜,还是“Wendy,5”有 2 次获胜的机会因为她参加了 2 次?跨度>

标签: sql sql-server tsql sql-server-2000


【解决方案1】:

试试这个。每个名称最多只能包含三个条目。

WITH UpToThree AS
(
    SELECT
         Name
        ,RN = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Vote)
        ,NEWID() as RandID
    FROM
        Entries
)
SELECT TOP 5
    Name, MAX(RandID)
FROM
    UpToThree
WHERE
    RN < 4
GROUP BY
    Name
ORDER BY
    MAX(RandID)

【讨论】:

  • 但这会影响参赛者的投票 - 以 Wendy 为例,她的“5”票不会被视为她的前三票是“3”。
  • 这不会阻止同一个人被多次选中。
  • @user2864740 我没有明白这是投票栏中的投票计数。如果是,那么这个表还有其他问题......
  • 现在它坏了。使用DISTINCT 时,如果不选择NEWID(),则无法通过NEWID() 订购。
  • 投票无关紧要。我只是将它们显示在我的获奖者名单中。 :)
【解决方案2】:

我不确定 SQL 2000 中是否有以下任何内容:

SELECT TOP 5 Name
FROM (SELECT Name,ABS(CHECKSUM(NEWID())) nid, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY NEWID()) RN
      FROM Table1) as sub
WHERE RN <= 3
GROUP BY Name
ORDER BY MAX(nid)

演示:SQL Fiddle

我不确定您想如何决定要显示哪张选票,但如果您希望仅根据姓名来考虑参赛作品,则应在单独加入获胜者列表时进行处理。

【讨论】:

  • 是的...我得到 'ROW_NUMBER' 不是一个可识别的函数名称。我看到我可以对临时表做同样的事情。我会调查的。这可能不是一个可能的查询。感谢大家的帮助!
【解决方案3】:

我认为确保获得 3 次参赛作品的人获胜的可能性是获得 1 次参赛作品的人的 3 倍是一项挑战。我假设votes 并不重要,因为问题或 cmets 中没有提到它。

策略是首先使用row_number()(和where)将条目限制为每人随机3个。然后,再次对结果排序并使用row_number() 随机枚举每一行。通过随机枚举,任何条目在顶部都有相同的变化 - 因此,拥有 3 个条目的人成为最佳的概率是拥有一个条目的人的三倍。

最后根据这个序号选出前五人:

with entries_3 as (
      select e.*
      from (select e.*, row_number() over (partition by name order by newid()) as seqnum
            from entries
           ) e
      where seqnum <= 3
     ),
     entries_3_ordered (
      select e.*, row_number() over (order by newid()) as seqnum2
      from entries_3
     )
select top 5 name, votes
from from entries_3_ordered
group by name, votes
order by min(seqnum2);

【讨论】:

    猜你喜欢
    • 2014-05-12
    • 2023-03-25
    • 2011-04-08
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多