Country State City Table - ID or name - mysql

Hi I am relooking at the design of my mysql dbase for efficiency..
currently i have 3 tables
tble country :
country id, country name
table state :
state id, state name, country id
table city :
city id, city name, state id
I am thinking whether it is better to have ...
country name instead of country id in table state
state name instead of state id in table city
this is because everywhere in my code i have to run extra queries to convert country id, state id and city id from numbers to alphabets (eg. 1 to USA)... wouldn't it be better to just reference alphabetically.. (less queries)

The whole world has roughly
260 country/regions
5000 states
many many cities
Design varies based on what you need.
1 - For the purpose of tiny storage:
country(id,country)
state(id,state,country_id)
city(id,city,state_id)
2 - For the purpose of quick query:
city(id,city,state,country)
3 - For the purpose of middle way:
country(code,country)
state(code,country) -- you might merge country and state into one table based on code
city(state_code,city)
You might be interested to have a look at the iso codes:
https://en.wikipedia.org/wiki/ISO_3166-1 eg US
https://en.wikipedia.org/wiki/ISO_3166-2 eg US-NY
As a result iso state code contains iso country code.
UPDATE as per more info from you:
If you are designing property websites for USA.
1 - You do not need a country table, most likely all properties are within USA
2 - There are less than 60 states within USA, so you can use enum to save sates. As nearly all of you will understand NY = New York, as a result you do not need a state table.
3 - So you need a city table. As you will use city_id for more than 10,000,000 property records.
usa_cities(
id int PK
state enum('NY', 'LA', ...)
city varchar
...
)
properties(
id int PK
city_id int,
....
)
AS property table is usually very big, you might skip state table, and de-normalize design to speed up query for less joins:
properties (
id int PK,
state enum('NY', 'LA',...)
city varchar
...
)
You might be able to use enum for city as well, I m not sure how many cities in usa, but it is not encouraged at my first thought.

If you want less query there is some technique call denormalization.
You can weight what most important and fit to your need.
for more about demonalization meaning from techopidia and wikipedia

Related

Better to have one master table or split into multiple tables?

I am creating a database and I am unsure of the best way to design my tables. I have a table of real estate properties and I want to store information about those properties - e.g. bedrooms, bathrooms, size... I may have additional information I want to store in the future if it seems useful - e.g. last purchase price or date built, so I need to be flexible to make additions.
Is it better to create a separate table for each "characteristic" or to have one table of all the characteristics? It seems cleaner to separate the characteristics, but easier programming-wise to have one table.
CHARACTERISTIC TABLE
id property_id characteristic value
1 1 bedrooms 3
2 1 bathrooms 2
3 1 square feet 1000
4 2 bedrooms 2
...
OR
BEDROOM TABLE
id property_id bedrooms
1 1 3
2 2 2
...
BATHROOM TABLE
id property_id bathrooms
1 1 2
...
Forgive me if this is a stupid question, my knowledge of database design is pretty basic.
I would suggest a middle ground between your two suggestions. Off the cuff I would do
property table (UID address zip other unique identifying properties)
Rooms table ( UID, propertyID, room type , room size,floor, shape, color, finish, other roo specific details ect..)
Property details (uid, propertyID, lot size, school district, how cost, tax rate, other entire property details)
Finally a table or two for histories eg.
Property sales history(UID, PropertyID , salesdate, saleprice, sale reason, ect..)
Often grouping your data by just "does it match" logic can yield you good results.... care needs only be taken to account for 1to1 and 1tomany relationship needs of tables.
I am focused to this:
"I have a table of real estate properties"
Now as far as i knew you has to be a different type of:
Houses
Bedrooms
Comfort room and so on.
For further explanation:
You has to be a table of:
1. House type
2. House names,description,housetypeid,priceid,bedroomid,roofid,comfortroomid and any other that related to your house.
3. Bedroom type
4. Comfort room type
5. Dining type
6. roof type if it has.
7. House prices
8. Bathroom type
something like that.
One table with a few columns:
Columns for price, #br, #bath, FR, DR, sqft and a small number of other commonly checked attributes. Then one JSON column with all the other info (2 dishwashers, spa, ocean view, etc).
Use WHERE clause for the separate columns, then finish the filtering in you client code, which can more easily look into the JSON.

Database Dependencies - Database Design

