How to join tables with aggregate functions in MYSQL query? - mysql

I have two tables from the database and I want to get the last status of each id. Tried adding the INNER JOIN claus but no avail. These are what my data looks like:
Table: employee
id name department
-------------------------
1 A X
2 B Y
3 C Z
Table: timelog
id time status count
-------------------------------
1 08:51 IN 1
3 09:00 OUT 2
2 09:00 IN 3
2 18:00 OUT 4
1 18:05 OUT 5
Currently, this is the query that I use but need to get the name of each employee.
SELECT
*
FROM timelog
WHERE timelog.count
IN (SELECT MAX(timelog.count)
FROM timelog
GROUP BY timelog.id)
ORDER BY clock.id;
Current output:
id time status
-------------------------------
1 18:05 OUT
2 18:00 OUT
3 09:00 OUT
This is the output I want to achieve:
id name time status
-------------------------------
1 A 18:05 OUT
2 B 18:00 OUT
3 C 09:00 OUT
Is it possible to add JOIN to the above query? If no, what would be the workaround? Any help would be greatly appreciated. TIA.

Use a correlated subquery to get the last record for each id in timelog:
SELECT e.*, tl.*
FROM employee e JOIN
timelog tl
ON e.id = tl.id
WHERE tl.count = (SELECT MAX(tl2.count)
FROM timelog tl2
WHERE tl2.id = tl.id
) ;
Note that your version of the query is not correct. The subquery returns the maximum count for each id. However, the outer query might match a different id to the count in the subquery. The correlation clause fixes this problem.

You can join the tables and use a correlated subquery for filtering:
select
e.id,
e.name,
t.time,
t.status
from employee e
inner join timelog t on t.id = e.id
where t.count = (
select max(count)
from timelog t1
where t1.id = t.id
)

Related

Group by with latest record on join query

Here is my table deals_transaction_status_log with the following fields
id,user_id,deal_transaction_id,transaction_status_id in which i want to fetch the records with group by on transaction_id with latest record on(max id).
This table also join some another tables to get some other data.
Here is my query
SELECT dtsl.id ,dtsl.deal_transaction_id,dts.id as statusId
FROM deals_transaction_status_log as dtsl
JOIN deals_transactions as dt ON dt.id=dtsl.deal_transaction_id AND dt.visitor_id=140
JOIN DEALS as d ON d.idDeal=dt.deal_id
JOIN USER as u ON d.userId=u.idUser
JOIN deals_transaction_status as dts ON dts.id=dtsl.transaction_status_id
WHERE dtsl.user_id!=140 AND dtsl.transaction_status_id=14 AND dtsl.id IN (
SELECT MAX(dtsl.id)
FROM deals_transaction_status_log as dtsl
GROUP BY dtsl.deal_transaction_id
) GROUP BY dtsl.deal_transaction_id
This works fine however it returns only one record even if i have more than one record with same deal_transaction_id
for eg:
Sample Input
id user_id deal_transaction_id transaction_status_id
1 4 2 14
2 4 2 14
3 5 3 14
4 5 3 14
Result
id statusId deal_transaction_id
3 14 3
Expected result
id statusId deal_transaction_id
2 14 2
4 14 3
UPDATE
I just tried fa06 answer without any join
SELECT dtsl.id,dtsl.deal_transaction_id,dtsl.transaction_status_id FROM deals_transaction_status_log as dtsl
WHERE dtsl.id IN (
SELECT MAX(id)
FROM deals_transaction_status_log as b where dtsl.transaction_status_id=b.transaction_status_id)
AND dtsl.transaction_status_id=14
GROUP BY dtsl.deal_transaction_id
But still i am getting only one row
use correlated subquery
SELECT dtsl.id ,dtsl.deal_transaction_id,dts.id as statusId
FROM deals_transaction_status_log as dtsl
JOIN deals_transactions as dt ON dt.id=dtsl.deal_transaction_id AND dt.visitor_id=140
JOIN DEALS as d ON d.idDeal=dt.deal_id
JOIN USER as u ON d.userId=u.idUser
JOIN deals_transaction_status as dts ON dts.id=dtsl.transaction_status_id
WHERE dtsl.user_id!=140 AND dtsl.transaction_status_id=14 AND dtsl.id IN (
SELECT MAX(id)
FROM deals_transaction_status_log as b where dtsl.deal_transaction_id=b.deal_transaction_id)

Query to find the sum of the values for duplicate id in MySQL

I have a requirement :
ID Quantity
1 5
1 4
1 2
1 4
2 1
2 2
2 3
3 1
3 3
3 2
Output required :
ID Quantity
1 15
2 6
3 6
I have tried the below query on MySQL but unable to get appropriate result.
SELECT
a.id, sum(b.Quantity)
FROM
​table_name a
INNER JOIN
​table_name b
ON a.id = b.id
​ ​group by
a.id, b.Quantity
Just remove ​b.Quantity from ​group by statement. SQL fiddle
SELECT
a.id, sum(b.Quantity)
FROM
​table_name a
INNER JOIN
​table_name b
ON a.id = b.id
​ ​group by
a.id
http://sqlfiddle.com/#!9/003625/1
SELECT id, SUM(quantity)
FROM `table_name`
GROUP BY id
You don't need any join. Simply try:
select id,sum(quantity) from table_name group by id
Use GROUP BY clause along with sum() like the query below-
select ID, sum(Quantity) FROM table_name GROUP BY ID;

I want to have Sum of individual columns of two different table and show it in a single query result where customer id matches?

Create or replace view cnPointsDetailsvw
as select sum(cd.value), sum(cd1.points)
from customerdetails cd left join
customerdetails1 cd1 on cd.customerid = cd1.customerid;
The problem is that the above query is calculating sum multiple times for the column cd1.points
If table customerdetails1 has only 1 row, so why you use SUM() function?
Just use MAX().
I am confused of your table, so let me give a sample structurs and data.
table1
id points
-----------
1 10
2 20
3 40
table2
id points
-----------
1 10
1 2
1 4
2 20
3 40
3 5
And your query should be looks like this :
CREATE OR REPLACE VIEW view_name AS
SELECT t1.id,max(t1.points) as points1, sum(t2.points) as points2
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
GROUP BY t1.id
Your view should be looks like this :
id points1 points2
---------------------
1 10 16
2 20 20
3 30 45
Do the calculation in subqueries, then join their results:
SELECT
CD.sum_value, CD1.sum_points
FROM
(SELECT sum(value) as sum_value FROM customerdetails) CD
INNER JOIN (SELECT sum(points) AS sum_points FROM customerdetails1) CD1
ON 1 = 1
Please note, that SUM() returns NULL if there were no matching rows, so the subqueries will return with exactly one record -> any ON condition will be fine which results to true.
If you want to group by customers, then do the grouping in the subqueries:
SELECT
CD.customerid, CD.sum_value, CD1.sum_points
FROM
(
SELECT customerid, sum(value) as sum_value
FROM customerdetails
GROUP BY customerid
) CD
LEFT JOIN
(
SELECT customerid, sum(points) AS sum_points
FROM customerdetails1
GROUP BY customerid
) CD1
ON CD.customerid = CD1.customerid
UPDATE
To create a view (and bypass the limitation of MySQL), you have to create 3 views: 2 for the 2 subresults, 1 to join their results:
CREATE VIEW customer_value AS
SELECT SUM(value) as sum_value FROM customerdetails;
CREATE VIEW customer_points AS
SELECT SUM(points) as sum_points FROM customerdetails1;
CREATE VIEW cnPointsDetailsvw AS
SELECT cv.sum_value, cp.sum_points
FROM customer_value cv
INNER JOIN customer_points cp
ON 1=1;

getting latest timestamp from 2 joined tables for each row output in select statement

