get a list of cities from location model and how many locations exist for each city - mysql

I have a location model which has a few columns: title, address, city, state, etc...
I am trying to show a list of all the cities based on the locations in my database. Then, I am trying to figure out per city how many locations there are.
I want to be able to output something like
Tampa(10)
Denver(20)
Atlanta(15)
... and so on
Currently to get a list of cities in the database I am using the following code:
cities = Location.uniq.pluck(:city)
Technically I could loop through all the cities and do a COUNT(*) WHERE city = "cityname"... but that seems like a very inefficient way to do this.
Is there a better way to accomplish this?

Location.group(:city).count
This will give you a hash with city as the key and value as the count

you should use a GROUP BY insted
SELECT city, COUNT(*) FROM locations GROUP BY city;

Related

mySql - Finding customers near a specific city

I am trying to craft a query to find all customers within X miles of a given city and state, using basically the following table structure:
Users Table
-----------
ID
PersonsName
ZipCode
Zipcodes Table (contains all ZIPs in the US)
--------------------------------------------
ID
ZipCode
City
State
latitude
longitude
It would be easy to find nearby users if I already know the lat/lng for the city I am interested in, as in the following query:
SELECT ID from Users u
JOIN Zipcodes z1 ON u.zipcode = z1.zipcode
WHERE
COS(SIN(PI()*z1.latitude/180.0)*SIN(PI()*[desired latitude]/180.0)+COS(PI()*z1.latitude/180.0)*COS(PI()*[desired latitude]/180.0)*COS(PI()*[desired longitude]/180.0-PI()*z1.longitude/180.0))*3963.0 <= [desired distance]
However, I want to be able to use City names and State abbreviations to make it easy to enter, then have the query use that lat/lng for the distance comparison.
I guess I could write two queries, the first to get the lat/lng of the desired city, then the second to use the results to find uses within a certain distance of the lat/lng pair returned, but can it be combined into one single query that gets the proper lat/lng for the city match and then uses it in the distance calculation which is in the WHERE clause?
Cannot figure out how to craft it so that the lat/lng can be found for a city and then used in the same query for distance.
Hoping to be able to have one of our employees be able to simply enter e city/state and a desired distance and the code returns all customers that apply. The code would only get the first match for a particular city (there may be many entries in the ZIP table for larger cities), but that is fine for our purposes (and thus we could just use the first match).
Sounds like you might need some geocoding in there, to translate city names into coordinates. Lots of good APIs are available (Google, Algolia, Mapbox etc)
I agree that geocoding will handle a large portion of edge cases not covered by this query but if you are looking for a quick and dirty fix using just the tools you have on hand I believe the following query will work for you.
SELECT ID from Users u
JOIN Zipcodes z1 ON u.zipcode = z1.zipcode
join (select latitude as desired_latitude, longitude as desired_longitude from Zipcodes limit 1 where City = '[user input]' and State = '[user input]' limit 1)
WHERE
COS(SIN(PI()*z1.latitude/180.0)*SIN(PI()*[desired latitude]/180.0)+COS(PI()*z1.latitude/180.0)*COS(PI()*[desired latitude]/180.0)*COS(PI()*[desired longitude]/180.0-PI()*z1.longitude/180.0))*3963.0 <= [desired distance];
Though assuming your User table will have more rows in it than you Zipcodes table you would probably want to refactor that query to be something like this:
SELECT ID from Users u
JOIN (
select z1.zipcode from Zipcodes z1
join (select latitude as desired_latitude, longitude as desired_longitude from Zipcodes limit 1 where City = '[user input]' and State = '[user input]' limit 1)
WHERE COS(SIN(PI()*z1.latitude/180.0)*SIN(PI()*desired_latitude/180.0)+COS(PI()*z1.latitude/180.0)*COS(PI()*desired_latitude/180.0)*COS(PI()*desired_longitude/180.0-PI()*z1.longitude/180.0))*3963.0 <= [desired distance]
) as zipsInRange ON u.zipcode = zipsInRange.zipcode;

SQL Query to find the common data based on two or more condition from the same table?

I have set of country codes and each country has set of accounts holder counts.
I want to fetch the same account numbers along with the country codes among all the countries which are being available in multiple countries.
For example:
Count the number of accounts grouped by country codes:
SELECT [Country Code],COUNT([Accounts]) FROM [table] GROUP BY [Country Code]

MySQL inner join with 3 tables

