Help forming a SQL statement - sql

I have two tables: attractions and cities. Attractions contains a column called city, which is a reference to the id in the cities table. I want to form a MySQL statement that will show me which cities have the most attractions.
I know I can do:
SELECT COUNT(*) as `number`
FROM `attractions`
WHERE `city` = XX
...to get a count of how many attractions are in one city, but is there one statement that can count all of the attractions in every city, and return the results in descending order by number of attractions?

SELECT City.Name, COUNT(Attractions.City) as AttractionCount
FROM City
LEFT OUTER JOIN Attractions ON City.City = Attractions.City
GROUP BY City.Name
ORDER BY COUNT(Attractions.City) DESC

Related

Selecting cities that have 10 or more students and instructors combined in SQL

I need to show the city, state, number of student residents, number of instructor residents, and total student/instructor residents in that city. The information is contained in 3 tables: ZIPCODE, STUDENT, and INSTRUCTOR.
The ZIPCODE table has the columns ZIP, CITY, and STATE.
The STUDENT table has STUDENT_ID and ZIP.
The INSTRUCTOR table has INSTRUCTOR_ID and ZIP.
I've tried a couple of inner joins, and intersects, but I keep getting a wide variety of errors. I'm still very new with SQL, and am not sure how to actually make this work, any help or advice would be greatly appreciated.
You probably want a mix of union and join for this. I doubt you want intersect. Plenty of ways to do this, here's one
SELECT
Z.city,
Z.state,
SUM(case when d.typ = 's' then 1 ELSE 0 END) as count_students,
SUM(case when d.typ = 'i' then 1 ELSE 0 END) as count_instructors,
Count(*) as count_all
FROM
(SELECT * FROM
(SELECT 's' as typ, zip FROM student)
UNION ALL
(SELECT 'I ' as typ, zip FROM Instructor)
) d
INNER JOIN
zipcode z
ON d.zip on z.zip
GROUP BY
z.city, z.state
I pull all the records out of each student and instructor table and union them to make one big list, make a column to keep track of the type, the sum does the counting, when the type is s, the case when returns a 1. The sum will sum the 1s up as a count. You thus end up with a city/state/typ combination for each row and when grouped on city and state and summed on the typ, it gives a count
Here's another way to do this:
SELECT
Z.city,
Z.state,
SUM(s.ct) as count_students,
SUM(i.ct) as count_instructors,
SUM(s.ct) + SUM(I.ct) as count_all
FROM
zipcode z
LEFT OUTER JOIN
(SELECT zip, count(*) ct FROM student GROUP BY zip) s
ON s.zip = z.zip
LEFT OUTER JOIN
(SELECT zip, count(*) as ct FROM Instructor GROUP BY zip) i
ON i.zip = z.zip
GROUP BY z.city, z.state
We group and count the students and the instructors in their own subqueries producing just a single count per zip and join these (left join) to all the zip codes. We group in a sub query to ensure that there is only ever a 1:1 relationship between zipcode and s/i. If it were 1:many the sums would beome distorted. Because multiple zips can refer to one city there is another round of grouping and summing to aggregate all the zips from one city

sql query to select matching rows for all or nothing criteria

I have a table of cars where each car belongs to a company. In another table I have a list of company locations by city.
I want to select all cars from the cars table whose company has locations on all cities passed into the stored procedure, otherwise exclude those cars all together even if it falls short of one city.
So, I've tried something like:
select id, cartype from cars where companyid in
(
select id from locations where cityid in
(
select id from cities
)
)
This doesn't work as it obviously satisfies the condition if ANY of the cities are in the list, not all of them.
It sounds like a group by count, but can't make it work with what I tried.
I"m using MS SQL 2005
One example:
select id, cartype from cars c
where ( select count(1) from cities where id in (...))
= ( select count(distinct cityid)
from locations
where c.companyid = locations.id and cityid in (...) )
Maybe try counting all the cities, and then select the car if the company has the same number of distinct location cities are there are total cities.
SELECT id, cartype FROM cars
WHERE
--Subquery to find the number of locations belonging to car's company
(SELECT count(distinct cities.id) FROM cities
INNER JOIN locations on locations.cityid = cities.id
WHERE locations.companyId = cars.companyId)
=
--Subquery to find the total number of locations
(SELECT count(distinct cities.id) FROM cities)
I haven't tested this, and it may not be the most efficient query, but I think this might work.
Try this
SELECT e.*
FROM cars e
WHERE NOT EXISTS (
SELECT 1
FROM Cities p
WHERE p.location = e.Location
)

