This is my Query :
SELECT
p.PRO_Id, p.PRO_Name,
COUNT(DISTINCT c.COM_Id) as commentCount,
COUNT(DISTINCT d.DIS_Id) AS disCount,
d.DIS_ThreadDesc,
dev.DEV_Name,
loc.LOC_Name,
d.USE_Id,
d.DIS_Date
FROM projects p
LEFT JOIN discussions d ON p.PRO_Id = d.PRO_Id
LEFT JOIN comments c ON d.DIS_Id = c.DIS_Id
LEFT JOIN developer dev ON p.DEV_Id=dev.DEV_Id
LEFT JOIN locality loc ON p.LOC_Id=loc.LOC_Id
WHERE p.PRO_Status=1
and d.DIS_Status=1
and c.COM_Status=2
GROUP BY p.PRO_Id
ORDER BY 3 desc LIMIT 3
What i'm trying to get is the sum of commenCount(total comments) and disCount(total discussions). I tried like this;- sum(COUNT(DISTINCT c.COM_Id) + COUNT(DISTINCT d.DIS_Id)) AS totalResponse but no chance.
You can add result of both COUNTs:
SELECT
p.PRO_Id, p.PRO_Name,
COUNT(DISTINCT c.COM_Id) AS commentCount,
COUNT(DISTINCT d.DIS_Id) AS disCount,
COUNT(DISTINCT c.COM_Id) + COUNT(DISTINCT d.DIS_Id) AS totalResponse
d.DIS_ThreadDesc, dev.DEV_Name, loc.LOC_Name, d.USE_Id, d.DIS_Date
FROM projects p
...
alternatively using subquery:
SELECT sub.*,
commentCount + disCount AS totalResponse
FROM (
SELECT
p.PRO_Id, p.PRO_Name,
COUNT(DISTINCT c.COM_Id) as commentCount,
COUNT(DISTINCT d.DIS_Id) AS disCount,
d.DIS_ThreadDesc,
dev.DEV_Name,
loc.LOC_Name,
d.USE_Id,
d.DIS_Date
FROM projects p
LEFT JOIN discussions d ON p.PRO_Id = d.PRO_Id
LEFT JOIN comments c ON d.DIS_Id = c.DIS_Id
LEFT JOIN developer dev ON p.DEV_Id=dev.DEV_Id
LEFT JOIN locality loc ON p.LOC_Id=loc.LOC_Id
WHERE p.PRO_Status=1
and d.DIS_Status=1
and c.COM_Status=2
GROUP BY p.PRO_Id
) AS sub
ORDER BY commentCount LIMIT 3
Keep in mind that your SELECT list and GROUP BY does not match. This will work for MySQL but is not compliant with ANSI standard. You should have the same list in both clauses or use aggregate functions for columns that are not specified in GROUP BY. More info here.
Related
I have two tables: users and courses. Inside users table i have filed course where i have course id. Inside courses table i have just ID and NAME.
I need to get popular course. I do request:
SELECT u.course, COUNT(*) as freq FROM users u INNER JOIN courses c ON u.course = c.id GROUP BY u.course
As a result: id => freq. But i need to replace ID to NAME of course. How?
Thanks.
You don't say what database you use, but I would assume you can use CTEs since most modern databases do. Your query can be written as:
with x as (
select course, count(*) as freq from users group by course
),
y as (
select max(freq) as max_freq from x
)
select c.name, x.freq
from x
join y on x.freq = y.max_freq
join courses c on c.id = x.course
This query has the [desirable?] side effect that it shows more than one course, if there are more than one tied in first place.
Add c.name to both the SELECT clause and the GROUP BY clause.
SELECT u.course, c.name, COUNT(*) as freq
FROM users u
INNER JOIN courses c
ON u.course = c.id
GROUP BY u.course, c.name;
Demo: https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=02a41e0f1e6407e516e91c49b4bdc1d2
SELECT u.course, COUNT(*) as freq, c.name FROM users u INNER JOIN courses c ON u.course = c.id GROUP BY u.course
If your DBMS supports row_number this will be suitable:
select t.id, c.name, t.cnt
from course c
join (
select c.id, count(1) cnt, ROW_NUMBER() over(order by count(1) desc) rn
from users u
join course c on c.id = u.course
group by id
)t on t.id = c.id and t.rn = 1
I have two tables called work and stuff both tables have same fields -
company, quality, quantity
I need the sum of all the quantity of work with group by company and quality and join the table with sum of all the quantity of stuff with group by company and quality
I didn't get the expected result.
SQLfiddel
http://sqlfiddle.com/#!9/eea577/6
working query
select st.company,st.quality,st.quantitys - ct.quantitys as balance from
(select company,quality,sum(quantity) as quantitys from stuff
group by quality,company) as st join (select company,quality,
sum(quantity) as quantitys from work group by quality,company)
as ct on `ct`.`company` = `st`.`company` and ct.quality = st.quality group by quality,company
u have missed the quality condition in the join
Try the following:
SELECT tableA.ID, tableA.`Year`, tableA.`Month`,
tableA.`Type`, tableA.instrument,
tableA.totalAmount, tableB.totalInstrument
FROM
(
SELECT a.ID, a.`Year`, a.`Month`,
b.`Type`, b.instrument,
SUM(b.`amount`) totalAmount
FROM `date` a
INNER JOIN `transactions` b
ON a.ID = b.id
GROUP BY b.`Type
) tableA
INNER JOIN
(
SELECT a.ID, a.`Year`, a.`Month`,
b.`Type`, b.instrument,
SUM(b.`instrument`) totalInstrument
FROM `date` a
INNER JOIN `transactions` b
ON a.ID = b.id
GROUP BY a.`Year`, a.`Month`
) tableB ON tableA.ID = tableB.ID AND
tableA.`Year` = tableB.`Year` AND
tableA.`Month` = tableB.`Month`
i create a web app like facebook by php and mysqli
in my app i have a table for posts , one table for likes , and one table for comments
i want to get the number of comments and likes of each post in one row with his post_id!!!
i try some querys likes this :
select `tblpost`.`post_id`, COALESCE(TCOMM.`comment_num`,0) as `c_num`, COALESCE(TLIKE.`like_num`,0) as `l_num`
from
(select `tblpost`.`post_id`, count(*) as `like_num` from `tblpost` join `tbllikes` on `tbllikes`.`post_id` = `tblpost`.`post_id` group by `tblpost`.`post_id`
) TLIKE
inner join
(select `tblpost`.`post_id`, count(*) as `comment_num` from `tblpost` join `tblcomments` on `tblcomments`.`post_id` = `tblpost`.`post_id` group by `tblpost`.`post_id`) TCOMM
on
TCOMM.`post_id` = TLIKE.`post_id`
but i don't know what's my problem
You can do count distincts with two left joins.
Something like this would work if there are fields like_id and comment_id in the tables tbllikes and tblcomments
SELECT
tblpost.post_id AS post_id,
COUNT(DISTINCT tbllikes.like_id) AS likes,
COUNT(DiSTINCT tblcomments.comment_id) AS comments
FROM tblpost
LEFT JOIN tbllikes ON tbllikes.post_id = tblpost.post_id
LEFT JOIN tblcomments on tblcomments.post_id = tblpost.post_id
GROUP BY tblpost.post_id
First, I think you can greatly simplify your query:
select l.post_id,
COALESCE(c.comment_num, 0) as c_num, COALESCE(l.like_num, 0) as l_num
from (select l.post_id, count(*) as like_num
from tbllikes l
group by l.post_id
) l inner join
(select c.post_id, count(*) as comment_num
from tblcomments c
group by c.post_id
) c
on l.post_id = c.post_id;
This will only get you posts that have both likes and comments. To get what you want, use a left join:
select p.post_id,
COALESCE(c.comment_num, 0) as c_num, COALESCE(l.like_num, 0) as l_num
from tblpost p left join
(select l.post_id, count(*) as like_num
from tbllikes l
group by l.post_id
) l
on l.post_id = p.post_id left join
(select c.post_id, count(*) as comment_num
from tblcomments c
group by c.post_id
) c
on c.post_id = p.post_id;
I wish to join multiple tables like- Categories, menus, restaurants, reviews, etc.
to return the restaurants that provide the inserted food with their prices.
Everything works except numberOfReviews in reviews table.
If a restaurant has no reviews then output should be 0 for numOfReviews column but other column values should be retrieved i.e. price, name, etc.
With following query I get all fields as null and count(numReviews) as 0:
select r.id
,r.`Name`
,r.`Address`
,r.city
,r.`Rating`
,r.`Latitude`
,a.`AreaName`
,m.`Price`
,count(rv.id)
from `categories` c, `menus` m, `restaurants` r, areas a, reviews rv
where m.`ItemName`="tiramisu"
and c.`restaurant_id`=r.`id`
and m.`category_id`=c.id
and r.`AreaId`=a.`AreaId`
and if I can't match rv.restaurant_id=r.id in where clause(obviously).
Where am I getting wrong? How do I solve this?
edited
select r.id,
r.`Name`,
r.`Address`,
r.city,
r.`Rating`,
r.`Latitude`,
a.`AreaName`,
m.`Price`,
r.`Longitude`,
r.Veg_NonVeg,
count(rv.id)
from restaurants r LEFT JOIN `reviews` rv on rv.`restaurant_id`=r.`id`
inner join `categories` c on c.`restaurant_id` = r.id
inner join `menus` m on m.`category_id` = c.id
inner join `areas` a on a.`AreaId` = r.`AreaId`
where m.`ItemName`="tiramisu"
First of all, don't use this old school syntax for the jointures.
Here is a query that may solve your problem:
SELECT R.id
,R.Name
,R.Address
,R.city
,R.Rating
,R.Latitude
,R.Longitude
,A.AreaName
,M.Price
,R.Veg_NonVeg
,COUNT(RV.id) AS numOfReviews
FROM restaurants R
INNER JOIN categories C ON C.restaurant_id = R.id
INNER JOIN menus M ON M.category_id = C.id
INNER JOIN areas A ON A.AreaId = R.AreaId
LEFT JOIN reviews RV ON RV.restaurant_id = R.id
WHERE M.ItemName = 'tiramisu'
GROUP BY R.id, R.Name, R.Address, R.city, R.Rating, R.Latitude, R.Longitude, A.AreaName, M.Price, R.Veg_NonVeg
I used explicit INNER JOIN syntax instead of your old school syntax and I modified the jointure with table reviews in order to get the expected result. The GROUP BY clause is required to use the aggregate function COUNT, every rows will be grouped by the enumerated columns (every column except the one used by the function).
Here is another solution that simplify the GROUP BY clause and allow the modification of SELECT statement without having to worry about the fact that every columns need to be part of the GROUP BY clause:
SELECT R.id
,R.Name
,R.Address
,R.city
,R.Rating
,R.Latitude
,R.Longitude
,A.AreaName
,M.Price
,R.Veg_NonVeg
,NR.numOfReviews
FROM restaurants R
INNER JOIN (SELECT R2.id
,COUNT(RV.id) AS numOfReviews
FROM restaurants R2
LEFT OUTER JOIN reviews RV ON RV.restaurant_id = R2.id
GROUP BY R2.id) NR ON NR.id = R.id
INNER JOIN categories C ON C.restaurant_id = R.id
INNER JOIN menus M ON M.category_id = C.id
INNER JOIN areas A ON A.AreaId = R.AreaId
WHERE M.ItemName = 'tiramisu'
As you can see here I added a new jointure on a simple subquery that does the aggregation job in order to provide me the expected number of reviews for each restaurant.
Hope this will help you.
I have two tables namely locations and pilots. I have been trying to fetch data based on location_id i.e selecting pilots who are flying in a particular location_id order by date(date of schedule).
I am using group by as i need only distinct pilots to be displayed.
select B.*,
A.rather_to_be_flying_now,
A.here_now,
A.flying,
A.when,
A.my_favorite,
A.start,
A.end,
A.Locationid
from locations A
inner join pilots B
on A.Pilotid=B.pilot_id
where A.VenueID='$venueid'
and (A.flying='1' or A.here_now='1')
group by A.Pilotid
ORDER BY A.start
The query works good if i wont include a group by clause. It returns the following result
with out group by clause
with group by clause
But the above table shows wrong order, as the output must return start time as 2013-01-24 02:00:00 for pilotid 1 (Chronological order).
You can use MIN()
select B.*,
A.rather_to_be_flying_now,
A.here_now,
A.flying,
A.when,
A.my_favorite,
MIN(A.start) as start,
A.end,
A.Locationid
from locations A
inner join pilots B
on A.Pilotid=B.pilot_id
where A.VenueID='$venueid'
and (A.flying='1' or A.here_now='1')
group by A.Pilotid
ORDER BY A.start
Try this instead:
SELECT
B.*,
A.rather_to_be_flying_now,
A.here_now,
A.flying,
A.when,
A.my_favorite,
A.start,
A.end,
A.Locationid
FROM locations A
INNER JOIN
(
SELECT pilotid, MIN(start) MinStart
FROM locations
GROUP BY pilotid
) a2 ON A.pilotId = a2.pilotId
AND a.start = a2.minStart
INNER JOIN pilots B on A.Pilotid = B.pilot_id
WHERE A.VenueID = '$venueid'
AND (A.flying='1' OR A.here_now='1');
ORDER BY A.start ;
This will give you only those pilots with the minimum start date.
Try this query -
SELECT
p.pilit_id, l.location_id, l.start
FROM pilots p
JOIN (SELECT l1.*
FROM locations l1
JOIN (SELECT location_id, MIN(start) start
FROM locations
GROUP BY locations) l2
ON l1.id = l2.id AND l1.start = l2.start
) l
ON l.pilot_id = p.pilot_id
GROUP BY p.pilot_id
Add your WHERE condition.