Mysql: which pizza prefer client - mysql

I have table with this data :
1. John | seafood pizza
2. Mike | pepperoni pizza
3. Mike | pepperoni pizza
4. John | original pizza
5. Mike | original pizza
6. John | seafood pizza
7. John | pepperoni pizza
....
How can I write a query that give me result such this:
John | seafood pizza
Mike | pepperoni pizza
If client have same quantity for many pizzas, the result may be any pizza's name.

Let's take it step by step
the following query will give you number of times each client ordered each kind of pizza
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
So how do we get the most often ordered pizza from that? We must first know, what is the highest number of pizza ordered by each client
SELECT name, MAX(cnt) AS cnt FROM (
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
) AS subquery GROUP BY name
then use this number to select actual pizza name
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable AS t
CROSS JOIN (
SELECT name, MAX(cnt) AS cnt FROM (
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
) AS subquery GROUP BY name
) AS sq
USING(name,cnt)
GROUP BY name, pizza

I'd go with grouping the counts by user and pizza then using this as a datasource for a query which finds the groupwise maximum (using the max concat trick). It's not hard:
SELECT user, SUBSTRING(MAX(CONCAT(LPAD(freq, 6, '0'),pizza)),7)
FROM
(SELECT user, pizza, COUNT(*) AS freq
FROM user_likes
GROUP BY user, pizza) ilv
GROUP BY user

Let's have a simple solution :
First of all, we have two columns,name and food.
You can list of favorite customer's food easily :
CREATE TEMPORARY TABLE tbltemp AS (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
);
Now we have all of foods by count.
Then you can order it by count descending :
SELECT *
FROM tbltemp
ORDER BY c DESC
Now you have a list that describes your customer's favorite.
UPDATE :
Instead of second query ,replace this one :
SELECT tbl1 . *
FROM (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
) AS tbl1, (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
) AS tbl2
WHERE tbl1.c = tbl2.c
AND tbl2.name = tbl1.name
AND tbl2.food = tbl1.food
AND tbl1.c = (
SELECT c
FROM tbltemp
ORDER BY c DESC
LIMIT 1 )
This query result is your question goal.

Related

mysql: union re-use subquery

There is a table:
ID City
1 Toronto
2 Toronto
3 Toronto
4 Toronto
5 NY
6 NY
How to get the following table:
City Total
NULL 6
Toronto 4
NY 2
I plan to use union:
(select city, count(*) as total from tbl group by city)
union
(select null, count(*) as total from tbl)
Is it possible to use something like to reuse the subquery:
(select city, count(*) as total from tbl group by city) tmp
union
(select null, count(*) as tmp from tbl)
Or sql already optimizes
(select city, count(*) as total from tbl group by city)
union
(select null, count(*) as total from tbl)
?
In at least MySQL 5.5 and newer, you can use the WITH ROLLUP modifier to get a total sum of the grouped elements without an extra query;
SELECT city, COUNT(*) AS total FROM tbl GROUP BY city WITH ROLLUP
city total
---------------
NY 2
Toronto 4
(null) 6
An SQLfiddle to test with.
You can't reuse the the query but you could use a view for reuse the code
create view my_view as
select city, count(*) as total
from tbl group by city
once created the view you could
select city, total
from my_view
union
select null, sum(total)
from my_view
1) Take aliases are only visible to join members and subquery. Not to union members.
2) The query as you wrote it makes little sense: aliasing tmp to a table then a scalar?
To achieve what you want to achieve, you can try using CTEs:
WITH tmp AS (SELECT city, COUNT(*) AS cnt GROUP BY city)
SELECT * FROM tmp UNION SELECT null, SUM(cnt) FROM tmp
I don't know what the performance difference would be. If you have an index on city, I doubt you will see a difference.
You use WITH ROLLUP in a subquery and then arrange the ordering in the outer query to put the rollup record on top:
SELECT *
FROM (SELECT city, COUNT(*) AS total FROM mytable GROUP BY city WITH ROLLUP) x
ORDER BY
CASE WHEN city IS NULL THEN 0 ELSE 1 END,
city
If you are planning to order the results by descending total, that's even simpler:
SELECT *
FROM (SELECT city, COUNT(*) AS total FROM mytable GROUP BY city WITH ROLLUP) x
ORDER BY total DESC
Demo on DB Fiddlde:
| city | total |
| ------- | ----- |
| | 6 |
| Toronto | 4 |
| NY | 2 |

