SQL - 从2个或更多列计数

时间:2013-06-11 12:53:49

标签: mysql sql

我不熟悉SQL,我有一个Election Application。我已经完成了80%的工作,现在仍然坚持计算来自2个或更多列的投票。

示例表:

|**Senator_1** | **Senator_2** | **Senator_3**|
----------------------------------------------
   George      |    Carl       |   Anthony
   Carl        |    Tony       |   Stark
   Anthony     |    George     |   Tony
   Anthony     |    George     |   Stark

我希望得到这样的结果。

|**Candidate_Name** | **Vote_Count**|
-------------------------------------
   George           |   3
   Anthony          |   3
   Carl             |   2
   Stark            |   2
   Tony             |   2

我真的不知道我将使用什么查询。解决这个问题的任何想法?

顺便说一句,对于混乱和从这里开始的所有论点,我将解释:

我想直接解决我的问题,这就是我刚发布样本表的原因。我有选民,候选人和投票的桌子。所有表都有它的ID等等,所以我很确定它是标准化的。

2 个答案:

答案 0 :(得分:11)

您遇到的主要问题是您的表未规范化。我强烈建议您修复当前的表结构。 可能的新表结构将是:

/* Table for unique voters */
CREATE TABLE voters (
    id INT UNSIGNED NOT NULL PRIMARY KEY,
    name VARCHAR(255) NOT NULL 
) ENGINE=InnoDB;

/* Table for unique candidates */
CREATE TABLE candidates (
    id INT UNSIGNED NOT NULL PRIMARY KEY,
    name VARCHAR(255) NOT NULL
) ENGINE=InnoDB;

/* Many-to-many table storing votes by voters for candidates */
CREATE TABLE votes (
    voter_id INT UNSIGNED NOT NULL,
    candidate_id INT UNSIGNED NOT NULL,
    PRIMARY KEY (voter_id, candidate_id),
    CONSTRAINT FOREIGN KEY (voter_id) REFERENCES voters (id),
    CONSTRAINT FOREIGN KEY (candidate_id) REFERENCES candidates (id)
) ENGINE=InnoDB;

/* Populate data */
INSERT INTO voters (name)
VALUES ('Voter 1'), ('Voter 2'), ('Voter 3'), ('Voter 4');

INSERT INTO candidates (name)
VALUES ('George'), ('Carl'), ('Anthony'), ('Tony'), ('Stark');

INSERT INTO votes (voter_id, candidate_id)
VALUES (1,1), (1,2), (1,3),
       (2,2), (2,4), (2,5),
       (3,3), (3,1), (3,4),
       (4,3), (4,1), (4,5);

然后,您可以通过加入两个表轻松获得结果:

/* query showing all voters and the candidates they voted for */
SELECT voters.name, candidates.name
FROM votes
    INNER JOIN voters on votes.voter_id = voters.id
    INNER JOIN candidates ON votes.candidate_id = candidates.id;

/* Finally, a query showing votes per candidate */
SELECT candidates.name, COUNT(*) AS votes
FROM votes
    INNER JOIN candidates ON votes.candidate_id = candidates.id
GROUP BY candidates.id;

请参阅SQL Fiddle with Demo

但是,如果您无法更改表的设计,则可以通过取消忽略多列中的数据来获得结果。您可以使用UNION ALL将多列拆分为行以获取计数:

select name, count(*) TotalVotes
from
(
  select senator_1 name
  from yt
  union all
  select senator_2 name
  from yt
  union all
  select senator_3 name
  from yt
) d
group by name
order by totalVotes desc;

请参阅SQL Fiddle with Demo

答案 1 :(得分:0)

我认为你正在计算总数。在不同的列中出现每个名称。基于此,我认为下面的内容可能有所帮助 -

select senator, sum(cnt) as 'count' from (
select senator_1 as 'senator', count(1) 'cnt' from election_table group by senator_1
union all
select senator_2 as 'senator', count(1) 'cnt' from election_table group by senator_2
union all
select senator_3 as 'senator', count(1) 'cnt' from election_table group by senator_3
) x group by x.senator