在MySQL中将表与相同列组合在一起

时间:2014-06-11 11:47:12

标签: mysql

我试图复制这个问题给出的情景Combine 2 tables with identical columns,但我遇到了一些严重的问题。这个设置基本上是这样的。我有两个列相同但内容不同的表。

MASTER TABLE
    +----------------+---------------+----------------+--------------------------------------+
    | VOTE_CANDIDATE | SURPLUS_RATIO | ORIGINAL_VOTES | SURPLUS_REDISTRIBUTION_TO_CANDIDATES |
    +----------------+---------------+----------------+--------------------------------------+
    |              1 |         0.125 |              8 |                                   -1 |
    |              2 |         0.125 |              1 |                                   -1 |
    |              3 |         0.125 |              2 |                                   -1 |
    |              4 |         0.125 |              4 |                                   -1 |
    |              5 |         0.125 |              2 |                                   -1 |
    |              6 |         0.125 |              3 |                                   -1 |
    +----------------+---------------+----------------+--------------------------------------+

SLAVE TABLE
    +----------------+---------------+----------------+--------------------------------------+
    | VOTE_CANDIDATE | SURPLUS_RATIO | ORIGINAL_VOTES | SURPLUS_REDISTRIBUTION_TO_CANDIDATES |
    +----------------+---------------+----------------+--------------------------------------+
    |              2 |         0.125 |              1 |                                0.125 |
    |              3 |         0.125 |              2 |                                 0.25 |
    |              4 |         0.125 |              4 |                                  0.5 |
    |              5 |         0.125 |              2 |                                 0.25 |
    +----------------+---------------+----------------+--------------------------------------+

我想将它们组合成一个表,即在行2,3,4,5 MASTER TABLE上用来自SLAVE TABLE的相应行替换SURPLUS_REDISTRIBUTION_TO_CANDIDATES。我已设法将其解决(最后一行因某种原因被排除在外 - 我不知道为什么。)

COMBINED TABLE
    +----------------+---------------+----------------+--------------------------------------+
    | VOTE_CANDIDATE | SURPLUS_RATIO | ORIGINAL_VOTES | SURPLUS_REDISTRIBUTION_TO_CANDIDATES |
    +----------------+---------------+----------------+--------------------------------------+
    |              1 |         0.125 |            120 |                                   -1 |
    |              2 |         0.125 |              1 |                                0.125 |
    |              3 |         0.125 |              2 |                                 0.25 |
    |              4 |         0.125 |              4 |                                  0.5 |
    |              5 |         0.125 |              2 |                                 0.25 |
    +----------------+---------------+----------------+--------------------------------------+

这非常接近我想要的但是第1行的ORIGINAL_VOTES应该是8 - 而不是120.看起来查询总结了所有投票而不是vote_order = 1的投票?的为什么吗 更多 - 如何确保最后一行(6)没有从结果中删除?

我的查询非常讨厌,但看起来像这样:

SELECT vote_candidate, (
  SELECT (
    (MAX(votes_above_the_threshold) - (
      SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) threshold
      FROM votes
    )) / MAX(votes_above_the_threshold)
  ) ratio
  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
  )
) surplus_ratio, COUNT(*) original_votes, CASE 
  WHEN (
    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
      )
    ) > (
      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
UNION
SELECT vote_candidate, (
  SELECT (
    (MAX(votes_above_the_threshold) - (
      SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) threshold
      FROM votes
    )) / MAX(votes_above_the_threshold)
  ) ratio
  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
  )
) surplus_ratio, COUNT(*) original_votes, (
  ROUND((COUNT(*) * (
    SELECT (
      (MAX(votes_above_the_threshold) - (
        SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) threshold
        FROM votes
      )) / MAX(votes_above_the_threshold)
    ) ratio
    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
    )
  )), 3)
) surplus_redistribution_to_candidates
FROM vote_orders b
WHERE vote_order = 1
AND vote_candidate IN ((
  SELECT vote_candidate
  FROM vote_orders a
  INNER JOIN (
    SELECT vote_id, MIN(vote_order) AS min_vote_order
    FROM vote_orders
    WHERE vote_candidate NOT IN ((
      SELECT vote_candidate
      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
          )
          OR (
            votes_above_the_threshold >= (
              SELECT FLOOR((COUNT(*) / (2 + 1)) + 1) threshold
              FROM votes
            )
            AND votes_above_the_threshold = 0
          )
          OR (
            votes_above_the_threshold = 0
          )
        )
      ) t
    ))
    GROUP BY vote_id
  ) b
  ON a.vote_id = b.vote_id
  AND a.vote_order = b.min_vote_order
  INNER JOIN (
    SELECT vote_id
    FROM vote_orders
    WHERE vote_candidate = (
      SELECT vote_candidate
      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
      )
    )
    AND vote_order = 1
  ) c
  ON a.vote_id = c.vote_id
  GROUP BY vote_candidate
))
GROUP BY vote_candidate;

我在MySQL 5.0.83上运行它。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

除非我非常误解你的问题,否则我认为你的问题严重过于复杂。这是你想要的? (显然,将列/表名称更改为您需要的名称)

UPDATE Master m
JOIN Slave s ON m.VOTE_CANDIDATE = s.VOTE_CANDIDATE
SET m.SURPLUS_REDIST = s.SURPLUS_REDIST

编辑: 这做了一些假设,但是会在没有实际执行更新的情况下显示这些更改。另一种方法是将主表复制到临时表中并更新临时表,然后从中更新SELECT *。

SELECT * FROM Master m
WHERE VOTE_CANDIDATE NOT IN (
    SELECT VOTE_CANDIDATE FROM Slave
)
UNION 
SELECT * FROM Slave