Selecting the top row in each group in mysql

I have a table with two columns - region and profession
region | profession
India | IT
India | IT
US | HR
US | HR
India | HR
I want to display the most popular profession in every region. the output should only be
Region | Profession
India | IT
US | HR
First, get a count of the results per group. Then you need to establish an order per group -- mysql can do this with user-defined variables.
Here's an example:
select region, profession
from (
select region, profession,
#rn:=if(#oldregion=region,#rn+1,0) rn,
#oldregion:=region
from (
select region, profession, count(*) cnt
from yourtable
group by region, profession) t, (select #rn:=0, #oldregion='') t2
order by region, cnt desc) t3
where rn = 0
SQL Fiddle Demo
Here's another solution using a correlated subquery:
select distinct region, (
select profession
from yourtable t2
where t.region = t2.region
group by region, profession
order by count(*) desc
limit 1) as profession
from yourtable t
More Fiddle

Count how many different countries are in the table

I have a table like this:
ID country
-------------
1 US
2 Japan
3 China
4 US
5 China
How can one query the table, so that it returns how many different countries are in the table (i.e 3)?
The following SQL query will result in counting the number of unique countries in your table.
select count(distinct country)
from YourTable
What you need is to select the amount of unique countries. This is done by selecting all country entries, which are then grouped so there is only one country entry per country name.
SELECT count(country) from countrytable group by country;
This is basically the same as Andomars answer.
you can use this
SELECT country, COUNT( id )
FROM [table_name] GROUP BY country
LIMIT 0 , 30
Output :
country count(id)
---------------------
US 2
Japan 1
china 2
SELECT count(distinct country) from countrytable
select count(distinct country)
from table1
SELECT count( DISTINCT country )
FROM table1 c
WHERE c.item_id = (
SELECT main_id
FROM table2
WHERE main_id = c.item_id )
select count(distinct country)
from [TableName]

Use group by in and return identity of the row

For this table...
id type food price
--------------------------
1 veg carrot 10
2 veg turnip 11
3 fruit bramble 6
4 fruit rasp 4
5 fruit current 9
...
I can return the max price of the most expensive food for each food type like this...
select max(price) from tableName group by type;
But I'd like to return the id number of each row that contains the most expensive food for each food type. And return one and only one row per food type. Ie return this....
id
----
2
5
...
This is a simplified version of my real problem.
SELECT id
FROM ( SELECT id, type
FROM table
ORDER BY price DESC) AS h
GROUP BY type
This horrible query will work when more food have the same type and price.
I would hardly ever use this in production as this is unmaintainable.
SELECT MIN(id) AS id
FROM (
SELECT t.id AS id, t.type
FROM tableName t
JOIN (
SELECT MAX(price) AS m, type
FROM tableName
GROUP BY type
) sub
ON sub.m=t.price AND sub.type=t.type
ORDER BY id
) whatever
GROUP BY type
SELECT max(id) from
(SELECT t1.* FROM tableName t1
JOIN (SELECT type, max(price) AS price FROM tableName GROUP BY type) t2
ON t2.type = t1.type AND t2.price = t1.price) t3
GROUP BY userId;

MySQL row number

Say I have a MySQL query, for example:
SELECT id, name, surname FROM employees ORDER BY id
The result woud be:
id name surname
1 Peter Smith
2 John Banjo
...
1384 Will Levenstein
While this is an ordered query, I can always assume (as long as I don't change the table) that John Banjo will come out second.
Now what if my query was
SELECT id, name, surname FROM employees WHERE name = 'John' AND surname = 'Banjo'
Could I somehow get what the row number would be in the first query?
I'm trying to do this in a much more complicated, but always ordered query, is there any way to archieve this?
SELECT x.id, x.name, x.surname, x.rownum
FROM (
SELECT #rownum:=#rownum+1 rownum, t.*
FROM (SELECT #rownum:=0) r, employees t
ORDER BY Id
) x
WHERE x.name = 'John'
AND x.surname = 'Banjo'