I have 3 tables as shown below. I want to get a list of member names, ids, together with the latest activity time for each of them, given a particular member name search term.
This 'latest activity time' is the latest time from comparing both the game_record and the eating_record tables.
The desired output is also given below.
member_info table:
name m_id
---- ----
john 1
doe 2
johnson 3
game_record:
time_of_activity game_id m_id
---------------- ------- -----
2013-01-20 23:01:00 1 3
2013-01-20 23:01:07 4 1
2013-01-20 23:01:06 1 2
2013-01-20 23:01:05 3 1
eating_record:
time_of_activity food_id m_id
---------------- ------- -----
2013-01-20 23:01:04 1 1
2013-01-20 23:01:03 4 1
2013-01-20 23:01:02 1 2
2013-01-20 23:01:01 3 3
desired output when search term is 'john':
name m_id latest_time
---- ---- -----------
john 1 2013-01-20 23:01:07
johnson 3 2013-01-20 23:01:01
What I have tried so far:
I can get the first 2 columns by the following query:
select name,
m_id
from
member_info
where
name like "john%";
And I can get the latest_time for a given member by the following query, but I'm not sure how to merge this second query with the first one to get my desired output.
select greatest ((select
max(time_of_activity)
from
game_record
join
member_info on game_record.m_id = member_info.m_id
where member_info.name = "john"),
(select
max(time_of_activity)
from
eating_record
join
member_info on eating_record.m_id = member_info.m_id
where member_info.name = "john"));
SQL Fiddle for this is available at: http://sqlfiddle.com/#!2/b70d0/3
P.S. The tables game_record and eating_record have other columns that are particular to games/food that are not included here, since I wanted to simplify and isolate the part where I needed help.
Thank you! :)
You could use a UNION ALL query to get the eating_record and game_record times in the same column, then apply an aggregate function to get the max time:
select m.name,
m.m_id,
max(time_of_activity) latest_time
from member_info m
left join
(
select time_of_activity, m_id
from game_record
union all
select time_of_activity, m_id
from eating_record
) g
on m.m_id = g.m_id
where m.name like 'john%'
group by m.name, m.m_id
See SQL Fiddle with Demo.
This could also be written with aggregates in the subquery:
select m.name,
m.m_id,
max(time_of_activity) latest_time
from member_info m
left join
(
select max(time_of_activity) time_of_activity, m_id
from game_record
group by m_id
union all
select max(time_of_activity) time_of_activity, m_id
from eating_record
group by m_id
) g
on m.m_id = g.m_id
where m.name like 'john%'
group by m.name, m.m_id;
See SQL Fiddle with Demo
My solution is to aggregate each of the tables (games and eating) by member id to get the latest time. Then, join these together and use the greatest() function to get the latest time:
select mi.*, greatest(gr.maxtime, er.maxtime) as latest_time
from member_info mi left outer join
(select m_id, MAX(time_of_activity) as maxtime
from game_record gr
group by m_id
) gr
on gr.m_id = mi.m_id left outer join
(select m_id, MAX(time_of_activity) as maxtime
from eating_record er
group by m_id
) er
on er.m_id = mi.m_id

mySQL - GROUP BY but get the most recent row

I've got a budget table:
user_id product_id budget created
-----------------------------------------------------------------
1 1 300 2011-12-01
2 1 400 2011-12-01
1 1 500 2011-12-03
2 2 400 2011-12-04
I've also got a manager_user table, joining a manager with the user
user_id manager_id product_id
------------------------------------
1 5 1
1 9 2
2 5 1
2 5 2
3 5 1
What I'd like to do is grab each of the user that's assigned to Manager #5, and also get their 'budgets'... but only the most recent one.
Right now my statement looks like this:
SELECT * FROM manager_user mu
LEFT JOIN budget b
ON b.user_id = mu.user_id AND b.product_id = mu.product_id
WHERE mu.manager_id = 5
GROUP BY mu.user_id, mu.product_id
ORDER BY b.created DESC;
The problem is it doesn't pull the most recent budget. Any suggestions? Thanks!
To accomplish your task you can do as follows:
select b1.user_id,
b1.budget
from budget b1 inner join (
select b.user_id,
b.product_id,
max(created) lastdate
from budget b
group by b.user_id, b.product_id ) q
on b1.user_id=q.user_id and
b1.product_id=q.product_id and
b1.created=q.lastdate
where b1.user_id in
(select user_id from manager_user where manager_id = 5);
I'm assuming here that your (user_id, product_id, created) combination is unique.
For what it's worth, here's the code that returned what I was looking for:
SELECT DISTINCT(b1.id),mu.user_id,mu.product_id,b1.budget,b1.created
FROM budget b1
INNER JOIN (
SELECT b.user_id, b.product_id, MAX(created) lastdate
FROM budget b
GROUP BY b.user_id, b.product_id) q
ON b1.user_id=q.user_id AND
b1.product_id=q.product_id AND
b1.created=q.lastdate
RIGHT JOIN manager_user mu
ON mu.user_id = b1.user_id AND
mu.product_id = b1.product_id
WHERE mu.manager_id = 5;
Thanks for the help Andrea!