I am trying to figure out the best method to relate country, region and town tables.
On my website I want the user to be able to just enter a town. Then optionally country and region, both of which will be required to be entered or not at all.
Currently my tables are as such
tbl>User has townID (FK)
tbl>town has id(PK) townName regionID(FK DEFAULT NULL)
tbl>region has id(PK) regionName countryID(FK NOT NULL)
tbl>country has id(PK) countryName
I thought to possibly further spit the user to town relation to:
tbl>User has locationID (FK)
tbl>location has id (PK) townID(FK) regionID(FK) countryID(FK)
But I think that is unnecessary and just further complicates the issue?
The country database is already populated. I intend to build up my own references of town > region > country relations as entered by users. So if a user enters a town with no region and country then it is entered into tbl>town without a regionID if there isn't already a town with the same name without a region ID. This is same for a town where a region and country ID has been entered by the user. Only I check that there isn't already a town > region > country relation that already exists before entering. Later on in the development of the site I will be providing Ajax suggestions for country/region based upon the town entered by a user.
So to the questions:
I can envisage pitfalls with this such as duplicate data or data possibly being overwritten. Is there a better way to construct the tables to fit in with my desired methods?
This might get answered by the prior question: but is there anything I can do to reduce the PHP processing of the tables. Obviously I'd prefer to just insert with one PHP statement but I think there are too many caveats to do it at once.
Also as the users town entry may be null and may or may not contain a foreign key reference to a region how is it best to create a View that takes that into consideration?
As it will be hosted I would rather not be using MySQL functions.
Please let me know if you need any clarification. I really want to get this right the first time before continuing, so your help will be invaluable.
I don't think you reduce the code because it's much too explicit. You can change it, but it won't be better.
Accepting a town name without a region and country is like letting someone enter their first name without their middle or last. It's data, but it's not an identifier.
Fullerton's full name is "Fullerton, California, USA". By not requiring Fullerton's full name, you abandon foreign keys for data integrity. ("Fullerton, California, USA" is a city; "Fullerton, Alabama, USA" is not.) Good luck with that.
If you're going down this path, the best advice I can offer you is get rid of the id numbers. ISO publishes standard codes for countries and subdivisions of countries. You can look them up in Wikipedia. Storing natural keys will reduce the number of joins from 3 to zero. Zero joins is almost always going to out perform 3 joins.
You'll probably need to use outer joins to create your views.
Related
I'm building an api, but I'm too afraid to it wrong with db design. I'm trying to practice an address book, where employee can have their addresses (home, work, other). So is this many to many relationship?
Is my db design correct? a compound table is created to for flexibility
Is ON DELETE and ON UPDATE important here? How to set it so that an employee is removed, we don't want to keep other records in other 2 tables?
First off I feel compelled to add that SO is not really the place for this, I am not sure but it wouldn't surprise me if there is a site/board just for Databases. A lot of this stuff is personal preference and Opinion.
Probably something like this would be a more appropriate place:
https://dba.stackexchange.com/
That said:
I would change the PK to just id in the tables, so address_type.id it would just be id and the same for person. It just becomes to redundant to do person.person_id
the id's should be INT(10) unsigned AUTO INCREMENT 10 is ten places, or about 99,999,999,999. You can't have negative ID's so the DB should enforce this. I do 10 because, it's INT(11) and that keeps the sign place reserved. It's not really necessary, but i do it out of habit for any unsigned int.
I would plural the bridge table persons_addresses. Because, records in person or address are for one entity. Records in the bridge table are for multiple entities. For me it makes it easier to tell that it's a bridge table. All others are singular these are plural, for example.
The main thing for "naming convention" is to be consistent. if you do {table}_id for your IDs then do them all that way. If you do person don't do something like zipcodes for a table. And even the column names if you do person_id then dont do any columns like FullName, fullName or Full_name etc. I would say pick a way and stick to it, it makes it much easier when you write code if you know ahead of time the table name will be singular. As I said I like the plural use for the bridge table as you would seldom use them by themselves.
For the relationship. You would still have to delete person and address separately. But the record in persons_addresses would be updated or deleted if you changed them to cascade. I think of it this way: the table that defines the relationship is the one that receives the changes.
This is the way it should be though. Imagine you have 2 person records with the same address. If you delete one person, you don't want the address deleted from both of them. Also, you would probably not want a person deleted if their address was deleted. So at most it should be:
person > persons_addresses > address
I am not sure if there is an automatic way to delete the address when there are no records in the bridge table. I've always just manually done it, but you could use a trigger to do it if there is not a better way.
For reference:
A trigger is a named database object that is associated with a table, and that activates when a particular event occurs for the table.
https://dev.mysql.com/doc/refman/5.7/en/triggers.html
To be honest I've never done it for that and I think triggers may not fire on cascade actions, I remember something about only being fired on SQL statements. In which case it may be better to do the delete from person solely with the trigger. So you would delete a person, the trigger would fire and you would check if anyone else uses the address, If false you delete both the persons_addresses record and the address record. If true you would only delete the persons_addresses record.
One other thing I would do, is break address down to have a separate zipcode. At my work we purchased a DB table with all the US zipcodes, which contain all the city, state, county, zip ( of course ) and the latitude and longitude.
By using that our address table contains a Many to One relationship to zipcodes. One zipcode can have many addresses associated with it. And we also break that down by state using a state table. So it becomes
address
id | street | street2 | zipcode_id
zipcode
id | city | state_id | county | zip | latitude | longitude
state
id | name | abbreviation
Then when users enter a zipcode it shows an auto-complete with all that information in it.
Then the final thing we do is normalize all the ST, N, NW etc. We chose to change them to the full name so ST becomes STREET when saved. We went that way because you could have street addresses like 187 NORTH PARK which would look like 187 N PARK which is way worse then 187 PARK NE becoming 187 PARK NORTH EAST. You would be amazed the variation on addresses, what I call the "dirt" or "dirtyness".
All of this, combined, removes a lot of errors. But as I said in the comments we deal with lawsuit data, so we have to have more accuracy and thus more complexity then just an address book.
I am not sure how to formulate the question, so I didn't find anything useful enough regarding my problem.
1. In PRO(projects) I have 3 columns: "organizer", "partners", "other". I want to use information from table ORG(organisations) in all of these 3. Also, I need to show more than one partner. Is it possible? For example, I have
org:
name |country|city |
apple |shop |fruits part |
cherry|plate |big |
orange|plate |little |
banana|shop |frozen fruits|
I want to show in view.php:
All projects:
name |organizer|partner |other |place |
salad |banana |apple,cherry |orange |plate,little|
salad2|banana |apple |orange |plate |
Info for place in PRO is taken from two tables, country and city. But country and city are also used by organisation. organisation's country doesn't equal project's country(for example, project takes place in London, but none of the participants'organisations are based in London).
Are all of these things doable with what I already have?
I get "circled" relationship thanks to country/city double usage, is it allowed?(my teacher said no or should be avoided -? I don't remember- and I got different opinions from web).
If you want to Add multiple partners, there are really two ways to do it.
You could add a table to store partner information you could then have a column that contains a foreign key to the projects primary key that they are assigned to.
(this would be best if a partner is never assigned to multiple projects)
this is really an extension of #1. except in this case if you need to have projects assigned to multiple partners and partners assigned to multiple projects you could add a another table with only two columns. The first would be a foreign key to a project primary key, and the second would be a foreign key to partner's primary key. This way if you want to query for all of the partners assigned to project you could do:
Select * from Partners_Table where id=(Select partner_id from CrossReference_Table);
you can do the same the other way too.
Your Country Fields should be foreign keys to your country table, Same with city because your projects are not necessarily in the same city as there respective organization, therefor they should not be linked to the organization's city and country field. Everything else looks good from what I can tell.
I want to store following information about the job seeker in mysql tables .
Personal Information
1)Name
2)Caste
3)Date of Birth
4)Annual Income (optional)
5)Source of Income (Optional)
6)Identification Mark
Family Information
1)Father Name
2)Mother Name
3)Father's source of Income
4)Mother's source of Income
Contact Information
1)Address
2)Pin Code
3)District
4)State
5)Mobile Number
6)Name of person who own a mobile(If mobile belong to someone-else)
7)Relation with person who own a mobile(If mobile belong to someone-else)
Education Qualification
1)Metric - Subject, Total Marks , obtained Marks , Year of Passing , Board Name , University Name.
2)Intermidiate(optional) - Subject, Total Marks , obtained Marks , Year of Passing , Board Name , University Name.
3)Graduation (optional) - Subject, Total Marks , obtained Marks , Year of Passing , Board Name , University Name.
Yes/No Questions
There are around 10 Yes/No Types Questions .
After recieving user application for a particular post .
The user application would go through following screening process .
1)Short list candidates who have submitted hard copy of their application.
2)Screen candidate based on information(education qualification,annual income etc) submit by them and shortlist candidate for first merit list.
3)Some other screen process to shortlist candidate for final merit list.
So I would be required to store following information about status of application :
1)Hard Copy Received Or Not and if received then i also need to store the date when the hard copy was received
2)Shortlisted in First Merit List or not. If shortlisted then i also need to store the rank in first merit list and if not shortlisted then i need to store the reason why the particular application was rejected .
3)Shortlisted in final merit list or not If shortlisted then i also need to store the rank of candidate in final merit list and if not shortlisted then i need to store the reason why the particular application was rejected.
A user would have single set of personal , contact, family ,education information .
The problem that i see with single table is with optional fields .
Can you please suggest me a better schema .
No you should not. There are many reasons why a single table is not appropriate.
Some questions to ask:
Is there a possibility that a user may have more than one address or phone? Could more than one person belong to the same University? Is it likely that a subject will be used more than once between all the people in your database?
Generally speaking, if you have sections like you listed, they would likely be good candidates for separate tables. If you have any reusable data, it should be separated into multiple tables.
Please consider checking out some tutorials on normalization.
In the meantime, here are a few basic rules of good database design:
Rule 1: Eliminate Repeating Groups. Make a separate table for each set
of related attributes, and give each table a primary key.
Rule 2: Eliminate Redundant Data, if an attribute depends on only part
of a multi-valued key, remove it to a separate table.
Rule 3: Eliminate columns not dependent on key. If attributes do not
contribute to a description of the key, remove them to a separate
table.
Check out this URL for more information: http://www.dbnormalization.com/
I have a two part question with no code to show, but i hope you can help:
Essentially, i have a website which lets businesses create a profile for themselves (original table schema here).
Now within the site I want a form with three select lists in it: the first select list is for business catagory/tag - I have managed to create a query which will return entries from my main business registration table by using a Toxi solution.
However i also want a second select list with countries or regions, and a third select list with states/counties which will load automatically BASED on the selection from the Country select list.
Then naturally, on submitting the form, i want to return the results to the visitor.
So, apart from wondering how to achieve this much in PHP/MySQL, i have a more fundamental question about whether to set up the countries/states 'tagging' or 'catagories' field as another Toxi solution, or if there's a better way to do it. For instance, should i/can i just create seperate tables to populate the select lists with states/counties based on country selection, and have the actual country and state fields that a business selects on registration, stored within my main business table, and just match the strings when the user hits submit, in order to reduce queries to MySql and improve speed?
As always, your advice and help is greatly appreciated.
Thanks
Dan
Think about the "full name" of a state (or whatever political division is one level narrower than "country"). In the Americas, here are some "full names" of states.
California, US
Connecticut, US
Ontario, CA
Sonora, MX
Lara, VE
Base your lists on a two-column table of the full names of states.
ISO country codes
The critical point is that your selection lists shouldn't allow values like "Alabama, MX" or "Sonora, US".
I am developing a web portal which will store the job requirement like, experience, salary etc in a database and whenever any user (new/old) matches that criteria the job should display him in his dashboard after he logins.
My Columns in employees are
Age, City, Industry, Marital status.
So, when admin post the jobs, he will define the criteria which user can see this. For ex. Age between 20-30, City only Mumbai like that.
How do I store these information in database efficiently.
I am using PHP/MySQL.
You would ideally create a table with the user's:
Unique ID
Name
Marital Status
City
Age
Create a second table to pair industry and UUID, like so:
Unique ID
Industry
This is so that a given user can belong to more than a single industry.
Third, create a table to pair user IDs and experience:
Unique ID
Position
Industry
Start date
End date
Since industry and experience are data which a given user can possess an arbitrary quantity of, you need to abstract the data into its own tables. Don't try representing all of this information in a single table - it's a solution that scales poorly past a single employer.
I'd also like to note that if your application is going to be deployed in the United States and several other nations, it's actually illegal for employers to discriminate based on age and marital status. I'm assuming this doesn't apply to you, but there it is.
in terms of speeding up your look ups, the most important thing you'll want to do is make sure you index the columns that you will be searching against.
So for instance, if you want to do a search that is based on someonen's start date:
like:
select * from tablename where start_date > 'some date';
then it's very important that you index the start_date column on the 'tablename' table.
Apart from making sure that your tables are orthongal deciding what the best way of setting up your database you'll want to ask your self what kind of questions will you be asking your database and design your tables around those questions.