mysql query path/radius - mysql

I have 2 tables: city and city_neighbor.
city contains a list of all cities while city_neighbor contains the neighbor(s) of a given city: insert into city_neighbor (city_id, neighbor_id) Values(1,2) - where neighbor_id is the id of another city from the city table. Nothing too fancy.
What I must build is a page where the user can select all cities in a given radius. Ex: select all cities neighboring Chicago in a radius of 5 cities for example. IMPORTANT: it's radius of 5 cities. I can't use radius of miles/km, I need to use this path style of radius (no lat/long related responses please).
Second scenario: The user wants to select all cities ordered ascending by the number of jumps (where a jump is one city which must be passed in order to get from A(Chicago) to B).
Any ideas?
P.S. My database contains ~8,000 cities.

FUNCTION: CountNeighbors
IMPORT: city, depth
EXPORT: neighbors
ALGORITHM:
neighbors = SET
++depth
direct_neighbors = SELECT NEIGHBORS OF city
neighbors += direct_neighbors
IF depth < 5
FOR EACH neighbor IN direct_neighbors
neighbors += CountNeighbors(neighbor, depth, result)

Related

What are the MySQL queries for the following tasks? Are my solutions and line of thinking correct so far? Thank you very much

This is my very first question on Quora. Thanks for any recommendations , solutions and remarks. I was not provided with many specifics and data, this is a assignments where one must use his or her imagination to fill in particular data and variables. What counts is the correct logic, approach and covering possibilities. Your help is highly appreciated! Thank you!
Country and Continent table
Required Visual Result for Question 3
Questions:
Write a query that would select all countries with GDP of more than 1 000 000 000 USD
Write a query that would return all countries in Europe (specifically) with GDP of more than 1 000 000 000 USD
Write a query that lists all continents with GDP per continent (as the sum of the GDP of all countries). Each country belong to one continent only.
For what result should look like - please resort to "Required Visual Result for Question 3" image.
My Solutions:
select * from countries where GDP > 1000000000
select * from countries where continent_id = 2 and GDP>1000000000;
select sum(GDP) from countries where continent_id = 4;
However, here in 3) I can only have the GDP sum displayed, and do not know how to have the continent's name on the left side as well. Please, if possible, assist with having the continent's name displayed and then right next to it and on the right handside - the relevant GDP sum.
Welcome!
Your image shows the tables as country and continent but your queries refer to countries? So which is it please?
On the basis your image is correct but the queries are wrong then number 3 would be as below:
With no 3 your currently only going to get the some for the continent with the ID of 4.
select sum(GDP) from country where continent_id = 4;
So what you want to do is remove the WHERE and the GROUP BY continent_id to give you 1 result per continent.
select sum(GDP) from country where 1 GROUP BY continent_id
No to get the continent name included in your results you can use the JOIN syntax.
In this instance you want all your records from country and just the records from continent that match your join condition which will be the continent_id from country and the id from the continent table.
SELECT
`continent`.`name`, sum(`GDP`)
FROM `country`
LEFT JOIN `continent`
ON `country`.`continent_id` = `continent`.`id`
GROUP BY `continent_id`
ORDER BY `continent`.`name` ASC;
That should give you the results 1 per continent as required.
I've specified the table names as its clearer how to target specific columns from each table.

Find all rows that contain a London postcode using SQL query

Is there a way to find all the orders shipped to London using an SQL query? Simply searching for London in the columns doesn't work as some customers have put the district name rather than "London".
So I thought the best way to go was via the postcode. Would this be the best way to go about finding the rows? And continue with using OR statements for each postcode?
select * from tt_order_data
where ship_postcode like "e1%"
According to wiki, this is the postcode range:
The E, EC, N, NW, SE, SW, W and WC postcode areas (the eight London
postal districts) comprised the inner area of the London postal region
and correspond to the London post town.
The BR, CR, DA, EN, HA, IG, SL, TN, KT, RM, SM, TW, UB, WD and CM (the
14 outer London postcode areas) comprised the outer area of the London
postal region.[20]
The inner and outer areas together comprised the London postal
region.[13]
One way to do this would be to leverage REGEXP and define a pattern that matches only ship_postcodes that begin with one of the aforementioned London postcode character sequences:
SELECT *
FROM tt_order_data
WHERE UPPER(TRIM(ship_postcode)) REGEXP '^(E|EC|N|NW|SE|SW|W|WC|BR|CR|DA|EN|HA|IG|SL|TN|KT|RM|SM|TW|UB|WD|CM)'
DB Fiddle | Regex101
It's important to keep in mind that you will still need to perform some amount of data cleansing if the inputs weren't properly controlled, as invalid postcodes would match this filter (e.g., E1 7AA is valid, but this filter would also consider a string like ERGO valid as well).
As an aside, I'm not exactly sure how this will perform with your specific dataset at scale, but if this is for a one-off exercise then it should fit your needs just fine.

Find all regions within 400km for each region in list

I have a mysql table called Region
id | name | lat | lng
I have a list of region id I want to search like
(48346, 48335, 48325, 48324)
For each region id above, I want to search region within 400km which can be done using (the following works for one region search and will return a list of regions within 400km of the chosen region):
// find region within 400km
SELECT id, (6371 *
ACOS(COS(RADIANS(lat)) *
COS(RADIANS(center_lat)) *
COS(RADIANS(lng) -
RADIANS(center_lng)) +
SIN(RADIANS(center_lat)) *
SIN(RADIANS(lat)))) AS distance
FROM
region
WHERE
active = 1
HAVING distance <= 400;
My problem is, currently I'm running PHP loop through the region list (48346, 48335, 48325, 48324) and for each id call the query to find region within 400km (after the loop, 4 lists of regions returned)
Is there a way to use one SQL query to find all regions IN (48346, 48335, 48325, 48324); and for each region find all regions within 400km of each region in the list

Why this query doesn't work with such condition?

I'm trying to solve some tasks from this http://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial
At the last task(number 8) I wrote a query:
select name, continent from world a
where a.population >
(select 3*max(population) from world b
where b.continent = a.continent)
but this query doesn't return any rows. But works almost the same query(just added an additional conditin in the end of subquery). But what's the matter? Why doesn't it return raws even if names of countries are the same?
select name, continent from world a
where a.population >
(select 3*max(population) from world b
where b.continent = a.continent and a.name <> b.name)
Let me translate what both query does to english, so you can realize the difference.
first query; compare and get all countries who are on the same continent and have more than 3 times of the maximum populated country in that continent.
second query; compare and get all countries who are on the same continent and have more than 3 times of the maximum populated country in that continent except himself.
in your first query the maximum populated country cannot be more than 3 times more populated than himself if he is the max populated country himself so your query returns 0 results.
but on the second query the maximum populated country EXCEPT himself can have population 3 times more than other countries in the same continent.

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