简体   繁体   中英

database design (joining 3 tables together)

My goal is to create a web app that show elections results from my country.

The data is the results for every candidates in every city for every election.

  • An election has many candidates and many cities.
  • A candidate has many elections and many cities.
  • A city has many elections and many candidates. For the 2nd round of the last presidential election:
City inscrits votants exprime candidate1 score C1 candidate2 score C2
Dijon 129000 100000 80000 Macron 50000 Le Pen 30000
Lyon 1000000 900000 750000 Macron 450000 Le Pen 300000

How can I join those 3 tables together?

Is it possible to create a join table between the three, like this?

  create_table "results", force: :cascade do |t|
    t.integer "election_id", null: false
    t.integer "candidate_id", null: false
    t.integer "city_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["city_id"], name: "index_results_on_city_id"
    t.index ["candidate_id"], name: "index_results_on_candidate_id"
    t.index ["election_id"], name: "index_results_on_election_id"
  end

But in this case, where can I add the city infos for election? (Column 2, 3, 4 of my data example, ie: in this city, for this election XXX people voted, XXX didn't vote.)

I came with this database schema:

my database schema

This will not work because I will not be able to access the result of a candidate in a specific city for a specific election. It looks like there is no connection between cities and candidates.

To actually tie these models together and record the data required you need a series of tables that record the election results at each level your interested in:

# rails g model national_result candidate:belongs_to election:belongs_to votes:integer percentage:decimal
class NationalResult < ApplicationRecord
  belongs_to :candidate
  belongs_to :election
  delegate :name, to: :candidate,
                  prefix: true
end

# rails g model city_result candidate:belongs_to election:belongs_to votes:integer percentage:decimal
class CityResult < ApplicationRecord
  belongs_to :city
  belongs_to :candidate
  belongs_to :election
  delegate :name, to: :candidate,
                  prefix: true
end

Instead of having C1 and C2 columns you should use one row per candidate instead to record their result. That will let you use the same table layout even if there are more then two candidates (like in a primary) and avoids the problem of figuring out which column a candidate is in. Use foreign keys and record the primary key instead of filling your table with duplicates of the names of the candidates which can easily become denormalized.

While you might naively think "But I don't need NationalResult, I can just sum up all the LocalResult's." - that process would actually expose any problems in your data set and very likely be quite expensive. Get the data from a repubable source instead.

You can then create the has_many assocations on the other side:

class Canditate < ApplicationRecord
  has_many :local_results
  has_many :national_results 
end

class Election < ApplicationRecord
  has_many :local_results
  has_many :national_results 
end

class City < ApplicationRecord
  has_many :local_results
end 

Keeping track of the number of eligable voters per election/city will most likely require another table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM