Query to find lakes that are in multiple states - mysql

I have tables to hold information about Lakes, Counties, and States. I also have a table called LakeLocation that is simple a pair of foreign keys of a LakeID and CountyID, so I can know where they are. And each county has a StateName inside it.
A high-level view of it all is something like this:
Lake = {id,name,...}
County = {id, name, StateName ....}
State = {name, ...}
LakeLocation = {LakeID, CountyID}
I am trying to find out which states have lakes that are in more than one state. An example is Lake Tahoe which crosses four county lines and two state lines. I know that I will need a recursive query, but I only understand those for simple one table child/parent type relationships. Not this.
How can I design a query that does what I need? Thanks

You only need a group by to know what are the lakes
SELECT LakeID
FROM LakeLocation
GROUP BY LakeID
HAVING COUNT(CountyID) > 1
Then if you want lake names
SELECT *
FROM Lake
WHERE LakeID IN (<previous query>)

Related

mysql - Database organization for representing location

I need to create database which will contain the following entities in country:
Regions
Municipalities
Now comes the hard part for me:
Municipality can also be city, where city can (but not always) have its own municipalities.
Municipality can have several cities.
Municipality in both cases contains several settlements
I wanted to create several tables, for example:
regions (region_id, region_name)
municipalities (municipality_id, municipality_name, region_id).
cities (city_id, city_name, region_id)
city_municipalities (city_municipality_id, city_municipality_name, city_id)
settlements (settlement_id, settlement_name, municipality_id, city_municipality_id)
i think that here i make problem. There would be a lot of NULLs for municipality_id or city_municipality_id, since i cant have both field filled.
But right now it comes to my mind to have two tables organized like this:
geo_entity(geo_id, geo_name, geo_type_id, parent)
geo_entities_type (geo_type_id, geo_type_name)
this table will contain definitions of what geo_entity entry is, like:
1 Region
2 Municipality
3 City
4 City Municipality
5 Settlement
What should i stick to? Do you have a better approach and which one?

Relating rows to one another in separate table

I have a table called Neighborhoods. Some of these neighborhoods are related, and I'd like to be able to capture that relationship in another table.
For example: NYC's Union Square is a neighborhood that's near East Village. I want to perform a query for nearby neighborhoods on Union Square and get East Village. Likewise, I'd like to query nearby neighborhoods on East Village and receive Union Square.
My plan is to have a table called NearbyNeighborhoods that links neighborhood1 to neighborhood2.
Is there a smarter way to do this?

MYSQL Postcode lookup

I have a MYSQL table with the following fields postcode, town, county. Based on the postcode number I want to do a lookup to get the closest matching town and county.
The postcodes are essentially postcode districts, so for example:
AL1 = Saint Albans, Hertfordshire
AL10 = Hatfield, Hertfordshire
In the example above lets say I'm querying AL10 I want to retrieve the closest match, so in this case it would be AL10 = Hatfield, Hertfordshire. But if AL10 didn't exist I want to retrieve AL1.
I have got around this by first querying for a match on AL10 then if that failed AL1, then if that failed AL.
But this seems like a very inefficient way to achieve this seeing as I'm querying the table potentially 3 times. Is there a better and more efficient way to achieve the same goal?

Displaying name from ID of lookup tables - design Q

I am sure this is a basic question but I am new to SQL so anyways, for my user profile I want to display this: location = "Hollywood, CA - USA" if a user lives in Hollywood. So I assume in the user table there will be 1 column like current_city which will have ID say 1232 which is a FK to the city table where city_name for this PK = Hollywood. Then connect with the state table and the country table to find the names CA and USA as the city lookup table will only store the IDs (like CA = 21 and USA = 345)
Is this the best way to design the table OR I was thinking should I add 2 columns like city_id and city_name to the user_table. And also add country_id, country_name, state_id, state_name to the city table. This way i save on trips to other parent tables just to fetch the name for the IDs.
This is only a sample use case but I have lots of lookup ID tables so I will apply the same principle to all tables once i know how to do it best. My requirement is scalability and performance so whatever works best for these is what i would like.
The first way you described is almost always better.
Having both the city_id and city_name (or any pair of that kind) in the users table is not best practice since it may cause data discrepancies - a wrong update may result in a city_id that does not match the city_name and then the system behavior becomes unexpected.
As said, your first suggestion would be the common and usually the best way to do this. If table keys are designed properly so all select statements can use them efficiently this would also give the best performance.
For example, having just the city_name in the users table would make it a little quicker to find and show the city for one user, but when trying to run other queries - like finding all users in city X, that would make much less sense.
You can find a nice series of articles for beginners about DB normalization here:
http://databases.about.com/od/specificproducts/a/2nf.htm. This article has an example which is very much like what you are trying to achieve, and the related articles will probably help you design many other tables in your DB.
Good luck!

Basic table design Q

I am trying to understand this concept. For example: I have two tables City and Country.
Country
-------
id
abbreviation
name
City
-----
id
name
Country (name or id, or both? - This is the question)
To reference and keep a particular city in sync with the country it belongs to I guess this will be reference to country.id as a FK. This means an example of the city table will be: (200, New York, 19) - where 19 = USA in country table. But this doesn't help a person viewing the table because he wont know what 19 is without looking up in country table what 19 is.
So I want to add the country name also to city table so it reads: (200, New York, USA). I don't need the 19 to display because 19 is of no use to the reader but is only used in back to connect the tables.
So what should my tables colunms / FK look like to i can store in city table rows like this (200, New York, USA), yet ensure New york will always reference to USA in the USA lookup and keep the 19 which is the primary key for USA out of the city table so the tables look clean and easy to understand? And I assume if these are referenced, tomorrow if i update USA to be 20, it will update in the city table on its own, and same way if I rename USA to US it will update on city table on its own?
My DB is in MySQL
Why not use ISO 3166 country codes (2 character or 3 character) as the country ID? This leaves you with recognizable codes in the city table; you can map to the full name in the country table.
As for viewing the data, use a VIEW to create a good looking table:
CREATE VIEW CityInfo(CityID, CityName, CountryID, CountryName) AS
SELECT ci.id, ci.name, ci.country, co.name
FROM City AS ci JOIN Country AS co ON ci.Country = co.id;
You don't ... if you need to have "usable" tables in the DB, so someone can easily view something useful with select * etc. (or to make programing the SQL by hand easier). Then you create the tables as above, in normal form, and then create a VIEW which combines the tables.
Tables aren't supposed to be viewed by people: some application should be accessing the tables to present data to people in a way they can parse it. The reason you want to have country.id as a FK in your table is so that you don't have a million rows whose country name is "USA", because then all kinds of problems can occur, like what happens when you mistype and "US A" lands in one of the fields? Or what if you want to change what the user sees from "USA" to "United States"?
The right way to handle it is to use the country.id as you initially suggest, and then use a JOIN statement to present the data, like this:
SELECT city.name, country.name
FROM city JOIN country ON country.id = city.country
My syntax could be off, but that's in essence what you want.