Search code examples
databasems-accessdelphi-xe8

Using Data from One Table in Another Table in Access


Hallo StackOverflow Users

I am struggling with transferring values between Access database tables which I will use in a Delphi program to tally election votes and determine the winning candidates. I have a total of six tables. One is my overall table, tblCandidates which identifies each candidate and contains the amount of votes they received from each party, namely the Grade Heads, the Teachers and the Learners. When it comes to the Learners we have four participating grades, namely the grade 8’s, 9’s, 10’s and 11’s, and each grade again has multiple participating classes, namely class A, B, C, etc.

Now, I have set up tables for each grade that contains all the classes in that grade. I named these tables tblGrX with X being the grade represented by 8 through 11. Each one of these tables has two extra fields, namely a field to identify a candidate and a field that will add up all the votes that candidate received from each of the classes in that grade. Lastly I have another table, tblGrTotals with fields Total_GrX (once again with X being the grade), that will contain all the total votes a candidate received from each grade, adding them up in another field for my tblCandidates table to use in its Total_Learners field.

So in short, I want, for example, tblGrTotals to use the value in the field Total of tblGr8 in its Total_Gr8 field, and then tblCandidates to use the value in field Total of tblGrTotals in its Total_Learners field. Is there any way to keep these values updated between tables like cells are updated in Excel the moment a change is made?

Thank you in advance!


Solution

  • You need to rethink your table design. I guess your background is Excel, and your tables are laid out like you would do in Excel sheets, but a relational database works differently.

    Think about the objects you are modelling.

    • Candidates - that's easy. ID, Name, perhaps additional info that belongs to each candidate. But nothing about votes here.

    • "Groups that are voting" or Parties. Not so trivial, due to the different types of parties. Still I would put them in one table, with Grade and Class only set for Learners, NULL for Heads and Teachers.

    e.g.

    +----------+------------+-------+-------+
    | Party_ID | Party_Type | Grade | Class |
    +----------+------------+-------+-------+
    |        1 | Head       |       |       |
    |        2 | Teacher    |       |       |
    |        3 | Learner    |     8 | A     |
    |        4 | Learner    |     8 | B     |
    |        5 | Learner    |     8 | C     |
    |        6 | Learner    |     9 | A     |
    |        7 | Learner    |     9 | B     |
    |        8 | Learner    |    10 | A     |
    +----------+------------+-------+-------+
    

    e.g.

    +----------+--------------+-----------+
    | Party_ID | Candidate_ID | Num_Votes |
    +----------+--------------+-----------+
    |        1 |            1 |         5 |
    |        1 |            2 |        17 |
    |        3 |            1 |         2 |
    |        3 |            2 |         6 |
    |        3 |            3 |        10 |
    +----------+--------------+-----------+
    

    Now: if you want to know the votes of Class 8A:

    SELECT Candidate_ID, SUM(Num_Votes) 
    FROM Parties p INNER JOIN Votes v
      ON p.Party_ID = v.Party_ID
    WHERE p.Party_Type = 'Learner'
      AND p.Grade = 8
      AND p.Class = 'A'
    GROUP BY Candidate_ID
    

    Or of all Grade 8? Simply omit the p.Class criteria.

    For the votes per candidate you join Candidates with Votes.

    Edit:
    for the votes counting differently, this is an attribute of Party_Type.
    We don't have a table for them yet, so create one:

    +------------+---------------+
    | Party_Type | Multiplicator |
    +------------+---------------+
    | Head       |             4 |
    | Teacher    |             3 |
    | Learner    |             1 |
    +------------+---------------+
    

    and to count all votes:

    SELECT c.Candidate_ID, c.Candidate_Name, SUM(v.Num_Votes * t.Multiplicator) AS SumVotes
    FROM Parties p 
      INNER JOIN Votes v ON p.Party_ID = v.Party_ID
      INNER JOIN Party_Types t ON p.Party_Type = t.Party_Type
      INNER JOIN Candidates c ON v.Candidate_ID = c.Candidate_ID
    
    GROUP BY c.Candidate_ID, c.Candidate_Name
    

    With a design like this, you don't need to keep updating data from one table into another - you calculate it when and how you need it, and it's always current.
    The magic of databases. :)