Using Distinct, Count and Group together in MySQL - mysql

I have a database table of 'attractions' with columns for both the county and/or city for each attraction. I need to display a list of counties and cities together, alphabetically, with the total number of records for each county or city.
The following SQL query works fine except the COUNT is displaying a total of only one for each instead of the total number of attractions in each county or city.
Could anyone tell me how to combine the two SQL statements below together?
SQL:
SELECT entry, COUNT(entry) AS totalForEntry
FROM ( SELECT DISTINCT county AS entry
FROM venues
WHERE (county IS NOT NULL AND county <> '' )
UNION ALL
SELECT DISTINCT city as entry
FROM venues
WHERE (city IS NOT NULL
AND
city <> ''
)
) X GROUP BY entry ORDER BY entry ASC
Results:
Hove (1)
Inverness-shire (1)
Isle of Man (1)
Kent (1)
Lancashire (1)
Leeds (1)
Leicester (1)
Leicestershire (2)
Lincolnshire (1)
Liverpool (1)
The following works for counting the counties, I need it to count the cities too and combine it with the query above:
SELECT DISTINCT county, COUNT(county) AS Count
FROM venues
WHERE (county IS NOT NULL AND county <> '')
GROUP BY county ORDER BY county ASC
The correct result should be something like:
Hove (7)
Inverness-shire (3)
Isle of Man (12)
Kent (20)
Lancashire (34)
Leeds (31)
Leicester (5)
Leicestershire (53)
Lincolnshire (7)
Liverpool (43)
Many thanks in advance.

It doesn't make sense to use DISTINCT with GROUP BY. You can do:
SELECT county AS entry, COUNT(county) AS Count
FROM venues
WHERE (county IS NOT NULL AND county <> '')
GROUP BY county
UNION ALL
SELECT city as entry, COUNT(city) As Count
FROM venues
WHERE (city IS NOT NULL AND city <> '')
GROUP BY city
ORDER BY entry ASC

Related

GROUP BY multiple row and want to show more than 1 record

I have a store table, and the sql is
SELECT * FROM `store` GROUP BY `store_name`, `country`, `branch`
The output is
store_name
country
branch
store_a
US
New_York
store_a
US
Texas
store_b
Japan
Tokyo
store_c
German
Hamburg
store_c
German
Berlin
store_c
German
Hesse
store_d
French
Paris
Now I want to show stores have more than 1 branches
This is what I expect:
store_name
country
branch
store_a
US
New_York
store_a
US
Texas
store_c
German
Hamburg
store_c
German
Berlin
store_c
German
Hesse
How to achieve this?
Here's a solution using window functions (you must use MySQL 8.0 for this feature):
select store_name, country, branch from (
select store_name, country, branch,
count(*) over (partition by store_name) as count
from store
) as t
where count > 1;
No GROUP BY is needed.
That is what the HAVING clause is for.
Try
SELECT *
FROM `store`
GROUP BY `store_name`, `country`, `branch`
HAVING COUNT(*) > 1
Join with a query that gets the number of branches per country and only returns the ones that have more than one branch.
SELECT a.*
FROM store AS a
JOIN (
SELECT store_name, country
FROM store
GROUP BY store_name, country
HAVING COUNT(*) > 1
) AS b ON a.store_name = b.store_name AND a.country = b.country

mysql various group by in one query