I've tried various solutions around here but I think I am missing something or that my DB structure is complete wrong. I've got the following 3 tables
Info (id, title, msg, status)
Countries (id, country)
Connect (infoid, countryid, status)
Countries table got the name of the country and a unique id per country.
Connect table is being used to connect the infoid and countryid together with a status and the info table is holding the rest of the information.
I am giving a country, for example UK, and I am trying to get the country id from the Countries table (countries.country = UK), then get all the available results where connect.countryid = countries.id and connect.status = 1 from connect table, and finally show the title and msg from the Info table where info.id = connect.infoid and info.status = 1.
Does this make sense or is my DB structure completely wrong? And can someone please help me with the statement to achieve the above result?
First of all, it is better to change the table name from Countries to Country. Or, you could use Infos and Connects to keep consistence.
You asked about your DB structure design. Firstly we need to know, what is the relationship between Countries and Info? One to one? One to many? Many to one? I guess it is many to many. It means one country might have multiple infos and one info can be shared by multiple countries.
If so, your design is OK and the code you need is shown below:
SELECT
Countries.country,
Info.title,
Info.msg
FROM Countries
INNER JOIN Connect ON Countries.id = Connect.countryid
INNER JOIN Info ON Connect.infoid = Info.id
WHERE
Countries.country = UK
AND Connect.status = 1
AND Info.status = 1;
Moreover, I still have two advices.
Firstly, do not use the column name status because it is the [Keywords and Reserved Words in MySQL 5.7 http://dev.mysql.com/doc/refman/5.7/en/keywords.html].
Secondly, If you want to still display the country without any info, you should use LEFT JOIN instead of INNER JOIN.

Get data from table by County in a single row

I want to get data from table in a single row for single county. Right now as shown in images it shows Different rows for Single county as Kalamazoo. It should show single with both records in single row.
I am using following query
SELECT County, Virus, SumOfPositiveTests
FROM StatewiseData
WHERE State = 'MICHIGAN'
I want the results to be shown as following
County Virus SUMOFPOSITIVETESTS
---------------------------------------------
Kalamazoo H3N2,H3N8 3
Total sum of both H3N2 and H3N8
use MYSQL GROUP_CONCAT
The following MySQL statement will return a list of comma(,) separated 'Virus's for each group of 'County' from the StatewiseData table
SELECT County,GROUP_CONCAT(Virus),sum(SumOfPositiveTests) FROM StatewiseData where State='MICHIGAN' group by County
Try this if you are using mysql:
SELECT country, GROUP_CONCAT(virus) _virus, SUM(SumofPositiveTests) as TotalPostitiveTest
FROM StatewiseData
WHERE Country = 'Kalamzoo'
GROUP BY Country
Please mind that this will not work with most databases, as they need you to to specify only the grouping field and aggregate functions of other fields in your query.
Here is the source
Try this. this would work on IBM DB2 and MySQL. what DB you are using
SELECT DISTINCT Country, Virus,SumOfPositiveTests FROM Customers where State='MICHIGAN' group by Country;
why are you using state in where condition? (please provide list of columns do you have in a column if i missed something)
if you are only selecting the country then it should be as simple as:
SELECT County,Virus,SumOfPositiveTests FROM StatewiseData where Country='Kalamzoo'
if you want to select summary or totals of single country then you you should use sum like:
SELECT country, SUM(SumofPositiveTests) as TotalPostitiveTest
FROM StatewiseData WHERE Country='Kalamzoo' GROUP BY Country

Forming SQL query

In my android app, I am getting a list of nearby restaurants from Google Place API.
But unfortunately, this list does not give menus of the restaurant.
I have T_RESTAURANT and T_MENU tables.
Lets say, I get 4 restaurants in the list returned by API, then how should I make my query to extract data.
If I do:
SELECT name, votes, review FROM T_MENU WHERE restaurant_name = REST_NAME_1;
and I have to fire this query for each of the restaurants i.e. 4 times in this case.
Can anyone suggest me a good solution?
SELECT name,
votes,
review
FROM T_MENU
WHERE restaurant_name
IN ( <four restaurant names comma separated> )
You can use "IN" keyword instead of "=".
A also suggest using restaurant ids instead of names.
try this:
select T.name, T.votes, T.review ,M.<menu_items>
from T_RESTAURANT R join T_MENU M
where R.restaurant_name=T.restaurant_name