选择最低连续值?

时间:2013-08-07 21:17:50

标签: php mysql

背景故事
我有一个MYSQL表存储每年比赛的应用程序数据。除此之外,该表还包含Racer的ID和该竞赛申请的年份。

今年,我们希望对应用程序的随机选择过程进行加权,以便申请X连续年数的人有更大的机会被选中。

在我的PHP脚本中,我让MYSQL对象每年都会返回1条记录,随机选择一条并从DB结果数组中取消分配,将其分配给获胜者数组,并忽略所有其他获胜者今年的ID相同。

实际问题
这种方法的问题是我当前的MYSQL查询返回所有申请今年和过去比赛的人的所有记录。有没有办法(最好是使用MYSQL)我可以让它从2014年开始只返回连续的应用程序?

SQL FIddle的示例结果集将为“1,1,1,2,2,2,2,3”。

我目前的查询是:

SELECT a.racer_id FROM applications a

WHERE a.racer_id IN
    (
        SELECT ab.racer_id FROM applications ab

        WHERE ab.racer_id = a.racer_id AND ab.race_year=2014
    )

ORDER BY RAND();

这不起作用,因为它抓住了过去几年,而不仅仅是2014年及之前的连续记录。

1 个答案:

答案 0 :(得分:0)

另一种表达这个问题的方法是找到赛车参赛的最近一年。然后,当年减去那一年提供连续年数。

您可以通过在年份和参赛者之间进行交叉连接来获得最近一年,并且左侧加入应用程序。没有比赛的地方是赛车手没有比赛的一年。

你必须做一些额外的簿记来处理所有年份参赛的选手。最后的查询是:

select racers.racer_id,
       maxyear - max(case when a.race_year is null then years.race_year
                          else const.minyear - 1
                     end)
from (select distinct race_year
      from applications
     ) years cross join
     (select distinct racer_id
      from applications
     ) racers cross join
     (select max(race_year) as maxyear, min(race_year) as minyear
      from applications
     ) const left outer join 
     applications a
     on a.race_year = years.race_year and
        a.racer_id = racers.racer_id
group by racers.racer_id;

我不确定这与SQL Fiddle中的数据有什么关系。你有四个赛车手,但你在问题中有8个建议值。

编辑:

现在我明白了。这很合理。以下查询基本上扩展了上述想法,加入回application以获得最长年份之后的任何年份,无需申请。子查询是从上面简化的:

select a.racer_id
from (select racers.racer_id,
             max(case when a.race_year is null then years.race_year
                 end) as maxyear
      from (select distinct race_year
            from applications
           ) years cross join
           (select distinct racer_id
            from applications
           ) racers left outer join 
           applications a
           on a.race_year = years.race_year and
              a.racer_id = racers.racer_id
      group by racers.racer_id
     ) ry join
     applications a
     on a.racer_id = ry.racer_id and
        (a.race_year > ry.maxyear or ry.maxyear is null);