mysql query to get count from a table - mysql

I have 3 tables like this:
Areas
id city_id area
1 1 mayfield
2 2 cleveland
neighbourhood
id neighbourhood area_id
101 cayahoga 1
102 milan 1
103 downtown 2
Salons
id neighbourhood_id
3 101
4 101
5 102
I am trying to get count of all Salons in all areas.
Like salons in areas (mayfield = 2, cleveland = 1)
Is it possible to do this in 1 query?

SELECT areas.area,COUNT(Salons.id)
FROM areas
LEFT JOIN neighbourhood ON neighbourhood.area_id = areas.id
LEFT JOIN Salons ON Salons.neighbourhood_id = neighbourhood.id
GROUP BY areas.id

select area,count(s.id) as salon_count FROM
Areas a
INNER JOIN neighbourhood n
ON a.id = n.area_id
INNER JOIN
Salons s on s.neigbourhood_id = n.id
GROUP BY area

Related

SQL: how to get membership based on ALL from a given cohort

I have the following tables in a MySQL database:
team
team_id name
3 Rangers
12 Capitals
19 Red Wings
4 Bruins
212 Avalanche
102 Flyers
20 Islanders
50 Sabres
7 Stars
player
id name
2 Zach
1 Deb
17 William
9 Viktor
12 Andrew
41 Chris
22 Bobby
5 Phil
3 Roy
92 Li
6 Juan
players_in
team_id player_id points
3 2 42
212 2 19
3 12 18
19 12 2
3 41 2
4 41 1
212 41 78
212 17 1
19 41 4
12 41 2
3 17 6
4 1 9
102 1 40
102 22 7
20 22 19
20 5 22
50 3 20
12 92 15
12 17 8
7 6 12
Here is a SQL Fiddle with the data: http://www.sqlfiddle.com/#!9/989ebe/1
I would like to get the name and id of the players who have played on ALL of the teams that Zach has played on.
In this case, Zach has played for the Rangers and the Avalanche.
Therefore, the desired result set would be:
name id
William 17
Chris 41
(because these players were part of both the Rangers and the Avalanche teams)
How would I do this?
Thanks!
select distinct p.*
from player p
join players_in pi on pi.player_id = p.id
join player p2 on p2.name = 'Zach'
join players_in pi2 on pi2.team_id = pi.team_id
and pi2.player_id = p2.id
where
p.name <> 'Zach'
and not exists (select 1 from players_in pi3
where pi3.player_id = p2.id
and pi3.team_id not in (select team_id
from players_in pi4
where pi4.player_id = p.id));
First of all I've joined players_in (pi) with players (p) obtaining the set of all players and theirs teams.
Second, cross joined player zack joined with player_in (pi2) obtaining the set of Zach's teams. Joined pi2 with pi I've obtained the set of all player that had played in a Zach's team.
Now the where conditions:
p.name <> 'Zach' will exclude Zach from my list.
The not exists condition is the hard part of the query.
I've selected all Zach teams again (pi3) not in the set of the player's (p) team,
SQL Fiddle here
Your requirement could be translated to: searching for players which there's not exists any Jack's team that they don't play in. Corresponding query could be:
SELECT
DISTINCT p1.name, p1.id
FROM
player p1
INNER JOIN players_in pin1 ON p1.id = pin1.player_id
WHERE
name != 'Zach'
AND NOT EXISTS (
SELECT 1
FROM
team t
INNER JOIN players_in pin2 ON t.team_id = pin2.team_id
INNER JOIN player p2 ON p2.id = pin2.player_id
WHERE
p2.name = 'Zach'
AND NOT EXISTS (SELECT 1
FROM players_in pin3
WHERE pin2.team_id = pin3.team_id
AND pin1.player_id = pin3.player_id)
);
Demo: http://www.sqlfiddle.com/#!9/989ebe/61
Using a cte for Zach's games and then checking all potential memberships based on team_id existence in the cte's values:
with cte as (
select pi1.team_id from players_in pi1 join player p2 on p2.id = pi1.player_id
where p2.name = 'Zach'
)
select p.* from player p where (select count(*) from cte c) = (select
sum(pi1.team_id in (select c.team_id from cte c))
from players_in pi1 where pi1.player_id = p.id) and p.name != 'Zach'
See fiddle.

mysql query not working as expected complex

