How to count a Column data using join over 3 tables - php

I have three tables
tbl_product
item_id | item_name
company_details
v_id | item_id | company_name
user_ratings
r_id | rate | v_id
I want to count the rate and also get the rate of the company. Here is my query
SELECT company_details.v_id,
company_details.company_name,
COUNT(user_ratings.rate) as vote,
user_ratings.rate,
tbl_product.item_name
FROM company_details
LEFT JOIN tbl_product ON tbl_product.item_id = company_details.item_id
LEFT JOIN user_ratings ON user_ratings.v_id = company_details.v_id
GROUP BY company_details.v_id, user_ratings.rate
This is Whts i am Getting after this query:
v_id company_name vote rate item_name
1 The Oberoi Udaivilas 1 4 5 Star Hotels
1 The Oberoi Udaivilas 1 5 5 Star Hotels
2 The Taj Mahal Palace 2 5 4 Star Hotels
3 Rambagh Palace 1 5 3 Star Hotels
4 Taj Lake Palace 1 5 5 Star Hotels
5 Windflower Hall 1 3 2 Star Hotels
5 Windflower Hall 1 5 2 Star Hotels
6 Leela Palace Kempinski 0 n 4 Star Hotels
7 Umaid Bhawan Palace 0 n 4 Star Hotels
8 Hotel Ratan Vilas 0 n 4 Star Hotels
9 The Leela Palace 0 n 4 Star Hotels
10 The Imperial Hotel 0 n 3 Star Hotels
You can see vote column is not counting.
This is what I am expecting
v_id company_name vote rate item_name
1 The Oberoi Udaivilas 2 5 5 Star Hotels
2 The Taj Mahal Palace 2 5 4 Star Hotels
But this query is not counting the rate from user_ratings table, because of I also want to get the rate, if I remove the user_ratings.rate from select clause, then this query works, but when I add the user_ratings.rate in the select clause, then this query is not counting the rates as(vote), and it is returning as one rows in every count.

You should remove user_ratings.rate from group by clause and add tbl_product.item_name.
SELECT
company_details.v_id,
company_details.company_name,
tbl_product.item_name,
COUNT(user_ratings.rate) as vote,
avg(user_ratings.rate) as rate
FROM
company_details
LEFT JOIN tbl_product ON tbl_product.item_id = company_details.item_id
LEFT JOIN user_ratings ON user_ratings.v_id = company_details.v_id
GROUP BY company_details.v_id, company_details.company_name, tbl_product.item_name;

Seems to me that your query is only missing an aggregation on the rate column, and from the expected output I'd say it's a max. You also should fix your group by. Try this one
SELECT company_details.v_id,
company_details.company_name,
COUNT(user_ratings.rate) as vote,
MAX(user_ratings.rate) as rate,
tbl_product.item_name
FROM company_details
LEFT JOIN tbl_product ON tbl_product.item_id = company_details.item_id
LEFT JOIN user_ratings ON user_ratings.v_id = company_details.v_id
GROUP BY company_details.v_id,
company_details.company_name,
tbl_product.item_name

Query and result are both correct. Look at the rate

you can try this query it will return your exactly output according to your given 3 tables.
"select c.v_id , c.company_name , u.rate , p.item_name from company_details c join tbl_product p on p.item_id = c.item_id join user_details u on c.v_id = u.v_id group by c.company_name ";

Related

Select row in group by min of another column

Hey can you help me with my simple sql query ?
Tables
Hotel
id | name | country | rating
1 Bali bg 4.5
2 Beach uk 4.0
3 Blue sk 3.7
Tour
id | id_hotel | price
1 2 250
2 2 270
3 1 250
4 1 300
5 3 250
And I want something like this
SELECT t.* FROM tour t LEFT JOIN hotel h ON t.id_hotel = h.id
WHERE h.country = uk GROUP BY h.id ORDER BY t.price
So I wanna get only one row for each one hotel with min tour price.
And best with using Doctrine 2 queryBuilder.
Thanks for help.
Hey prbably I have solution
SELECT MIN(tour.id), hotel.* FROM `tour` INNER JOIN (
SELECT MIN(t.final_price) as final_price, t.id_hotel FROM tour t GROUP
BY t.id_hotel) ht
ON tour.id_hotel = ht.id_hotel AND tour.final_price =
ht.final_price
LEFT JOIN hotel ON hotel.id = tour.id_hotel GROUP BY tour.id_hotel
Use group by with order by to accomplish your result, try below query
select hotel.name,Tour.id,Tour.price,Hotel.rating from Hotel inner join Tour on Tour.id_hotel = Hotel.id group where hotel.country = 'uk' group by Tour.id_hotel order by Tour.price asc
Let me know if it helps
[Edit] This query should work with you