I'm designing a database with the following attribute dependencies:
Approach 1: A <- B <- C <-D
Approach 2: A <- B, {A,B} < C, {A,B,C} <- D;
With the first approach, attribute D is dependent on attribute C, C on B and B on A.
With second approach, attribute D can be gotten directly from A.
Please I need your help on which approach is better. Thanks
EDIT
Sample tables for approach 1
Country_info
------------- , state info, city_info, village_info
id | country_id | name
TABLE PAIRS
country_state
id | state_id | country_id
state_division
id | division_id | state_id
village_division
id | village_id | division_id
Now, I have the id of a village and I want to know the name of the country in which it belongs. I will have to look for the division, state before arriving at the country.
With the second approach, the village table will have the division_id, state_id and the country_id.
Thanks!
If village is "main" obiect which will be used very often (and it's relations to other tables will be also often used) then by using second approach you will reduce number of code lines and increase performance (eg. in filtering villages by country).
KISS.
Table 1: A business/person/etc has an address and a City.
Table 2: The City also includes the Viliage, State, Province, Country_code, Postal_code, whatever.
Normalizing each layer is overkill.
If you have half a dozen tables, imagine the number of JOINs needed to get all the parts of the address!

MySQL Query to display records from table

I have a query.I have table with two columns country and state.I want to display columns in following format
Country State
----------- ---------
India Delhi
Bangalore
Kolkata
Mumbai
USA California
Florida
Las Vegas
Virginia
It means "India" just appear one time in country column and and repeated values would come as blank value in country column when i select country and state from table.
Thanks in advance
Presentation is usually if not always better done outside of SQL so I'd recommend doing this in whatever your presentation layer runs, but if it's a requirement for the query, you can do it using session variables;
SELECT Country, State FROM (
SELECT IF(Country=#country, '', Country) Country, State, #country := Country
FROM (SELECT Country, State FROM Table1 ORDER BY Country, State) dummy1,
(SELECT #country:='') dummy2
) dummy3;
An SQLfiddle to test with.
Just to show a (probably) better way, you can use this to get a list of states per country, and process it further in your presentation layer;
SELECT Country, GROUP_CONCAT(State) FROM Table1 GROUP BY Country;
Another SQLfiddle.
use pl/sql.Moreover your table would be voilating 5th normal form.

Querying normalized database, 3 tables

I have three tables in a MySQL database:
stores (PK stores_id)
states (PK states_id)
join_stores_states (PK join_id, FK stores_id, FK states_id)
The "stores" table has a single row for every business. The join_stores_states table links an individual business to each state it's in. So, some businesses have stores in 3 states, so they 3 rows in join_stores_states, and others have stores in 1 state, so they have just 1 row in join_stores_states.
I'm trying to figure out how to write a query that will list each business in one row, but still show all the states it's in.
Here's what I have so far, which is obviously giving me every row out of join_stores_states:
SELECT states.*, stores.*, join_stores_states.*
FROM join_stores_states
JOIN stores
ON join_stores_states.stores_id=stores.stores_id
JOIN states
ON join_stores_states.states_id=states.states_id
Loosely, this is what it's giving me:
store 1 | alabama
store 1 | florida
store 1 | kansas
store 2 | montana
store 3 | georgia
store 3 | vermont
This is more of what I want to see:
store 1 | alabama, florida, kansas
store 2 | montana
store 3 | georgia, vermont
Suggestions as to which query methods to try would be just as appreciated as a working query.
If you need the list of states as a string, you can use MySQL's GROUP_CONCAT function (or equivalent, if you are using another SQL dialect), as in the example below. If you want to do any kind of further processing of the states separately, I would prefer you run the query as you did, and then collect the resultset into a more complex structure (hashtable of arrays, as a simplest measure, but more complex OO designs are certainly possible) in the client by iterating over the resulting rows.
SELECT stores.name,
GROUP_CONCAT(states.name ORDER BY states.name ASC SEPARATOR ', ') AS state_names
FROM join_stores_states
JOIN stores
ON join_stores_states.stores_id=stores.stores_id
JOIN states
ON join_stores_states.states_id=states.states_id
GROUP BY stores.name
Also, even if you only need the concatenated string and not a data structure, some databases might not have an aggregate concatenation function, in which case you will have to do the client processing anyway. In pseudocode, since you did not specify a language either:
perform query
stores = empty hash
for each row from query results:
get the store object from the hash by name
if the name isn't in the hash:
put an empty store object into the hash under the name
add the state name to the store object's stores array

How to prioritize a LIKE query select based on string position in field?

I am attempting to query a table for a limited resultset in order to populate an autocomplete field in javascript. I am, therefore, using a LIKE operator with the partial string entered.
If I have, for example, a table such as:
tblPlaces
id country
1 Balanca
2 Cameroon
3 Canada
4 Cape Verde
5 Denmark
For the sake of this example, let's say I want two rows returning - and yeah, for this example, I made up a country there ;) I want to prioritize any instance where a partial string is matched at the beginning of country. The query I began using, therefore is:
SELECT id, country FROM tblPlaces WHERE country LIKE 'ca%' LIMIT 2
This returned 'Cameroon' and 'Canada' as expected. However, in instances where there are no two names in which the string is matched at the beginning of a word (such as 'de'), I want it to look elsewhere in the word. So I revised the query to become
SELECT id, country FROM tblPlaces WHERE country LIKE '%ca%' LIMIT 2
This then returned 'Cape Verde' and 'Denmark', but in doing so broke my original search for 'ca', which now returns 'Balanca' and 'Cameroon'.
So, my question is, how to go about this using a single query that will prioritize a match at the start of a word (perhaps I need to use REGEXP?) I am assuming also that if the 'country' column is indexed, these matches will at least be returned with subsequent alphabetical priority (i.e. Cameroon before Canada etc).
If you mean to prioritize matches that are Exactly at the start...
SELECT id, country
FROM tblPlaces
WHERE country LIKE '%ca%'
ORDER BY CASE WHEN country LIKE 'ca%' THEN 0 ELSE 1 END, country
LIMIT 2
EDIT
More generic and possibly faster (Assuming "closer to the start the 'better' the match")...
SELECT id, country
FROM tblPlaces
WHERE country LIKE '%ca%'
ORDER BY INSTR(country, 'ca'), country
LIMIT 2