选择随机名称

时间:2010-06-17 05:05:59

标签: sql sql-server sql-server-2005

我有时会看到一篇有趣的帖子,但没有解决方案。试试运气:

有一个表包含10个名称(U1,U2,U3 ......等)。我必须每天选择5个名字,并显示一个作为编辑,4个作为贡献者

在选择随机名称时,我还必须考虑如果一个用户被选为编辑,他就不能再成为编辑,直到每个人都有机会。

输出应类似于以下内容:

           Editor   Cont1   Cont2     Cont3    Cont4
20-Jun   U1      U8       U9         U3       U4
21-Jun    U7      U2       U5         U6       U10
22-Jun    U3      U4       U9         U2       U8
23-Jun      U4      U8       U3          U5      U2
and so on..

3 个答案:

答案 0 :(得分:2)

这种迁移是一种方法。最有可能的是,更短的版本是可能的,但输出似乎符合您的要求。

解决方案的要点如下

  • 为每位用户添加一个计数器,指出用户成为编辑的次数以及他作为撰稿人的次数。
  • 使用TOP 1NEWID()从具有最低EditorCount的所有用户中选择一个随机用户,并更新该用户的EditorCount。
  • 同样是贡献者的选择。从具有最低ContributorCount的所有用户中选择一个随机用户,不包括刚刚成为编辑/贡献者并更新该用户的ContributeCount的用户。

SQL脚本

SET NOCOUNT ON

DECLARE @Users TABLE (
  UserName VARCHAR(3)
  , EditorCount INTEGER
  , ContributorCount INTEGER
)

DECLARE @Solutions TABLE (
  ID INTEGER IDENTITY(1, 1)
  , Editor VARCHAR(3)
  , Contributor1 VARCHAR(3)
  , Contributor2 VARCHAR(3)
  , Contributor3 VARCHAR(3)
  , Contributor4 VARCHAR(3)
)

DECLARE @Editor VARCHAR(3)
DECLARE @Contributor1 VARCHAR(3)
DECLARE @Contributor2 VARCHAR(3)
DECLARE @Contributor3 VARCHAR(3)
DECLARE @Contributor4 VARCHAR(3)

INSERT INTO @Users
SELECT 'U1', 0, 0
UNION ALL SELECT 'U2', 0, 0
UNION ALL SELECT 'U3', 0, 0
UNION ALL SELECT 'U4', 0, 0
UNION ALL SELECT 'U5', 0, 0
UNION ALL SELECT 'U6', 0, 0
UNION ALL SELECT 'U7', 0, 0
UNION ALL SELECT 'U8', 0, 0
UNION ALL SELECT 'U9', 0, 0
UNION ALL SELECT 'U0', 0, 0

/* Keep Generating combinations until at least one user has been editor for 10 times */
WHILE NOT EXISTS (SELECT * FROM @Solutions WHERE ID = 30)
BEGIN
  SELECT  TOP 1 @Editor = u.UserName
  FROM    @Users u
          INNER JOIN (
            SELECT  EditorCount = MIN(EditorCount)
            FROM    @Users
          ) ec ON ec.EditorCount = u.EditorCount
  ORDER BY NEWID()
  UPDATE @Users SET EditorCount = EditorCount + 1 WHERE UserName = @Editor
  INSERT INTO @Solutions VALUES (@Editor, NULL, NULL, NULL, NULL)  

  SELECT  TOP 1 @Contributor1 = u.UserName
  FROM    @Users u
          INNER JOIN (
            SELECT  ContributorCount = MIN(ContributorCount)
            FROM    @Users
          ) ec ON ec.ContributorCount = u.ContributorCount
  WHERE   UserName <> @Editor
  ORDER BY NEWID()
  UPDATE @Users SET ContributorCount = ContributorCount + 1 WHERE UserName = @Contributor1
  UPDATE @Solutions SET Contributor1 = @Contributor1 WHERE Contributor1 IS NULL

  SELECT  TOP 1 @Contributor2 = u.UserName
  FROM    @Users u
          INNER JOIN (
            SELECT  ContributorCount = MIN(ContributorCount)
            FROM    @Users
          ) ec ON ec.ContributorCount = u.ContributorCount
  WHERE   UserName NOT IN (@Editor, @Contributor1)
  ORDER BY NEWID()
  UPDATE @Users SET ContributorCount = ContributorCount + 1 WHERE UserName = @Contributor2
  UPDATE @Solutions SET Contributor2 = @Contributor2 WHERE Contributor2 IS NULL

  SELECT  TOP 1 @Contributor3 = u.UserName
  FROM    @Users u
          INNER JOIN (
            SELECT  ContributorCount = MIN(ContributorCount)
            FROM    @Users
          ) ec ON ec.ContributorCount = u.ContributorCount
  WHERE   UserName NOT IN (@Editor, @Contributor1, @Contributor2)
  ORDER BY NEWID()
  UPDATE @Users SET ContributorCount = ContributorCount + 1 WHERE UserName = @Contributor3
  UPDATE @Solutions SET Contributor3 = @Contributor3 WHERE Contributor3 IS NULL

  SELECT  TOP 1 @Contributor4 = u.UserName
  FROM    @Users u
          INNER JOIN (
            SELECT  ContributorCount = MIN(ContributorCount)
            FROM    @Users
          ) ec ON ec.ContributorCount = u.ContributorCount
  WHERE   UserName NOT IN (@Editor, @Contributor1, @Contributor2, @Contributor3)
  ORDER BY NEWID()
  UPDATE @Users SET ContributorCount = ContributorCount + 1 WHERE UserName = @Contributor4
  UPDATE @Solutions SET Contributor4 = @Contributor4 WHERE Contributor4 IS NULL

