gpt4 book ai didi

mysql - 在 MySQL 中使用 union 进行正确分组

转载 作者:行者123 更新时间:2023-11-29 00:12:45 25 4
gpt4 key购买 nike

我浏览了 StackOverflow 和 Internet 以寻找以下问题的答案,但我找到的答案都不适合我。这是我的问题。

我想使用 UNION 合并两个查询。我已经设法按预期将它们组合在一起,但我无法让它们按照我想要的方式进行分组。我希望通过对子查询进行排序来隐藏重新分配值为 0 的重复行,以便它们在分组时优先考虑......(我知道错误的解释 - 我希望下面的图形演示更好地解释它。我想要删除的行在右边缘标有一个小箭头)。

我到底该怎么做?

+-----------+-------+---------------+----------------+----------------------------+
| CANDIDATE | VOTES | RANKED_CHOICE | REDISTRIBUTION | VOTES_AFTER_REDISTRIBUTION |
+-----------+-------+---------------+----------------+----------------------------+
| 1 | 8 | 0 | 0 | 8 |
| 2 | 1 | 6 | -1 | 0 |
| 2 | 1 | 0 | 0 | 1 | >
| 3 | 2 | 0 | 0 | 2 |
| 4 | 4 | 0 | 0 | 4 |
| 5 | 2 | 0 | 0 | 2 |
| 6 | 3 | 0 | 0 | 3 | >
| 6 | 3 | 0 | 1 | 4 |
+-----------+-------+---------------+----------------+----------------------------+