I have 3 tables in which all 3 tables are joined to get the result.
Below is the table,
//tbl_order
order_id order_no_first order_no order_no_last order_date
---------------------------------------------------------------------
1 C 1000 a 2017-05-16
2 C 1001 a 2017-05-16
3 C 1001 b 2017-05-16
4 A 1002 a 2017-05-16
5 A 1002 b 2017-05-16
//tbl_assign
assign_id order_id order_no_first central_status central_assign_unit
----------------------------------------------------------------------------
1 1 C 1 1
2 2 C 1 1
3 3 C 1 1
4 4 A 1 1
//tbl_unit_status
status_id assign_id status_status
---------------------------------------
1 1 Cutter
2 1 Stitch
3 1 Delivery
4 2 Cutter
5 2 Stitch
6 3 Cutter
7 4 Cutter
I want the result as below,
//Required output
order_id assign_id order_no_first order_no order_no_last status_status
---------------------------------------------------------------------------
2 2 C 1001 a Stitch
3 3 C 1001 b Cutter
4 4 A 1002 a Cutter
5 A 1002 b
from the table tbl_unit_status the status below status_status field, if it is Despatch then do not display that result.
I have tried to get the above result. But no success below is my code.
`SELECT *
FROM tbl_order o
LEFT JOIN tbl_assign a
ON a.order_id = o.order_id AND o.order_no_first = a.order_no_first
LEFT JOIN (
SELECT u.assign_id, max(u.status_id) AS maxid
FROM tbl_unit_status u GROUP BY u.assign_id) uu
ON uu.assign_id = a.assign_id
LEFT JOIN tbl_unit_status u2 on u2.status_id = uu.maxid
WHERE a.central_status = 1 AND a.central_assign_unit = 1
OR (u2.status_status != "Delivery" AND u2.status_status != "Despatch")
GROUP BY o.order_id
From the above code, the result is
//wrong output
order_id assign_id order_no_first order_no order_no_last status_status
---------------------------------------------------------------------------
1 1 C 1000 a Delivery
2 2 C 1001 a Stitch
3 3 C 1001 b Cutter
4 4 A 1002 a Cutter
5 A 1002 b
Is there any way to get the Required output as soon in the first output. I have tried and am stuck in here.
Thank you.
Use parenthesis correctly arround AND OR clauses and I recommend using NOT LIKE instead of != when dealing with strings.
SELECT *
FROM tbl_order o
LEFT JOIN tbl_assign a
ON a.order_id = o.order_id AND o.order_no_first = a.order_no_first
LEFT JOIN (
SELECT u.assign_id, max(u.status_id) AS maxid
FROM tbl_unit_status u GROUP BY u.assign_id) uu
ON uu.assign_id = a.assign_id
LEFT JOIN tbl_unit_status u2 on u2.status_id = uu.maxid
WHERE a.central_status = 1 AND (a.central_assign_unit = 1 OR u2.status_status NOT LIKE 'Delivery' AND u2.status_status NOT LIKE 'Despatch')
GROUP BY o.order_id
Obs: I can't comment due to my reputation, I'm sorry
You should be using AND instead of OR in your where clause. You don't need the parentheses either.
SELECT *
FROM tbl_order o
LEFT JOIN tbl_assign a
ON a.order_id = o.order_id
AND o.order_no_first = a.order_no_first
LEFT JOIN
(SELECT u.assign_id, max(u.status_id) AS maxid
FROM tbl_unit_status u
GROUP BY u.assign_id
) uu ON uu.assign_id = a.assign_id
LEFT JOIN tbl_unit_status u2
on u2.status_id = uu.maxid
WHERE a.central_status = 1
AND a.central_assign_unit = 1
AND (
u2.status_status IS NULL
OR
u2.status_status NOT IN ("Delivery", "Despatch")
)
GROUP BY o.order_id

How to select counts from different tables with foreign keys?

city
----------------------
id city_name
1 Pune
2 Mumbai
3 Banglore
Branches
----------------------
id branch_name city_id
1 Magarpatta 1
2 Wagholi 1
3 Kurla 2
4 CST 2
5 Thane 2
6 Anekal 3
Employees
----------------------
id employee_name city_id
1 Arun 1
2 Varun 1
3 Mahesh 2
4 Umesh 2
5 Prakash 1
6 Kedar 3
Expected result
-----------------------------
id(city) city_name No_of_Branch no_of_employee
1 Pune 2 3
2 Mumbai 3 2
3 Banglore 1 1
Can I get above result in single Query?
Can I Use Crosstab in this scenario? How?
SELECT c.*, count(DISTINCT b.id) AS No_of_Branch, count(DISTINCT e.id) AS no_of_employee
FROM city c
LEFT JOIN branches b ON (b.city_id=c.id)
LEFT JOIN employees e ON (e.city_id=c.id)
GROUP BY c.id
Or
SELECT c.*,
(SELECT count(b.id) FROM branches b WHERE b.city_id=c.id) AS No_of_Branch,
(SELECT count(e.id) FROM employees e WHERE e.city_id=c.id) AS no_of_employee
FROM city c
Try this:
SELECT c.id, c.city_name,
COUNT(b.id) AS No_of_Branch,
no_of_employee
FROM city c
LEFT JOIN branches b ON b.city_id = c.id
LEFT JOIN (
SELECT city_id, COUNT(e.id) AS no_of_employee
FROM employees AS e
GROUP BY e.city_id
) AS e_grp ON e_grp.city_id = c.id
GROUP BY c.id, c.city_name
The trick here is to use a derived table containing the count of employees per city_id. I you just join all tables together you will end up with duplicate counts of employees.
Demo here

mysql complicated inner join on many to many

I have 7 tables db_category, db_city, db_locality, db_shop, db_shop_locality, db_shop_recommended, db_shop_views.
db_category
category_id category_name publish
1 Apparel 1
db_city
city_id city_name publish
1 bangalore 1
db_locality
locality_id locality_name publish
1 kalyan nagar 1
2 Madiwala 1
db_shop
shop_id category_id city_id locality_id shop_name publish
1 1 1 1 name 1
2 1 1 2 name1 1
3 1 1 1 name2 1
4 1 1 1 name3 1
db_shop_recommended
recommended_id category_id shop_id priority publish
1 1 1 1 1
2 1 2 2 1
db_shop_views
views_id shop_id ip_addr publish
1 1 127.0.0.1 1
2 2 ::1 1
3 4 127.0.0.1 1
4 4 ::1 1
5 3 ::1 1
I want to join all the above tables. And the conditions for the join are,
display all the rows from db_shop when publish=1 and join db_category, db_city and db_locality with db_shop
in db_shop_recommended who's priority=1 comes first and so on.
and shop_id not in db_shop_recommended, count shop_id not in db_shop_recommended from db_shop_views who's shop_id got more views.
My result should looks like below,
shop_id category_name city_name locality_name shop_name
1 Apparel bangalore kalyan nagar name (result based on `db_shop_recommended` who's priority is more)
2 Apparel bangalore Madiwala name1 (result based on `db_shop_recommended` who's priority is more)
4 Apparel bangalore kalyan nagar name4 (result based on `db_shop_views` who's view count is more)
3 Apparel bangalore kalyan nagar name3 (result based on `db_shop_views`)
I have no idea how to join and count the views. Is it possible to join in above method.
After lots of searching. Finally i got the answer.
SELECT DISTINCT s.shop_id, c.city_name, l.locality_name, ca.category_name, s.shop_name, s.shop_logo, s.cart_url, s.shop_about FROM db_shop s INNER JOIN db_city c ON c.city_id = s.city_id INNER JOIN db_category ca ON ca.category_id = s.category_id INNER JOIN db_locality l ON l.locality_id = s.locality_id LEFT JOIN (SELECT * FROM db_shop_recommended r ORDER BY r.priority ASC) r1 ON s.shop_id = r1.shop_id LEFT JOIN (select distinct g.shop_id, g.cnt from (select distinct shop_id, count(shop_id) cnt from db_shop_views group by shop_id) g inner join (select max(s.cnt) max_cnt from(select distinct shop_id, count(shop_id) cnt from db_shop_views group by shop_id) s) m on m.max_cnt = g.cnt) v ON s.shop_id = v.shop_id WHERE s.publish = 1

mysql query: how to

here's my (simplified) table structure:
table: category_main
id name
-------------
1 food
2 vegetable
table category_sub
id id_catmain name
---------------------
10 1 cake
11 1 chocolate
12 1 burger
13 2 apple
14 2 banana
table images
id id_catsub filename views
-------------------------------------
1 10 cake1.jpg 11
2 10 cake2.jpg 24
3 10 cake3.jpg 65
4 11 chocolate1.jpg 31
5 11 chocolate2.jpg 62
6 11 chocolate3.jpg 32
7 11 chocolate4.jpg 58
8 12 burger1.jpg 23
9 12 burger2.jpg 43
10 12 burger3.jpg 76
11 13 apple1.jpg 29
11 13 apple2.jpg 67
11 14 banana1.jpg 78
desired output:
id name total_views
----------------------------
1 food 425
2 vegetable 174
as you can see i want to get the total views for each main category.
currently i'm running a loop for each subcategory but there must be an easier and faster way :/
thanks
Double LEFT JOIN + aggregation will do the job.
SELECT cm.id, cm.name, sum(images.views) as views
FROM category_main as cm
LEFT JOIN category_sub as cs ON cs.id_catmain = cm.id
LEFT JOIN images ON images.id_carsub = cs.id
GROUP BY cm.id
ORDER BY views DESC;
LEFT JOIN (instead of JOIN) will make you sure that you have all categories listed even if there's no subcategory or image in it. If you don't want empty categories to be listed, then use JOIN.
SELECT c.id AS id, c.name AS name, sum(i.views) AS total_views
FROM category_main c, category_sub s, images i
WHERE c.id=s.id_catmain and s.id=i.id_catsub
GROUP BY c.id,c.name;
simply join the three tables, and then you can sum the views grouped by the id's:
select cm.id, cm.name, sum(i.views) as total_views from
category_main as cm inner join category_sub as cs on cm.id = cs.id_catmain
inner join cs.id = i.id_catsub group by cm.id