Mysql: Duplicate and incorrect output when using join

I have 4 tables on which I need to use a join. The query is returning duplicate rows. However for simplicity I will post my question with just 2 tables as the problem still exits even with 2 tables. Tables are called as product_offer and promo. The structures are as below
product_offer table:
id product_id offer_id store_id validity
1 1 1 1 2016-12-12 00:00:00
2 2 2 1 2016-12-12 00:00:00
3 3 3 1 2016-12-12 00:00:00
4 1 4 1 2016-12-12 00:00:00
promo table:
id product_id store_id name
1 1 1 Buy 1 Get 1 free
2 2 1 10% off
3 3 1 $10 off
4 1 1 Get Chips Free
I am trying to fetch all the offers for a particular product-store combination. I am expecting to get this
product_id offer_id store_id name
1 1 1 Buy 1 Get 1 Free
1 4 1 Get Chips Free
But When I run this query I am getting the below output which is incorrect and with duplicate rows
SELECT po.product_id, po.offer_id,po.store_id,o.name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
product_id offer_id store_id name
1 1 1 Buy 1 Get 1 Free
1 4 1 Buy 1 Get 1 Free
1 1 1 Get Chips Free
1 4 1 Get Chips Free
I also want to improve the query and use concat(using ~ as separator) to only return one row per product_id as below:
product_id offer_id store_id name
1 1~4 1 Buy 1 Get 1 free~Get Chips Free
You want to use a GROUP BY, what does it, it takes the column you chose puts them together to avoid duplicate results where data in that column matches
SELECT po.product_id, po.offer_id,po.store_id,o.name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
GROUP BY product_id
In order to concatenate them, there is the option of GROUP_CONCAT, you can read more at http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat
use Group by with GROUP_CONCAT
SELECT po.product_id,GROUP_CONCAT(DISTINCT po.offer_id SEPARATOR '~') offer_id
,po.store_id,GROUP_CONCAT(DISTINCT o.name SEPARATOR '~') name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
Group by product_id
I realized I was doing the Join ON the wrong column. When I changed the join on offer_id from product_offer and id on promo it worked nicely.
SELECT po.product_id, group_concat(po.offer_id SEPARATOR '~') offer_id, po.store_id ,group_concat(o.name SEPARATOR '~') offer
FROM product_offer po
LEFT JOIN
promo o ON po.offer_id = o.id
WHERE
po.product_id = 1 and po.store_id = 1
I think you need to group by offer_id
SELECT po.product_id,GROUP_CONCAT(po.offer_id SEPARATOR '~') offer_id,po.store_id,o.name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
Group by offer_id

How To Use Max function with group by using MYSQL

I have those 3 tables
candidates
cdid cdname
1 Moussa
2 Moustafa
3 Haitham
positions
posid posname
1 pos1
2 pos2
3 pos3
joboffers
cdid posid salary
1 1 600
1 2 800
1 3 700
2 1 500
2 2 700
2 3 900
3 2 1000
3 3 500
I need to make a query that get the cdname with max salary for every position
the table should be like this
cdname posname salary
moussa pos1 600
haitham pos2 1000
moustafa pos3 900
I am using this query but it's not getting the correct cdid
$sql="select joboffers.cdid,joboffers.posid,Max(joboffers.salary),candidates.cdname
FROM joboffers,candidates
Where joboffers.cdid=candidates.cdid
Group by joboffers.posid";
Try this :)
SELECT sub.cdname, sub.posname, sub.salary
FROM (
SELECT * FROM joboffers jo
INNER JOIN positions ps USING (posid)
INNER JOIN candidates cd USING (cdid)
ORDER BY posid, salary DESC
) sub
GROUP BY sub.posid
I think you need to group by all non-aggregated columns, like this:
SELECT j.cdid, c.cdname, j.posid, MAX(j.salary)
FROM joboffers j
JOIN candidates c ON j.cdid = c.cdid
GROUP BY j.cdid, c.cdname, j.posid
SELECT c.cdname, p.posname, MAX(j.salary)
FROM joboffers j
INNER JOIN candidates c ON j.cdid = c.cdid
INNER JOIN positions p ON j.posid = p.posid
GROUP BY c.cdname, p.posname
enter code hereSELECT customerNumber, MAX(amount)
FROM payments
GROUP BY customerNumber
ORDER BY MAX(amount);

mysql join and sum problems

