How I use mysql count with select query? - mysql

I have a mysql select query like this:
select r.restaurant_id, r.restaurant_name, r.city_id, c.name
from restaurants r
inner join cities c on c.id = r.city_id;
This is the result of above query:
+---------------+----------------------+---------+-------------+
| restaurant_id | restaurant_name | city_id | name |
+---------------+----------------------+---------+-------------+
| 7 | Somasiri Bake House | 5 | Mumbai |
| 8 | Indian Bake House | 7 | Chennai |
| 9 | KFC Rest | 5 | Mumbai |
| 10 | Indian t | 5 | Mumbai |
+---------------+----------------------+---------+-------------+
Now I want to display all the available cities with the number of restaurants existing to one city.
Eg: Mumbai (3), Chennai(1) and so on
I tried it like below with mysql COUN(), but it doesn't work for me.
SELECT c.name, count(r.city_id) AS count
FROM cities c
INNER JOIN restaurants r ON c.id = r.city_id;
Can anybody tell me what is the wrong with this?
Hope somebody may help me out.
Thank you.

SELECT c.name, COALESCE(count(r.city_id), 0) AS count
FROM cities c
LEFT JOIN restaurants r ON c.id = r.city_id
GROUP BY c.id

Use a simple group by if you don't want restaurant data:
select c.name, count(r.city_id) as available
from cities c
left join restaurants r on c.id = r.city_id
group by r.city_id
See SQLFiddle.
Or, if you want restaurant data too, select from cities first, then left join to other tables so cities without restaurants still get returned. Add a left join to a subquery that calculates each city's frequency:
select
r.restaurant_id,
r.restaurant_name,
c.id,
c.name,
coalesce(available, 0) available
from cities c
left join restaurants r on c.id = r.city_id
left join (select city_id, count(*) available from restaurants group by 1) a
on a.city_id = r.city_id
See SQLFiddle.

That's called a grouping or aggregate query, you need to tell it how to group your elements.
Just add
GROUP BY r.restaurant_id, r.restaurant_name, r.city_id, c.name
at the end, before your final semi-colon.

Related

How to count a join in MySQL

I have 2 tables,
Cities
Id | city_name
Wanteds
Id | city_id | user_id
I want to create a table using a MySQL query that looks like the following -
City Name | Number of Wanteds
Leeds | 3
Manchester| 1
Halifax | 0
Bradford | 0
etc
where the Number of wanteds pull from the Wanteds table the total number of city_id's.
I have tried
select c.city_name, count(w.city_id) from cities c inner join wanteds w on c.id = w.city_id
but it only returns the total count for the first city.
You need to add group by clause
select c.city_name, count(w.city_id)
from cities c inner join wanteds w on c.id = w.city_id
group by c.city_name

Mysql left join style sum()

I believe the answer is already there at stackoverflow but I cannot find the right keywords. So please help.
Table sales looks like this:
state | sales-representative | product | sales
NY | Mike B. | prod-A | 90
FL | David J. | prod-B | 120
FL | Mike B. | prod-A | 15
I need to get the total sales by such sales representative. Expected results for Mike B. look at this:
state | product | sales
NY | prod-A | 90
FL | prod-A | 15
NY | prod-B | 0 <--How can I get this record as well?
FL | prod-B | 0
A regular sum query returns the first 2 records. How can I get the last 2 records as well?
select state, product, sum(sales)
from sales
where sales-representative = 'Mike B.'
group by state, product
SELECT ss.state, sp.product, SUM(sr.sales)
FROM (SELECT DISTINCT state FROM sales) AS ss
CROSS JOIN (SELECT DISTINCT product FROM sales) AS sp
LEFT JOIN sales AS r
AS sr ON ss.state = s.state
AND sp.product = s.product
AND r.`sales-representative` = 'Mike B.'
GROUP BY ss.state, sp.product;
The cross join gets you every combination of state and product, and the left join gets you the specified representative's associated sales.
You can use a left join on subquery for stated and product
select t.state, t.product, sum(sales)
from table1
left join (
select t1.state, t2.product
from t1
cross join (
select product
from t1
) t2
) t on t.state = table1.state and t.product = table1.product
grooup by t.state, t.product

sql query combine two queries into one with empty rows

