我应该如何存储每周民意调查数据?

时间:2011-11-08 04:06:58

标签: php mysql

我正在写一个十大投票系统。民意调查员每周都会在他们的前10名投票。我应该如何存储每周的民意调查?也就是说,如何控制轮询在存储(mySQL)或PHP(5.x +)计算中的哪一周?

System#1 )我以前通过在我设置为0的服务器上设置文件“week.txt”然后每周运行一个cron作业来更新+1来完成此操作。当我将轮询数据存储在数据库中时,我只是加载文件并知道它是什么周。我正在寻找更优雅的东西。

系统必须:

  1. 能够在一年中的任何时间开始。
  2. 能够跳过几周。
  3. 计算期间不需要改变周数。
  4. 除了一次性活动外,还可以免除人的维护(比如说“这是开始日期”,“这是结束日期”,一旦出现在蓝色的月亮中)。
  5. 使用PHP,mySQL,文件或其他“标准”服务器项目(其他编程语言或数据库除外)。
  6. 不需要其他软件(例如“安装软件X,它会这样做!”)。
  7. 民意调查员可能是非技术人员,因此不允许向他们询问“输入前10名”或“编辑前10名”以外的任何内容。
  8. 能够顺利完成日历年度结束(例如11月开始,3月结束)。
  9. 其他信息:

    1. 民意调查员只能在一天内投票。
    2. 我将立即进行多项民意调查,彼此之间没有任何关系,因此可能会有不同的跳过周。
    3. 我以前用过的系统不起作用,因为为了跳过几周,它需要互动并违反#4,否则不能跳过几周,从而违反#2。

      我已经考虑过2个系统,但它们的部分原因都失败了:
      System#2 )当民意测验者投票时使用PHP的日期(“W”)。因此,第一周他们都得到#48周(例如),第二周#49,所以很容易分辨哪一周是什么。问题是一些民意调查将持续到日历年,因此我最终会得到48,49,50,51,52,1,2,3,4并违反上述#3。此外,如果我们跳过几周,我们最终会得到48,49,50,1,2,3,这违反了上面的#2和#8。

      System#3 )然后,我有想法存储他们进入民意调查的日期。我会设置一个日期来计算从第一轮投票之前的一周,因此,它只需要计算周数之间的差异,我就知道周数。但除非我们改变违反#3的日子,否则没有简单的方法可以跳过违反#2的数周。

      System#4 )然后,我认为当民意测验者第一次投票时,我们只将其记录为第1周投票。当他们下次投票时,它是第2周,依此类推。如果他们想要编辑他们的民意调查(同一天),他们只是使用编辑按钮,我们不会记录新的民意调查,因为他们已经发信号通知它是一个编辑。唯一的问题是,如果民意测验者忘记了一周,这意味着我必须进入并更正数据(添加一个空白周或更改他们投票但违反#4的周数)。这样处理跳过周就好了。也许一个cron工作会解决这个问题?如果有人忘了,在投票结束后运行的cron作业将进入一个空白周。可编程以查看输入的最大周数,如果任何用户ID没有该周数,则只需输入空白数据。

      如果您可以调整上述任何系统以满足所有标准,那也没关系。我正在寻找一种简单,优雅,免提的解决方案。

      请询问任何其他澄清信息。

1 个答案:

答案 0 :(得分:3)

使用周数时,您应该记住01.01.2012是在第52周(而不是1)。问题是,您是否希望在日历周内修正您的民意调查,或者从民意调查开始日期开始7天抵消。考虑一下周五开始的投票,并在7天之后结束。您将跨越日历周障碍,因此您的用户可以投票2个星期。

我可能更喜欢偏移方法,因为严格的日历绑定通常无济于事。你想回答“日历周34的票数是多少”或“投票第三周的票数是多少”的问题?

计算偏移非常简单:

// 0-based
$week_offset = floor(time() - strtotime("2011-11-02") / 7);

我不知道你的轮询算法。我只是用加权民意调查来证明(1-3星,3是最好的):

| poll_id | user_id | week_offset | vote |
|       7 |       3 |           0 |    1 |
|       7 |       4 |           0 |    3 |
|       7 |       5 |           0 |    2 |
|       7 |       3 |           1 |    2 |
|       7 |       4 |           1 |    2 |
|       7 |       5 |           2 |    3 |
|       7 |       5 |           5 |    1 |

运行类似

的查询
SELECT 
  poll_id, 
  week_offset, 
  SUM(vote) as `value`,
  COUNT(user_id) as `count`,
  AVG(vote) as `average`
FROM votes_table
WHERE poll_id = 7
GROUP BY poll_id, week_offset
ORDER BY poll_id, week_offset;

会给你类似的东西

| poll_id | week_offset | value | count | average |
|       7 |           0 |     6 |     3 |       2 |
|       7 |           1 |     4 |     2 |       2 |
|       7 |           2 |     3 |     1 |       3 |
|       7 |           5 |     1 |     1 |       1 |

到目前为止,您可能已经注意到差距0,1,2,[3],[4],5。

当从MySQL获取数据时,你必须反复迭代结果。那么问题在于延长填充间隙的问题在哪里?

<?php
// your database accessor of heart (mine is PDO)
$query = $pdo->query($above_statement);
$results = array();
$previous_offset = 0;
foreach ($query as $row) {
  // calculate offset distance
  $diff = $row['week_offset'] - $previous_offset;

  // make sure we start at 0 offset
  if ($previous_offset === 0 && $row['week_offset'] > 0) {
    $diff++;
  }

  // if distance is greater than a single step, fill the gaps
  for (; $diff > 1; $i--) {
    $results[] = array(
      'value' => 0,
      'count' => 0,
      'average' => 0,
    );
  }

  // add data from db
  $results[] = array(
    'value' => $row['value'], 
    'count' => $row['count'],
    'average' => $row['average'],
  );

  // remember where we were
  $previous_offset = $row['week_offset'];
}
// 0 based list of voting weeks, enjoy
var_dump($results);

您也可以使用function在MySQL中执行上述操作。