Im having some trouble with this.
Here's an example of my tables.
Booking
id zone_id name excursion_id
1 2 1
2 1 1
3 2 1
The table where I have the quantities
booking_price
id_booking id_price quantity
1 1 2
1 2 3
2 1 1
2 2 0
3 1 2
3 2 3
Here the zone table
Zone
id Name
1 a
2 b
3 c
So I want to have a table like that
Zone_id Quantity
1 1
2 10
3 0
The problem is when im joining tables and filtering by excursion_id im not getting ALL the zones.
I want to know how many people goes in each zone.
I think better way of doing it is
select z.id, coalesce(sum(bp.quantity),0) as quantity
from Booking b
right join Zone z on z.id = b.zone_id AND b.excursion_id = 1
left join booking_price bp on bp.id_booking = b.id
group by z.id
demo http://sqlfiddle.com/#!2/771f5/13
You could use a query like:
SELECT zone.id as zone_id,
sum(quantity) as Quantity
FROM zone
LEFT JOIN Booking on Booking.zone_id = zone.id
LEFT JOIN Excursion on Excursion.id_booking = Booking.id
GROUP BY zone.id

PHP MySQL Highscore table

Im joining 3 tables to present a table with users highest score
My tables
game_log:
---ID---user_ID---score---time---
| 1 52 567 10 |
| 2 53 641 13 |
| 3 52 465 8 |
| 4 53 451 14 |
---------------------------------
users:
---ID---name---countyid---
| 52 Dave 1 |
| 53 John 2 |
------------------------
county:
---countyid---countyname---
| 1 Orange wichit |
| 2 Orange clemts |
--------------------------
SQL:
SELECT * FROM game_log
INNER JOIN users ON game_log.user_ID=users.ID
INNER JOIN county ON users.countyid=county.countyid
ORDER BY game_log.score DESC , game_log.time LIMIT 20";
Above code gives me this result:
Rank---Name--------County------Score---Time
1 John Orange clemts 641 13
2 Dave Orange wichit 567 10
3 John Orange clemts 465 8
4 Dave Orange wichit 451 14
My problem is that I want the highscore table to display the top 20 users with the highest score, not the 20 highest scores.
Like this:
Rank---Name--------County------Score---Time
1 John Orange clemts 641 13
2 Dave Orange wichit 567 10
Need som help with this, not familiar with joining tables ;-)
This approach will show the top 20 users and each user's highest score, and if they have multiple instances of the same score, it'll show the information for the earliest one (lowest time value for that user and score).
SELECT *
FROM game_log gl
INNER JOIN users u
ON gl.user_ID = u.ID
INNER JOIN county c
ON u.countyid = c.countyid
WHERE not exists (select 1
from game_log gl2
where gl2.user_id = gl.user_id
and gl2.score > gl.score)
and not exists (select 1
from game_log gl2
where gl2.user_id = gl.user_id
and gl2.time < gl.time
and gl2.score = gl.score)
ORDER BY gl.score DESC, gl.time LIMIT 20;
Without doing this, if the same user in the top 20 had the same score 2+ times, they would be listed 2+ times, and you would not get back 20 people by using LIMIT 20 because the same person would be taking up N rows out of that 20.
SQL Fiddle here showing data with a tie: http://sqlfiddle.com/#!2/0ac931/5/0
GROUP BY should do the job.
SELECT users.ID, users.name, county.countyname, MAX(game_log.score) AS score, game_log.time
FROM game_log
INNER JOIN users ON game_log.user_ID = users.ID
INNER JOIN county ON users.countyid = county.countyid
GROUP BY game_log.user_ID
ORDER BY game_log.score DESC, game_log.time
LIMIT 20;
Try it out with SQL Fiddle.
I would do this with the not exists approach to get the highest score for each user. The rest of the query is the same:
SELECT *
FROM game_log gl INNER JOIN
users u
ON gl.user_ID = u.ID INNER JOIN
county c
ON u.countyid = c.countyid
WHERE not exists (select 1
from game_log gl2
where gl2.user_id = gl.user_id and gl2.score > gl.score
)
ORDER BY gl.score DESC, gl.time
LIMIT 20;
The where clause is saying "keep this row if no other row for the same user has a higher score".
Another way to do this is with the aggregation approach:
SELECT *
FROM (select user_id, max(score) as maxscore
from game_log gl
group by user_id
) gl INNER JOIN
users u
ON gl.user_ID = u.ID INNER JOIN
county c
ON u.countyid = c.countyid
ORDER BY gl.maxscore DESC
LIMIT 20;
But this method loses the information about time. It is possible to include that, but it makes the query more complicated.

Categories