-- The resulting table that's shown on the screen
SELECT vote_candidate candidate, original_votes votes, ranked_choice, redistribution, (original_votes + redistribution) votes_after_redistribution
FROM (
-- Create the first table with original information
SELECT c.vote_candidate, c.original_votes, '0' ranked_choice, '0' redistribution
FROM (
SELECT o.vote_candidate, COUNT(*) original_votes
FROM vote_orders o
WHERE o.vote_order = 1
GROUP BY o.vote_candidate
) c
GROUP BY c.vote_candidate
-- Union a second table containing the second ranked choice of an eliminated candidate and the redistribution.
-- This is done in two steps. In the first step we find out the ranking. In the second step we union the ranked
-- candidate and its' redistribution with each other
UNION
SELECT vote_candidate, original_votes, ranked_choice, redistribution
FROM ((
SELECT vote_candidate, IFNULL(d.original_votes, 0) original_votes, IFNULL(COUNT(*), 0) ranked_choice, (0 - IFNULL(d.original_votes, 0)) redistribution
FROM vote_orders a
-- Get the second favored vote from each eliminated candidates ballots
INNER JOIN (
SELECT vote_id, c, MIN(minimum_vote)
FROM (
SELECT vote_id, vote_candidate c, COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t1
WHERE minimum_vote = (
SELECT MIN(minimum_vote)
FROM (
SELECT COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
)
GROUP BY c
) b
ON a.vote_id = b.vote_id
-- Get the eliminated candidates votes at the beginning of this round
LEFT OUTER JOIN
(
SELECT vote_candidate o, COUNT(*) original_votes
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) d
ON a.vote_candidate = d.o
GROUP BY vote_candidate
ORDER BY redistribution DESC
LIMIT 1
-- Union the candidates redistribution
UNION
(
SELECT vote_candidate, d.original_votes, '0' ranked_choice, (CASE
WHEN IFNULL(d.original_votes, 0) = 0
THEN (0 - IFNULL(d.original_votes, 0))
ELSE (
SELECT MIN(minimum_vote)
FROM (
SELECT vote_candidate c, COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t1
WHERE minimum_vote = (
SELECT MIN(minimum_vote)
FROM (
SELECT COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
)
GROUP BY c
)
END) redistribution
FROM vote_orders a
INNER JOIN (
SELECT vote_id, MIN(minimum_vote)
FROM (
SELECT vote_id, COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t1
WHERE minimum_vote = (
SELECT MIN(minimum_vote)
FROM (
SELECT COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
)
) b
ON a.vote_id = b.vote_id
LEFT OUTER JOIN
(
SELECT vote_candidate o, COUNT(*) original_votes
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) d
ON a.vote_candidate = d.o
-- Determine which candidate to add the redistribution to
WHERE vote_candidate = (
SELECT IFNULL(COUNT(*), 0) ranked_choice
FROM vote_orders a
INNER JOIN (
SELECT vote_id, c, MIN(minimum_vote)
FROM (
SELECT vote_id, vote_candidate c, COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t1
WHERE minimum_vote = (
SELECT MIN(minimum_vote)
FROM (
SELECT COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
)
GROUP BY c
) b
ON a.vote_id = b.vote_id
)
GROUP BY vote_candidate
ORDER BY redistribution DESC
LIMIT 1
)
)) y
) z
-- This is where the grouping fails on me
-- GROUP BY vote_candidate
ORDER BY vote_candidate ASC;

这是模式:

CREATE TABLE votes
(
vote_id INT NOT NULL AUTO_INCREMENT,
vote_candidate_a INT,
vote_candidate_b INT,
vote_candidate_c INT,
vote_candidate_d INT,
vote_candidate_e INT,
vote_candidate_f INT,
PRIMARY KEY vote_id(vote_id)
);

INSERT INTO votes
VALUES
(NULL, 1, 3, 2, 5, 4, 6),
(NULL, 1, 2, 4, 6, 3, 5),
(NULL, 5, 3, 2, 1, 4, 6),
(NULL, 6, 1, 5, 3, 4, 2),
(NULL, 2, 3, 5, 6, 1, 4),
(NULL, 4, 1, 6, 3, 2, 5),
(NULL, 3, 2, 6, 1, 5, 4),
(NULL, 4, 3, 1, 6, 2, 5),
(NULL, 1, 2, 4, 3, 6, 5),
(NULL, 1, 5, 3, 2, 4, 6),
(NULL, 4, 5, 6, 2, 3, 1),
(NULL, 1, 4, 2, 3, 5, 6),
(NULL, 1, 2, 3, 4, 5, 6),
(NULL, 3, 6, 5, 1, 4, 2),
(NULL, 1, 2, 3, 4, 5, 6),
(NULL, 6, 5, 4, 3, 2, 1),
(NULL, 4, 3, 1, 5, 6, 2),
(NULL, 6, 3, 1, 2, 5, 4),
(NULL, 1, 4, 6, 3, 2, 5),
(NULL, 5, 3, 6, 4, 2, 1);


CREATE TABLE vote_orders
(
id INT NOT NULL AUTO_INCREMENT,
vote_id INT,
vote_order INT,
vote_candidate INT,
PRIMARY KEY id(id)
);

INSERT INTO vote_orders (id, vote_id, vote_order, vote_candidate)
SELECT NULL, vote_id, 1, vote_candidate_a FROM votes
UNION
SELECT NULL, vote_id, 2, vote_candidate_b FROM votes
UNION
SELECT NULL, vote_id, 3, vote_candidate_c FROM votes
UNION
SELECT NULL, vote_id, 4, vote_candidate_d FROM votes
UNION
SELECT NULL, vote_id, 5, vote_candidate_e FROM votes
UNION
SELECT NULL, vote_id, 6, vote_candidate_f FROM votes;

最佳答案

实际上,您已经知道什么是 vote_candidate 和票数。这是一个简单的查询,

Select vote_candidate, count(*)
From vote_orders
Where vote_order = 1
Group by vote_candidate

这是整个查询的基础,因为选择中唯一缺少的是 ranked_choice、重新分配和 votes_after_redistribution(尽管这是非常微不足道的,因为它是来自其他两个列的计算)。因此,我建议使用您已完成的所有工作来查找缺少的两个列。本质上,您应该将查询更改为子选择以仅查找缺失的列。

我将您的子选择更改为仅查找不为 0 的 ranked_choice 和 redistribution 值。然后,我正在获取这些值(使用左外连接)。如果子选择中没有任何内容,那么我们将默认值为0。

您之前的查询首先将所有值默认为 0,然后返回不为 0 的行的信息。让我们跳过所有额外的工作。请注意,我仍然建议清理子选择,特别是因为我删除了原始投票的计数。有些连接可能是额外的,因为您不再需要查找该信息。 fiddle :http://sqlfiddle.com/#!2/1b0cb/51

-- The resulting table that's shown on the screen
SELECT v.vote_candidate candidate,
count(*) votes,
IfNull(z.ranked_choice, 0) ranked_choice,
IfNull(z.redistribution, 0) redistribution,
(count(*) + IfNull(z.redistribution, 0)) votes_after_redistribution
FROM vote_orders v left outer join

(

-- Union a second table containing the second ranked choice of an eliminated candidate and the redistribution.
-- This is done in two steps. In the first step we find out the ranking. In the second step we union the ranked
-- candidate and its' redistribution with each other
SELECT vote_candidate, ranked_choice, redistribution
FROM ((
SELECT vote_candidate,
IFNULL(COUNT(*), 0) ranked_choice,
(0 - IFNULL(d.original_votes, 0)) redistribution
FROM vote_orders a
-- Get the second favored vote from each eliminated candidates ballots
INNER JOIN (
SELECT vote_id, vote_candidate c, MIN(minimum_vote)
FROM (
SELECT vote_id, vote_candidate, COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
) b
ON a.vote_id = b.vote_id
-- Get the eliminated candidates votes at the beginning of this round
LEFT OUTER JOIN
(
SELECT vote_candidate o, COUNT(*) original_votes
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) d
ON a.vote_candidate = d.o
GROUP BY vote_candidate
ORDER BY redistribution DESC
LIMIT 1
-- Union the candidates redistribution
UNION
(
SELECT vote_candidate,
0 ranked_choice,
(CASE
WHEN IFNULL(d.original_votes, 0) = 0
THEN (0 - IFNULL(d.original_votes, 0))
ELSE (
SELECT MIN(minimum_vote)
FROM (
SELECT COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
)
END) redistribution
FROM vote_orders a
INNER JOIN (
SELECT vote_id, MIN(minimum_vote)
FROM (
SELECT vote_id, COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t1
WHERE minimum_vote = (
SELECT MIN(minimum_vote)
FROM (
SELECT COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
)
) b
ON a.vote_id = b.vote_id
LEFT OUTER JOIN
(
SELECT vote_candidate o, COUNT(*) original_votes
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) d
ON a.vote_candidate = d.o
-- Determine which candidate to add the redistribution to
WHERE vote_candidate = (
SELECT IFNULL(COUNT(*), 0) ranked_choice
FROM vote_orders a
INNER JOIN (
SELECT vote_id, c, MIN(minimum_vote)
FROM (
SELECT vote_id, vote_candidate c, COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t1
WHERE minimum_vote = (
SELECT MIN(minimum_vote)
FROM (
SELECT COUNT(*) minimum_vote
FROM vote_orders
WHERE vote_order = 1
GROUP BY vote_candidate
) t2
)
GROUP BY c
) b
ON a.vote_id = b.vote_id
)
GROUP BY vote_candidate
ORDER BY redistribution DESC
LIMIT 1
)
)) y
) z
on v.vote_candidate = z.vote_candidate
Where v.vote_order = 1
GROUP BY v.vote_candidate
ORDER BY v.vote_candidate ASC;

关于mysql - 在 MySQL 中使用 union 进行正确分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24288046/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com