Mysql: Union two columns with count - mysql

I'm looking for a sql statement for the following problem:
Here is an excerpt from my table
'from_city' 'to_city'
New York Boston
Chicago New York
New York Los Angeles
Dallas San Francisco
Miami New York
Dallas Los Angeles
The expected result should look like this:
City Count Percentage
New York 4 33%
Los Angeles 2 17%
Dallas 2 17%
San Francisco 1 8%
Miami 1 8%
Chicago 1 8%
Boston 1 8%
So I need to union the two columns 'from_city' and 'to_city' which I was able to with:
(SELECT from_city AS City FROM table) UNION
(SELECT to_city AS City FROM table)
But now I don't know how to appy the count and percentage on the result set.
Can you please help me out?
Thanks in advance!

You may want to use subquery:
SELECT
city,
COUNT(1) AS c,
CONCAT(100*COUNT(1)/sums.total, '%') AS p
FROM
(SELECT from_city AS city FROM t
UNION ALL
SELECT to_city FROM t) AS cities
CROSS JOIN
(SELECT
COUNT(from_city)
+COUNT(to_city) AS total
FROM t) AS sums
GROUP BY
city
ORDER BY
c DESC
-note, that double count won't work in common case (thus used sum of counts by both columns) Check the demo.
Also you've not specified format of percentage - i.e. how many signs should be in it (because it may be non-integer) - so I've left it as it is

SELECT City, COUNT(*) AS Count, ROUND(100*COUNT(*)/total) AS Percentage
FROM (SELECT from_city AS City
FROM table
UNION ALL
SELECT to_city AS City
FROM table
) AS u
CROSS JOIN (SELECT 2 * COUNT(*) AS total
FROM table) AS t
GROUP BY City
ORDER BY Count DESC
DEMO

SELECT
cities.City,
COUNT(*) as `Count`,
CONCAT((COUNT(*) / (SELECT COUNT(*)*2 FROM table)) * 100, '%') as Percentage
FROM (
SELECT from_city AS City FROM table UNION ALL
SELECT to_city AS City FROM table
) as cities
GROUP BY cities.City

I believe the following query will provide your desired results
SELECT
city,
count(*),
count(*)/(SELECT count(*)*2 FROM table)
FROM
(SELECT from_city AS city FROM table
union all
SELECT to_city AS city FROM table) a
GROUP BY
city

Related

MySQL query multiple column group by issue

This is my data set
I want to get the most common used phone and car per city.
So the result expected is
For example: in NewYork there are 2 instances of iPhone out of 3 and 2 instances of Honda car out of 3, so they are the most common used phone and car for NY.
I'm not able to express in query how to execute group by clause on these 3 columns simultaneously.
Any pointers are appreciated, thanks in advance.
I'm sure there's a shorter way but, anyway, you can do:
select x.city, x.phone, y.car
from (
select city, phone, row_number() over(partition by city order by count(*) desc) as rn
from t group by city, phone
) x
join (
select city, car, row_number() over(partition by city order by count(*) desc) as rn
from t group by city, car
) y on x.city = y.city and x.rn = 1 and y.rn = 1
Result:
city phone car
--------- -------- -----
Houston Android Kia
New York iPhone Honda
See running example at db<>fiddle.

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

How to join two select statements in one table?

I'm new to mysql and I have two correctly working select statements with longest and shortest names. I can't really understand how can I join them in one statement. Can someone help, please.
Here are the queries:
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength
FROM country
ORDER BY CHAR_LENGTH(name) DESC, name
LIMIT 1;
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength
FROM country
ORDER BY CHAR_LENGTH(name), name
LIMIT 1;
The result I'm looking for is:
Country NameLength
----------------------------------------------------------
South Georgia and the South Sandwich Islands 44
Chad 4
Cuba 4
You use UNION:
SELECT Country, NameLength FROM (
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength FROM country LIMIT 1;
UNION
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength FROM country LIMIT 1; )a
ORDER BY NameLength DESC, Country

How can I select the first time a number shows up in more than one column in MySQL?

I have a table of flights, which have an origin and destination city, represented as a foreign id.
A very simplified example of this table looks like:
id | origin | destination
023 1 3
044 3 2
332 2 1
509 1 3
493 1 4
I need to get the first time that a city shows up as an origin or a destination; a list of all the flights that contain a city that hasn't been flown to or from yet.
What I would like to get for the above example would be:
023: 1, 3
044: 2
493: 4
Flights 332 and 509 aren't in the output because they only visit cities that have already been visited.
Here's what I've tried:
(SELECT distinct(origin), distinct(destination) FROM flights ORDER BY id)
Doesn't work because you can't select more than one distinct column
SELECT (distinct(origin) FROM flights ORDER BY id) UNION (distinct (destination) FROM flights ORDER BY id)
Doesn't work because of syntax errors, but mainly because it doesn't take into account that a city should be unique in the origin and destination columns.
If there's not a quick way to do this in SQL I'm also happy to just iterate through and keep track of cities that have been visited (this app has literally one user, and he doesn't care about a few milliseconds of computation because he's over 80), but I'd love to know just so that I can learn more about SQL!
This does it:
SELECT id, GROUP_CONCAT(city ORDER BY city) cities
FROM (
SELECT city, min(id) id
FROM (
SELECT origin city, MIN(id) id
FROM flights
GROUP BY city
UNION
SELECT destination city, MIN(id) id
FROM flights
GROUP BY city) u
GROUP BY city) x
GROUP BY id
DEMO

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