END

SELECT * FROM @Solutions
SELECT * FROM @Users

答案 1 :(得分:0)

这是一些伪C#代码。

假设你有两张桌子

1)用户表,其中包含所有用户

2) DailyTeam 表,其中包含每日选择的用户(您的输出)

struct Team 
{
    string name;
    int editorCount;
}
currentEditorList is a List of Team 
existingUserList is a List of Team 

currentEditorList = Get Current Editor List from DailyTeam
existingUserList = Get All Users from User and its editor count (may need left outer join)


todayTeam is a new Array

// populate the normal users to dailyTeam
while (todayTeam count is less than 4)
{
    randomIndex = generate a random number (from 0 to 9)
    userName = get name from existingUserNames[randomIndex]
    if (userName is not in todayTeam)
    {
       add userName to todayTeam
    }
}


sort existingUserList by its editorCount
editorName = get the first item from existingUserList
add editorName to todayTeam

注意:我会在powershell中实现这个算法。

答案 2 :(得分:0)

这里让我解释一下我的解决方案,或者我应该说逻辑,因为我在可以访问SQL Server的地方。 所以我无法对其进行测试,您可能需要进行编辑以使其正常运行。所以解释我的逻辑是什么..

  1. 首先假设您将在现有表中附加一列(这个逻辑必须为此逻辑),说“unirow”,它将具有唯一的编号 从1开始分配给每位员工。

  2. 然后yoy必须创建一个表tbl_counter,其中一列作为数字。只有一行(限制) 最初让它为1。

  3. 由于先决条件已经完成,现在让我们转向逻辑。我所做的就是五次为Employees表自我交叉加入 这样你就拥有了独特的团队组合。现在所有需要做的就是每次查询/程序时选择唯一的编辑器 被执行。此查询/过程的输出将包含5列第1列用于编辑器,其余用于贡献者。

  4. BEGIN

    DECLARE @counter number
    DECLARE @limit number
    DECLARE @Editor varchar(100)
    
    
    select @limit=count(*) from Employees
    
    select @counter=counter+1 from tbl_counter
    
    IF(@counter>@limit)
    begin
         set @counter=1
         update tbl_counter set counter=1
    end
    
    select @Editor=Name from Employees2 where id=@counter
    
    select  top 1 newid() as unirow,t1.name Editor,t2.name Contributor1,
    t3.name Contributor2,t4.name Contributor3,t5.name Contributor4
    from Employees t1,Employees t2,Employees t3,Employees t4,Employees t5
    where t1.name<>t2.name and t1.name<>t3.name and t1.name<>t4.name and t1.name<>t5.name
    and t2.name<>t1.name and t2.name<>t3.name and t2.name<>t4.name and t2.name<>t5.name
    and t3.name<>t2.name and t3.name<>t1.name and t3.name<>t4.name and t3.name<>t5.name
    and t4.name<>t2.name and t4.name<>t3.name and t4.name<>t1.name and t4.name<>t5.name
    and t5.name<>t2.name and t5.name<>t3.name and t5.name<>t4.name and t5.name<>t1.name
    and t1.name=@Editor
    order by unirow 
    

    END