How To Use Max function with group by using MYSQL - php

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);

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

how to select records based on recent date in mysql

I have 3 tables like below :
hr_emp_job_compensation:
id date fkEmp_id basic_wage part_hours part_amt
1 04-01-2016 1 4500 35 120
2 04-01-2016 3 3800 30 150
3 08-01-2016 3 3200 30 100
hr_emp_job_info:
id fkEmp_id
1 1
2 3
hr_emp_info:
id employee_id first_name
1 001 Ram
2 002 Lak
3 003 jai
4 004 shiva
I want to select records from table 1 , based on the column Date value is higher.
I Try the following query :
SELECT t1.fkEmp_id,max(t1.date),max(t1.id) as uid,t1.part_hours,t1.part_amt, t3.first_name, t3.employee_id
FROM `hr_emp_job_compensation` as t1
inner join `hr_emp_job_info` as t2 on t1.fkEmp_id = t2.fkEmp_id
left join `hr_emp_info` as t3 on t3.id = t1.fkEmp_id
group by t1.fkEmp_id
But the result is look like below :
fkEmp_id max(t1.date) uid part_hours part_amt first_name employee_id
1 2016-01-04 1 35 120 Ram 001
3 2016-01-08 3 30 150 Jai 003
Here the part_hours and part_amt columns are fetched from the id 2. How to change the query.
No need to add MAX() for the dateand id. You can handle the MAX(date) in the WHERE clause.
SELECT t1.fkEmp_id, t1.date as `date`, t1.id as uid,
t1.part_hours, t1.part_amt,
t3.first_name, t3.employee_id
FROM `hr_emp_job_compensation` as t1
INNER JOIN `hr_emp_job_info` as t2 on t2.fkEmp_id = t1.fkEmp_id
LEFT JOIN `hr_emp_info` as t3 on t3.id = t1.fkEmp_id
WHERE t1.`date`= ( SELECT MAX(`date`)
FROM `hr_emp_job_compensation`
WHERE fkEmp_id = t1.fkEmp_id);
Please find the Working Demo

Mysql select multiple count giving wrong values

I'm trying to find a patient's appointments and messages count. My table records are like below 3 table patient, appointments and messages
Patient table
pid fname lname
1 john sid
2 rother ford
3 megan rough
4 louis kane
appointments table
id pid appointment_date
1 1 2015-08-04
2 2 2015-08-05
3 1 2015-08-06
4 1 2015-08-07
5 3 2015-08-07
6 2 2015-08-08
7 4 2015-08-13
8 1 2015-08-12
Messages table
id pid description message_date
1 2 join 2015-08-04
2 2 update 2015-08-05
3 3 join 2015-08-05
4 4 update 2015-08-10
5 3 test 2015-08-07
So if write query to find counts i'm getting wrong values
SELECT pd.fname,pd.lname , pd.pid, COUNT( a.id ) AS app_cnt, COUNT( m.id ) AS mes_cnt
FROM patient pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid
LEFT OUTER JOIN messages m ON m.pid = pd.pid
GROUP BY pd.pid
ORDER BY pd.pid
fname lname pid app_cnt mes_cnt
john sid 1 4 0
rother ford 2 4 4
megan rough 3 2 2
louis kane 4 1 1
Here pid 1 have 4 appointments and 0 messages, pid 2 have 2 appointments and 2 messages but getting wrong values.
Can someone please help to resolve this issue. I'm not interested in writing sub queries for this.
Functionality looks simple but I'm really facing problem for writing query.
Anymore suggestions please.
After thoroughly analysing your problem and tables, It cannot be done directly using simple query as LEFT OUTER JOIN is returning some superfluous records, that's why to filter it, you will have to use temporary table and modify the query as:
Select temp.fname, temp.lname, temp.pid, a_count, count(m.pid) as m_count from
(SELECT fname,lname,pd.pid, count(a.pid) as a_count
FROM patients pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid group by pd.pid) temp
LEFT OUTER JOIN messages m ON m.pid = temp.pid
group by temp.pid
Explanation:
It will join patients and appointments table and group them by pid so that messages from message table do not repeat for each patients.pid.
The wrong result is as a result of left outer join as it is giving wrong results for this query
SELECT *
FROM patients pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid
LEFT OUTER JOIN messages m ON m.pid = pd.pid
Since we need to limit the results of first two joins, hence temporary table is necessary.

mysql query to get the min values according to the latesttime stamp

Hi I have try to find a solution for a query to get the minvalues along with latest time stamp.
I have following tables
Table1
sno user_id name subject rank Timestamp
1 10 SS maths1 1 2014-12-05 17:24:33
2 10 SS maths2 2 2014-12-05 17:24:33
3 10 PH phy1 3 2014-12-05 17:24:33
4 10 PH phy2 4 2014-12-05 17:24:33
5 10 SS maths1 2 2014-12-04 17:24:33
6 10 SS maths2 1 2014-12-04 17:24:33
7 10 PH phy1 3 2014-12-04 17:24:33
8 10 PH phy2 4 2014-12-04 17:24:33
Tabe12
sno name Status
1 SS Active
2 PH ACtive
3 So Inactive
So I am trying to get the following result
sno userid name subject rank timpestamp
1 10 SS maths1 1 2014-12-05 17:24:33
2 10 PH phy1 3 2014-12-05 17:24:33
So far I tried this query I am able to get the latest time and least rank values for subjects with Distinct name.
but they are not connected to each other means I getting the latesttime stamp and least value from some other row. Please help me How to solve it.
SELECT DISTINCT(T1.`name`),
T1.`user_id`,
T1.`subject`,
MAX(T1.`Timestamp`) as latest_Timestamp,
MIN(T1.`rank `) as rank
FROM Table1 T1,Table2 T2
where T1.`user_id`='10'
AND T2.`status` = 'Active'
AND T1.`name` = T2.`name`
GROUP BY T1.`exercise_id`
ORDER BY T1.`quality_id`, T1.`Timestamp` ASC
Relational databases work well on sets. So think of the data in different sets
You need a set that combines t1 and t2
You need a subset of t1 that only consists of the min rank and max timestamp for each user_Id and name.
So T1 and T2 are joined generating the universe of data and columns you need. We then join to the subquery contianing the subset to filter out the non max timestamp and non-min rank you want.
SELECT T1values.name,
T1values.user_id,
T1values.subject,
T1values.rank,
T1values.timestamp
FROM Table2 T2
INNER JOIN table1 t1Values
ON t1values.sno = t2.sno
and t2.status='Active'
INNER JOIN (SELECT user_Id, name max(timestamp) maxTime, min(rank) Mrank
FROM Table1
GROUP BY user_Id, Name) T1
ON t1.name = T1values.name
and t1.user_Id = t1values.user_ID
and t1.maxTime = T1Values.timestamp
and t1.rank = T1values.mrank
WHERE T1values.user_id='10'
ORDER BY T1values.quality_id, T1values.Timestamp ASC

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