I would like to get statistics on my dataset,
for example this is my dataset:
FirstName LastName Country City BirthMonth
Donald Trump England London Jan
Bill Gates England London Sep
Donald Suther England York Sep
Donald Suther Germany Berlin Jan
and this is my 'group_by' list:
[['FirstName', 'LastName'], ['Country', 'City'], ['BirthMonth']]
I would like to get the following statistics:
group by FirstName & LastName:
FirstName LastName Count
Donald Trump 1
Donald Suther 2
Bill Gates 1
group by Country & City:
Country City Count
England London 2
England York 1
Germany Berlin 1
group by BirthMonth:
BirthMonth Count
Jan 2
Sep 2
my query would look like this:
select FirstName, LastName, Country, City, BirthMonth
from my_table
where <some conditions to filter rows only from certain timestamp>
now I have two options:
a. return all values to server and process there (I'm using python) - this query includes many rows and causes overhead
b. query multiple times, each time grouping by the specific fields
select FirstName, LastName, count(*) as group_by
from my_table
where ...
group by FirstName, LastName
c. is there a third option of having one query, and return all different 'group_by's?
and another question:
from (a) and (b) which is better?
I'll note that the group by has limited options - for example 'FirstName' has only 20 options, this means that (b) will result each time less than 20*(num of group by in query rows) < 40, but (a) will result 20^5 rows which is tons of data
to simplify I'll assume there aren't more than 2 columns in a group_by each time,
(which is actually the current situation, it might grow in the future but currently I can use a solution that takes that into account)
You can combine each grouped query with the others using UNION. Fill in the unused columns in each subquery with NULL.
SELECT FirstName, LastName, NULL AS Country, NULL AS City, NULL AS BirthMonth, COUNT(*) AS count
FROM my_table
GROUP BY FirstName, LastName
UNION ALL
SELECT NULL, NULL, Country, City, NULL, COUNT(*)
FROM my_table
GROUP BY Country, City
UNION ALL
SELECT NULL, NULL, NULL, NULL, BirthMonth, COUNT(*)
FROM my_table
GROUP BY BirthMonth

Retrieve data from 2 fields with a count from one of them

I need to retrieve data from a countries table to use for formatting search results but i don't seem to have the correct sql format.
Each country is stored with country_code, country_name, iso_code and sales_location
So for instance it would have 222, United Kingdom, GB, UK Sales
What i need is to be able to query how many times a sales location is listed and what country names are associated with that sales location (Rest of the World has 221 country names)
I tried
SELECT sales_location, countries_name, COUNT( sales_location )
FROM countries
GROUP BY sales_location
which does give me the locations and counts, but the country name is only giving the first country alphabetically.
SELECT sales_location, GROUP_CONCAT(countries_name), COUNT( * )
FROM countries
GROUP BY sales_location
SELECT countries_name, GROUP_CONCAT(sales_location) as sales_location,
COUNT(sales_location ) as location_count
FROM countries
GROUP BY countries_name
SELECT sales_location, GROUP_CONCAT(countries_name), COUNT(sales_location)
FROM countries
GROUP BY sales_location
This query should help.

Limit number of records that are counted in sql

In my database I can easily see the last 50 people in my table with state=NY and postcode=12405 and I can look down the table to see if they have a dog.
SELECT state, postcode, havedog
FROM address
WHERE (state=NY) AND (postcode=12405)
ORDER BY surname DESC
LIMIT 0 , 5
Which returns
state postcode havedog
NY 12405 yes
NY 12405 yes
NY 12405 no
NY 12405 no
NY 12405 yes
I can also count how many people there are in my whole database that have a dog where state=NY and postcode=12405
SELECT state, postcode COUNT(havedog) AS DOG
FROM address
WHERE (state=NY AND postcode=12405 ) AND (havedog=yes)
But I can't work out how to limit the count so it only counts the last 5 records where state=NY and postcode=12405 and havedog=yes, is it possible to apply a limit to the Count function?
eg given the table above, the result of my count should be 3.
Use a subselect:
SELECT COUNT(*) FROM
(
SELECT state, postcode, havedog
FROM address
WHERE state = 'NY' AND postcode = 12405
ORDER BY surname DESC
LIMIT 5
) T1
WHERE havedog = 1
You can do this:
SELECT
state,
postcode
COUNT(havedog) AS DogCounts
FROM
(
SELECT state, postcode, havedog
FROM address
WHERE (state=NY) AND (postcode=12405)
ORDER BY surname DESC
LIMIT 50
) t
GROUP BY state, postcode
SELECT top 50 state, postcode, COUNT(havedog) OVER () AS DOG
FROM address
WHERE (state='NY' AND postcode=12405 ) AND (havedog='yes')

Order by COUNT per value

I have a table which stores IDs and the city where the store is located.
I want to list all the stores starting with the stores that are in the city where there are the most stores.
TABLE
ID CITY
1 NYC
2 BOS
3 BOS
4 NYC
5 NYC
The output I want is the following since I have the most stores in NYC, I want all the NYC location to be listed first.
1 NYC
4 NYC
5 NYC
2 BOS
3 BOS
SELECT count(City), City
FROM table
GROUP BY City
ORDER BY count(City);
OR
SELECT count(City) as count, City
FROM table
GROUP BY City
ORDER BY count;
Ahh, sorry, I was misinterpreting your question. I believe Peter Langs answer was the correct one.
This one calculates the count in a separate query, joins it and orders by that count (SQL-Fiddle):
SELECT c.id, c.city
FROM cities c
JOIN ( SELECT city, COUNT(*) AS cnt
FROM cities
GROUP BY city
) c2 ON ( c2.city = c.city )
ORDER BY c2.cnt DESC;
This solution is not a very optimal one so if your table is very large it will take some time to execute but it does what you are asking.
select c.city, c.id,
(select count(*) as cnt from city c2
where c2.city = c.city) as order_col
from city c
order by order_col desc
That is, for each city that you come across you are counting the number of times that that city occurs in the database.
Disclaimer: This gives what you are asking for but I would not recommend it for production environments where the number of rows will grow too large.
SELECT `FirstAddressLine4`, count(*) AS `Count`
FROM `leads`
WHERE `Status`='Yes'
AND `broker_id`='0'
GROUPBY `FirstAddressLine4`
ORDERBY `Count` DESC
LIMIT 0, 8