Skip to content
Advertisement

How to structure limited voting system design

I have 3 types of tables. Categories, Candidates, Voters. To be describing the problem as short as possible, Candidates can belong to only 1 category. Voters can vote for each category and only one person from a category. There can not be second person to vote for 1 category. I mean, If Voter votes for Paul, which Paul is a candidate for President, the same voter can not vote for a second presidential candidate, but can vote for Vice President and Secretary. So the main problem is creating a structure for 1 Voter can vote for 3 types of categories and for only 1 candidate inside of the category

Here are the tables.

CREATE TABLE Categories(
    Id INT PRIMARY KEY IDENTITY(1,1),
    Name NVARCHAR(20) NOT NULL UNIQUE,
);

CREATE TABLE Candidates(
    Id INT PRIMARY KEY IDENTITY(1,1),
    Name NVARCHAR(20) NOT NULL,
    Surname NVARCHAR(20) NOT NULL,
    Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
);

CREATE TABLE Voters(
    Id INT PRIMARY KEY IDENTITY(1,1),
    Name NVARCHAR(20) NOT NULL,
    Surname NVARCHAR(20) NOT NULL,
    Age INT NOT NULL  CHECK(Age>=18),
);

Here is the table which I encountered with the problem on

CREATE TABLE VotersCandidates(
    Id INT PRIMARY KEY IDENTITY(1,1),
    Voter_Id INT FOREIGN KEY REFERENCES Voters(Id) NOT NULL,
    Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
    Candidate_Id INT FOREIGN KEY REFERENCES Candidates(Id) NOT NULL,
);

Thank you to lend a hand!

Advertisement

Answer

The primary key on VoterCandidates is fine. What you are describing is a unique constraint:

CREATE TABLE VotersCandidates (
    Id INT PRIMARY KEY IDENTITY(1,1),
    Voter_Id INT FOREIGN KEY REFERENCES Voters(Id) NOT NULL,
    Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
    Candidate_Id INT FOREIGN KEY REFERENCES Candidates(Id) NOT NULL,
    CONSTRAINT unq_VotersCandidates_Voter_Category UNIQUE (Voter_Id, Category_Id)
);

Now, you have another issue . . . it is possible for the category in this table to be inconsistent with the category in the candidates table. To fix that, use another unique constraint and foreign key reference:

CREATE TABLE Candidates (
    Id INT PRIMARY KEY IDENTITY(1,1),
    Name NVARCHAR(20) NOT NULL,
    Surname NVARCHAR(20) NOT NULL,
    Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
    CONSTRAINT unq_Candidates_Candidate_Category UNIQUE (Category_Id, id)
);

Then use this for the foreign key relationship in the votes table:

CREATE TABLE VotersCandidates (
    Id INT PRIMARY KEY IDENTITY(1,1),
    Voter_Id INT FOREIGN KEY REFERENCES Voters(Id) NOT NULL,
    Category_Id INT FOREIGN KEY REFERENCES Categories(Id) NOT NULL,
    Candidate_Id INT NOT NULL,
    CONSTRAINT fk_voterscandidates_candidates FOREIGN KEY (Category_Id, Candidate_Id) REFERENCES Candidates (Category_Id, Id) 
    CONSTRAINT unq_VotersCandidates_Voter_Category UNIQUE (Voter_Id, Category_Id)
);

And one final comment. I recommend naming the primary key after the table. So instead of candidates.id, it would be candidates.candidate_id. That way, the foreign key relationships are usually on columns with the same name — a form of self-documentation.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement