MySQL中循环返回错误值的情况

时间:2014-06-11 21:07:47

标签: mysql

为了完成我今天的MySQL问题,我想就此事提出一些建议。我有一个表,我需要添加一个具有计算值的列。我不打算更新表格 - 只是结合信息。 与我合作的表格看起来像这样:

        +----------------+----------------+--------------------------------------+
        | VOTE_CANDIDATE | ORIGINAL_VOTES | SURPLUS_REDISTRIBUTION_TO_CANDIDATES |
        +----------------+----------------+--------------------------------------+
        |              1 |              8 |                                   -1 |
        |              2 |              1 |                                   -1 |
        |              3 |              2 |                                   -1 |
        |              4 |              4 |                                   -1 |
        |              5 |              2 |                                   -1 |
        |              6 |              3 |                                   -1 |
        +----------------+----------------+--------------------------------------+

我的问题是只有第1行应该在列SURPLUS_REDISTRIBUTION_TO_CANDIDATES上返回-1,因为它的ORIGINAL_VOTES大于7的阈值。其余的应该(如下面的状态)返回零,因为它'低于门槛。似乎查询锁定在第一行,然后在所有行上重用SURPLUS_REDISTRIBUTION_TO_CANDIDATES。这是我正在使用的查询:

SELECT vote_candidate, COUNT(*) original_votes, CASE
  WHEN (
    (
      SELECT MAX(
        (
          SELECT COUNT(*) votes_above_the_threshold
          FROM vote_orders
        )
      ) votes
      FROM vote_orders
      WHERE vote_order = 1
    ) >= (
      SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) threshold
      FROM votes
    )
  )
  THEN (
    SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) threshold
    FROM votes
  ) - (
    SELECT MAX(votes_above_the_threshold) votes
    FROM (
      SELECT vote_candidate vote_candidate, COUNT(*) votes_above_the_threshold
      FROM vote_orders
      WHERE vote_order = 1
      GROUP BY vote_candidate
      HAVING votes_above_the_threshold >= (
        SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) threshold
        FROM votes
      )
    ) t
    WHERE votes_above_the_threshold = (
      SELECT MAX(votes_above_the_threshold)
      FROM vote_orders
    )
  )
  ELSE 0
END surplus_redistribution_to_candidates
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate;

我如何实现我正在寻找的结果?

1 个答案:

答案 0 :(得分:1)

我无法破译您的查询所做的事情,以及为什么要这样做。

看起来只有一个"阈值&#34 ;;这是根据针对votes表的查询计算得出的。

如果目标是返回"阈值"之间的非正差异。价值和" orginal_votes"每个候选人的价值,我会这样做:

SELECT c.vote_candidate
     , c.original_votes
     , LEAST(0,t.threshold - c.original_votes) AS surplus_redistribution_to_candidates
  FROM ( SELECT o.vote_candidate
              , COUNT(*) original_votes
           FROM vote_orders o
          WHERE o.vote_order = 1
          GROUP
             BY o.vote_candidate
       ) c
 CROSS
  JOIN ( SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) AS threshold
           FROM votes
        ) t
 ORDER BY c.vote_candidate

作为c的别名的内联视图获取" original_votes"对于每个候选人,内联视图别名为" t"获得"阈值"。外部查询比较两个值,并返回差值(如果是负数)或零。


我认为您的查询未锁定到第一行。相反,我认为问题是每个SELECT MAX()子查询的每次执行都会为每个vote_candidate返回相同的值。并且恰巧巧合的是,最大值恰好与"第一"结果集中vote_candidate

看起来你只想比较" original_votes"对于每个vote_candidate到"阈值"值。看起来好像所有这些子查询都是完全没必要的;他们只会造成混乱。


如果您想避免使用MySQL LEAST()函数,并使用ANSI标准CASE表达式,那么您可以

替换这个:

    LEAST(0,t.threshold - c.original_votes)

用这个:

    CASE
    WHEN t.threshold < c.original_votes
    THEN t.threshold - c.original_votes
    ELSE 0
    END