This is my sql table structure:
Table1: details
|--id--|--id_user--|--price--|
| 1 | 1 | 10 |
| 2 | 2 | 15 |
| 3 | 1 | 25 |
| 4 | 3 | 30 |
| 5 | 3 | 7 |
------------------------------
Table2: users
|--id--|--id_country--|
| 1 | 1 |
| 2 | 2 |
| 3 | 0 |
-----------------------
Table3: country
|--id--|--country--|
| 1 | France |
| 2 | Italy |
--------------------
What I need is to get the SUM of price by country:
SELECT c.country, SUM(d.price) AS price
FROM details d
INNER JOIN users u ON u.id = d.id_user
INNER JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
I get this:
|--country--|--price--|
| France | 35 |
| Italy | 15 |
-----------------------
BUT I'd need to get this:
|--country--|--price--|
| France | 35 |
| Italy | 15 |
| Undefined | 37 |
-----------------------
where undefined would be if id_country=0. (I can't add to country table the id=0 or id=undefined, it will messed up other things). Right now I'm achieving this by two separate queries, the second one is:
SELECT SUM(d.price) as price
FROM details d
INNER JOIN users u ON u.id = d.id_user AND u.id_country=0
GROUP BY u.id_country
I'm thinking if... is it possible to do this in one query?
You need to use left join in this case:
SELECT c.country, SUM(d.price) AS price
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
If you use INNER JOIN, you will only get results that exists in both tables.
To replace NULL with Undefined use:
SELECT IFNULL(c.country,'Undefined') AS Country, SUM(d.price) AS price
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
One way to sort to get Undefined last is to add a Sortfield
SELECT A.Country,A.Price FROM (
SELECT IFNULL(c.country,'Undefined') AS Country, SUM(d.price) AS price, IFNULL(c.Country,'ZZZZZZZZ') AS Sort
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
) A
ORDER BY A.Sort
Edit: ORDER BY suggested in comments
SELECT IFNULL(c.country,'Undefined') AS Country, SUM(d.price) AS price
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country IS NULL, c.country
Try below query.
SELECT
CASE
WHEN c.country is NULL THEN 'Undefined'
ELSE c.country
END as country
, SUM(d.price) AS price
FROM users u
left JOIN details d ON u.id = d.id_user
left JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
For Demo :
SqlfiddlE Demo :
Please let us know if you have any que.

SQL - Join 3 tables little confusing

I need a help about a little confusing sql query. I have 3 tables. Names : article, category and category_article table.
In my article table, there are 4 columns which are :
aid -> article id
py -> Year of article
totalPoint -> point of Article
tc -> number of cited of article
In category table, there are 2 columns which are :
cid -> category id
category -> name of category
Lastly, in my category_article table, there are 2 columns which are :
cid -> category id
aid -> article id related with category
In the below, there are sample table inputs.
Article Table
______________________________
| aid | py | totalPoint | tc |
-------------------------------
| 1 | 2014| 30 | 3 |
-------------------------------
| 2 | 2013| 20 | 2 |
-------------------------------
| 3 | 2014| 50 | 10 |
_______________________________
Category Table
__________________
| cid | category |
-------------------
| 1 | Surgery |
-------------------
| 2 | Enginering|
____________________
Category_Article Table
__________________
| cid | aid |
-------------------
| 1 | 3 |
-------------------
| 2 | 5 |
____________________
My purpose is find this output with only one sql query.
Category name, year, totalArticleNumber, totalPoint(desc), id of article(the most cited article at that year and at that category), citedTime (Top 20)
The example output is :
_______________________________________________________________________________________
Category name | year | totalArticleNumber | totalPoint | id of article(best) | citedTime |
________________________________________________________________________________________
Surgery | 2013 | 182 | 5234 | 312 | 22 |
_________________________________________________________________________________________
Engineering | 2014 | 189 | 5000 | 10 | 32 |
I can do this table with java programing language. Like first do some query and after that do it second query.
But i need to do it in one query.
I try to use JOIN , HAVING , GROUP BY , DISTINCT and anaother some sql stuff but i cannot succeed.
Any help is appreciated.
EDIT
For example if there are two article with same time cited value, they are shown together.
Like in first two column, the article 419 and 385 same time cited value so they both in table.
There are two options for me.
First way -> Show only one article and limit 20. So in this way i can see 20 different category-year combination.
Second way -> Show the same value timecited articles but i have to see 20 different category-year combination.
This is a little tricky, because you're trying to do a lot of different things here. I would simply break them down and put them back together. First, if you want to JOIN all the tables together, you can use the following syntax:
SELECT *
FROM article a
JOIN category_article ca ON ca.aid = a.aid
JOIN category c ON c.cid = ca.cid;
Now, this will only show articles that are assigned to a category. In other words, if an article doesn't exist in the category_article table, or a category doesn't exist in the category_article table, it won't appear here.
If you want to get the total number of articles for a category per year, you can use the COUNT(*) aggregate function, and the SUM() function to get the total points for that category, and then group by category and year to get the amounts for that group:
SELECT c.category, a.py, COUNT(*) AS numArticles, SUM(totalPoint) AS totalPoints
FROM article a
JOIN category_article ca ON ca.aid = a.aid
JOIN category c ON c.cid = ca.cid
GROUP BY c.cid, a.py;
Next, getting the best article will have to be done using a subquery. I recommend focusing just on that subquery for a moment. You can write one query to get the MAX tc for each category and year, and then join that with your table to get all the matching conditions, like this:
SELECT c.category, a.*
FROM category c
JOIN category_article ca ON c.cid = ca.cid
JOIN article a ON a.aid = ca.aid
JOIN(
SELECT c.cid, a.py, MAX(a.tc) AS maxCited
FROM category c
JOIN category_article ca ON ca.cid = c.cid
JOIN article a ON a.aid = ca.aid
GROUP BY c.cid, a.py) temp ON temp.cid = c.cid AND temp.py = a.py AND temp.maxCited = a.tc;
Once you have that, you can JOIN that subquery with the query above to show the best article information alongside the other group information.
SELECT temp1.category, temp1.py, temp1.numArticles, temp1.totalPoints, temp2.aid AS bestArticle, temp2.tc AS citedTime
FROM(
SELECT c.category, a.py, COUNT(*) AS numArticles, SUM(totalPoint) AS totalPoints
FROM article a
JOIN category_article ca ON ca.aid = a.aid
JOIN category c ON c.cid = ca.cid
GROUP BY c.cid, a.py) temp1
JOIN(
SELECT c.category, a.*
FROM category c
JOIN category_article ca ON c.cid = ca.cid
JOIN article a ON a.aid = ca.aid
JOIN(
SELECT c.cid, a.py, MAX(a.tc) AS maxCited
FROM category c
JOIN category_article ca ON ca.cid = c.cid
JOIN article a ON a.aid = ca.aid
GROUP BY c.cid, a.py) temp ON temp.cid = c.cid AND temp.py = a.py AND temp.maxCited = a.tc) temp2
ON temp1.category = temp2.category AND temp1.py = temp2.py;
Here is an SQL Fiddle example. I am going to play around with how to use fewer JOINS, but for right now it should give you what you want and since your tables are indexed it shouldn't run too slowly.

How to combine MySQL number of rows of the joined table, including 0?

I have two tables: 'company' and 'order'. The first one contains company info and the second one holds all orders made with a company. (order.company = company.ID).
I am making a query on the first table, for example all companies in the city of New York. I would like to make a join with the order table, so that it immediately shows how many orders for a company was made. I could do this with a simple JOIN query, however, it does not include 0. For example, if a company has no orders yet, it will not show up at all, while it should be in the list with 0 orders.
Desired end result:
----------------------------------------
| ID | Name | ... | Orders |
----------------------------------------
| 105 | Company A | ... | 14 |
| 115 | Company B | ... | 5 |
| 120 | Company C | ... | 0 |
| 121 | Company D | ... | 0 |
----------------------------------------
Thanks in advance!
This is a left join with aggregation:
SELECT c.ID, c.Name, count(o.company) as total
FROM companies c left outer join
orders o
on c.id = o.company
WHERE c.city = 'New York'
GROUP BY c.ID;
In MySQL, it is best to avoid subqueries in the from clause -- where possible -- because the derived table is actually created.
The COUNT() expression is counting the number of matches by counting the number of non-null values in the id field used for the join.
Try this
SELECT com.id,com.name,od.orders FROM compnay AS com
LEFT JOIN orders AS od ON od.company = com.id;
SELECT companies.ID,companies.Name ,orders.total FROM
(SELECT ID,Name FROM company where county ='NEW YORK') companies
LEFT JOIN (SELECT company,COUNT(*) as total FROM order GROUP BY company) orders
ON orders.company = companies.ID