Reputation: 41
I am somehow new to SQL, and I have a Election Application. I have done 80% of it and now stuck at counting votes from 2 or more Columns.
Example Table:
|**Senator_1** | **Senator_2** | **Senator_3**|
----------------------------------------------
George | Carl | Anthony
Carl | Tony | Stark
Anthony | George | Tony
Anthony | George | Stark
I would like to have this kind of result.
|**Candidate_Name** | **Vote_Count**|
-------------------------------------
George | 3
Anthony | 3
Carl | 2
Stark | 2
Tony | 2
I really don't have any idea of what query I am going to use. Any ideas of solving this?
By the way, for the confusion and all the arguments that started here, I am going to explain:
I wanted to be straight to my problem that's why I just posted a sample table. I have a table for the Voters, Candidates and the Votes. All tables have its ID and such, so I'm pretty sure it's normalized.
Upvotes: 2
Views: 169
Reputation: 247710
The main issue that you have is your table is not normalized. I would strongly advise that you fix your current table structure. A possible new table structure would be:
/* 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);
Then you could easily get a result by joining the two tables:
/* 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;
However, if you cannot alter the design of the table, then you can get the result by unpivoting the data that you have in multiple columns. You can use a UNION ALL to unpivot the multiple columns into rows to get the count:
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;
Upvotes: 11
Reputation: 688
I think you are looking to count the total no. of occurrence of each name in different columns. Based on this, I think something like below might help -
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
Upvotes: 0