Sql query for extracting info from one table based on other

I have two tables
Country with countryid and countryname
City with cityid and cityname
I want to extract city names based on the countryid I select.
I'm very new to sql database and please help me with direct query if you can.
Thank you very much.
According to the table structure which you showed, this query is not possible. You need to add a 'country_id' to the cities table so that you know in which country is each city. Once this has been done, your query would be
select cities.cityname, countries.countryname
from cities inner join countries on countries.country_id = cities.country_id
order by countries.countryname, cities.cityname
First you should have countryid in city table as a country can have many cities. Then you can write.
select A.cityname from city A
where
A.countryid in (select B.countryid from country B)
Please check this link if you want to find out more.
SQL: Select from one table matching criteria in another?
You have to add a countryid in City table and write the following query
select * from city c left outer join country co on c.countryid=co.countryid;
You need to have the countryid in the city table.
SELECT cityid, cityname FROM city WHERE countryid = $CounrtyID

How to get count from mapping table group be another table in PostgreSQL?

I have three tables:
store
=====
name
address
city
state
country
tag ...,
post
=======
title
summary
tags ...
store_post_map
================
(mapping on store and post based on tag).
Now I want to get count of posts from mapping table group by city, state, country or store.id, what to be the SQL in PostgreSQL?
Basically, it's this:
SELECT store_id, count(*) AS posts_ct
FROM store_post_map
GROUP BY store_id;
How can we get counts for each city, state or country where each area
can have multiple stores?
Count per country:
SELECT s.country, count(*) AS posts_ct
FROM store s
JOIN store_post_map sp ON sp.store_id = s.id
GROUP BY 1; -- positional parameter - is the same as GROUP BY s.country here
For the count per city you may have to GROUP BY area and country in addition since a city name is hardly unique. Like:
SELECT s.city, s.area, s.country, count(*) AS posts_ct
FROM store s
JOIN store_post_map sp ON sp.store_id = s.id
GROUP BY 1, 2, 3;

SQL Query Not Working, Returning Nothing Back

The goal of my query is to return the country, capital, and number of languages spoken. It also needs to be ordered by descending number of languages spoken, and then by capital. Finally, the number of languages must be at least 5 and 10 or less.
Here is my query:
SELECT country.name AS Country,
city.name AS Capital,
Count(countrylanguage.language) AS NumLanguages
FROM country,
city,
countrylanguage
WHERE city.id = country.capital
GROUP BY city.name,
country.name
HAVING ( Count(countrylanguage.language) BETWEEN 5 AND 10 );
It returns nothing. The where clause is necessary in order to get the city name to display. In the country table is just an id number, and then the city table holds the id number and name.
If anyone could spot my error I"d be very grateful!
You are missing the relationship with countrylanguage. Without it, you have a cartesian product, so Count(countrylanguage.language) is equal the number of records in countrylanguage, which is most likely to be greater then 10.
Here's a proposed solution (adjust with field names/DB structure accordingly):
SELECT country.name AS Country,
city.name AS Capital,
Count(countrylanguage.language) AS NumLanguages
FROM country,
city,
countrylanguage
WHERE city.id = country.capital
AND countrylanguage.language_id = country.language_id
GROUP BY city.name,
country.name
HAVING ( Count(countrylanguage.language) BETWEEN 5 AND 10 )
ORDER BY NumLanguages desc, city.Name
That said, you should always try to avoid joins in the WHERE clause of the query (implicit joins). Favoring explicit (declarative) joins will give you more readability and also more flexibility.
Update
As per comments suggestion, here is the query's version using ANSI-92 join syntax:
SELECT country.name AS Country,
city.name AS Capital,
Count(countrylanguage.language) AS NumLanguages
FROM country
INNER JOIN city on city.id = country.capital
INNER JOIN countrylanguage on countrylanguage.language_id = country.language_id
GROUP BY city.name,
country.name
HAVING ( Count(countrylanguage.language) BETWEEN 5 AND 10 );
ORDER BY NumLanguages desc, city.Name