Join three tables with group by to get counts - mysql

I have three tables- Ad(Id,AgentId,AdDesc,AdTitle,EmailId,ADate), AdComment(ComId,email,comment,AdId) and MyLikes(LikeId,email,AdId). Here I have to join three tables and display Ad table's all fields along with number of comments from AdComment table based on every Ad Id(Ad.Id=AdComment.AdId) and number of likes from MyLikes based on a given email for every Ad Id(Ad.Id=MyLikes.AdId).
When I just joined Ad and Ad comment I used -
SELECT * , (
SELECT COUNT( c.AdId )
) AS ComCount
FROM Ad a
LEFT JOIN AdComment c ON a.Id = c.AdId
GROUP BY a.Id
ORDER BY a.Id DESC
This is working fine.
Also when I joined Ad and MyLikes I used -
SELECT a.Id, (
SELECT COUNT( * )
FROM MyLikes m
WHERE (
m.email = 'nik#gmail.com'
AND m.AdId = a.Id
)
) AS MyCount
FROM Ad a
LEFT JOIN MyLikes m ON a.Id = m.AdId
GROUP BY a.Id
This is working fine.
But when I tried all three table join it is not working, gives some wrong value for comment count.
For this I used-
SELECT a.Id,a.AgentId,a.EmailId,a.AdTitle,a.AdDesc, (
SELECT COUNT(m.AdId)
FROM MyLikes m
WHERE (
m.email = 'nik#gmail.com'
AND m.AdId = a.Id
)
) AS MyCount,(
SELECT COUNT( c.AdId )
) AS ComCount
FROM Ad a
LEFT JOIN MyLikes m ON a.Id = m.AdId LEFT JOIN AdComment c ON a.Id = c.AdId
GROUP BY a.Id ORDER BY a.Id DESC
How can I join these three tables and get the desired result.

Assuming I'm understanding your question correctly, here's one option using subqueries to count your data in the joins instead:
select a.Id, a.AgentId, a.EmailId, a.AdTitle, a.AdDesc,
b.AdIdCount, c.AdIdCount
from Ad a
left join (select AdId, count(*) AdIdCount
from AdComment
group by AdId) b ON a.Id = b.AdId
left join (select AdId, count(*) AdIdCount
from MyLikes
where email = 'nik#gmail.com'
group by AdId) c ON a.Id = c.AdId
If you prefer correlated subqueries, then this should work:
select a.Id, a.AgentId, a.EmailId, a.AdTitle, a.AdDesc,
(select count(*)
from AdComment b
where a.Id = b.AdId),
(select count(*)
from MyLikes c
where c.email = 'nik#gmail.com' and
a.Id = c.AdId)
from Ad a

Assuming that LikeID and ComId are the unique id fields of the MyLikes and AdComment tables then you should be able to just use a pair of joins and count the distinct id fields from each table:-
SELECT a.Id,
a.AgentId,
a.EmailId,
a.AdTitle,
a.AdDesc,
COUNT(DISTINCT m.LikeId) AS MyCount,
COUNT(DISTINCT c.ComId) AS ComCount
FROM Ad a
LEFT OUTER JOIN MyLikes m ON m.email = 'nik#gmail.com' AND a.Id = m.AdId
LEFT JOIN AdComment c ON a.Id = c.AdId

Related

mysql query taking long time to respond

SELECT t.id
, t.department
, t.owner
, t.client
, u.username as owner_name
, c.name as catagery
, d.dept_name as deptname
, t.periority
, t.status
, t.estimate
, cl.takeaway_name
from tbl_task t
JOIN tbl_user u
ON u.id = t.owner
JOIN tbl_task_catagery c
ON c.id = t.catagery
JOIN tbl_department d
ON d.id = t.department
JOIN tbl_clients cl
ON cl.id = t.client
and t.status = 0
and (t.id in (select task_id
from tbl_task_note tn
where tn.user_id = '69'
and tn.id in (select max(id)
from tbl_task_note tt
where tt.task_id = tn.task_id
)
)
)
order by t.id
Note : The above query is used for check users hold tasks. tbl_task_note table is used for check task notes for separate users task.
With this query you will get the task that have the last task_note registered, including the user, departament, client, and some other.
If it is what you need you can just do this.
select
t.id,
t.department,
t.owner,
t.client,
u.username as owner_name,
c.name as catagery,
d.dept_name as ptname,
t.periority,
t.status,
t.estimate,
cl.takeaway_name
from tbl_task t
INNER JOIN tbl_user u ON u.id=t.owner
INNER JOIN tbl_task_catagery c ON c.id=t.catagery
INNER JOIN tbl_department d ON d.id=t.department
INNER JOIN tbl_clients cl ON cl.id=t.client and t.status=0
INNER JOIN (select * from tbl_task_note where id =
(select max(id) from tbl_task_note)
)tb on tb.task_id = t.id
order by t.id
That way you can improve your query.
You shoud also ensure that your keys compared are foreign keys to get faster consults.

Get Value from INNER JOIN 3 table with LASTEST RECORD from each table

I get problem to get value from some of tables. You can see picture below, I wanna get row what I block with red color.
I try with code below
SELECT p.id,
p.email,
p.name,
p.lastname,
p.gender,
ex.startwork,
ex.endwork,
e.degree,
e.majority,
j.division
FROM job_jobseeker AS p
INNER JOIN job_experience AS ex
ON p.email = (SELECT ex.email
FROM job_experience
ORDER BY ex.id DESC
LIMIT 1)
INNER JOIN job_education AS e
ON p.email = (SELECT e.email
FROM job_education
ORDER BY ex.id DESC
LIMIT 1)
INNER JOIN job_applying AS j
ON p.email = (SELECT j.email
FROM job_applying
ORDER BY ex.id DESC
LIMIT 1)
You need correlated sub-queries.
Find the latest id for each email in all the three tables
SELECT startwork,
endwork,
email
FROM job_experience a
WHERE a.id = (SELECT Max(b.id)
FROM job_experience b
WHERE a.email = b.email)
The above query will find the latest id for each email in job_experience table. Do the same for other two tables as well, then join the result with job_jobseeker table to get the result.
SELECT p.id,
p.email,
p.name,
p.lastname,
p.gender,
ex.startwork,
ex.endwork,
e.degree,
e.majority,
j.division
FROM job_jobseeker AS p
INNER JOIN (SELECT startwork,
endwork,
email
FROM job_experience a
WHERE a.id = (SELECT Max(b.id) FROM job_experience b
WHERE a.email = b.email)) AS ex
ON p.email = ex.email
INNER JOIN (SELECT email, //Just called column without initialize
degree,
majority
FROM job_education a
WHERE a.id = (SELECT Max(b.id) FROM job_education b
WHERE a.email = b.email)) AS e
ON p.email = e.email
INNER JOIN (SELECT email, //Just called column without initialize
division
FROM job_applying a
WHERE a.id = (SELECT Max(b.id) FROM job_applying b
WHERE a.email = b.email)) AS j
ON p.email = j.email

Calculate within multiple where clause mysql

I have database structure as shown in the picture (it's simplified)
so now i want to calculate products in all stocks so that the result looked like (this assuming that store table has two records of store1 and store2):
if this is not possible this format is acceptable too
The main problem is that i can't figure out how should i calculate current stock for each store.
the curent stock for each stock = sum of all productin this stock
- sum of all productout this stock
+ sum of all producttransfer with transfertype=0 in this stock
- sum of all producttransfer with transfertype=1 in this stock
so how should i calculate it for each store when store number is not fixed
I think it should work, I'm writting it on the go so can't be 100% sure and there might be some typos
select A1.ProductID, A1.storehouseID, (SUM(IN)-SUM(OUT)) as quantity
from (
Select AD.productID, A.storehouseID, SUM(AD.Quantity) as IN
from actions A inner join productIN PI on A.ID = PI.ID
inner join actiondetails AD on PI.ID = AD.ID
group by AD.productID, A.storehouseID
UNION
select AD.ProductID, A.storehouseID, SUM(AD.Quantity)
from actions A inner join ProductTransfers T on A.ID = T.ID
inner join actiondetails AD on A.ID = AD.ID
where transferType = 0
group by AD.ProductID, A.storehouseID) as A1
inner join
(select AD.productID, A.storehouseID, SUM(AD.Quantity) as Out
from actions A inner join ProductOut PO on A.ID = PO.ID
inner join actiondetails AD on AD.ID = A.ID
group by AD.ProductID, A.storehouseID
UNION
select AD.productID, A.storehouse.ID, SUM(AD.Quantity) as Out
from actions A inner join ProductTransfers T on A.ID = T.ID
inner join actiondetails AD on AD.ID = A.ID
where TransferType = 1
group by AD.ProductID, A.storehouseID) as A2
on A1.ProductID = A2.ProductID and A1.storehouseID = A2.storehouseID
group by A1.ProductID, A1.StorehouseID

sql select distinc where max date

I have 3 tables "maintenances", "cars", "users" . I want to select all data from table maintenance with a distinct car_id and the last record for each distinct (based on max maintenance_date)
SELECT
m. * , u.username, c.Model, c.Make, c.License, c.Milage, COUNT( m.process_id ) AS count_nr
FROM
maintenances AS m
LEFT JOIN users AS u ON u.id = m.user_id
LEFT JOIN cars AS c ON c.id = m.car_id
WHERE
maintenance_date = (SELECT MAX(maintenance_date) FROM maintenances WHERE car_id = m.car_id)
The problem is that this query returns only one record which has the max date from all records. I want all records (distinct car_id and from records with the same car_id to display only values for max(maintenance_date))
This is your query:
SELECT m. * , u.username, c.Model, c.Make, c.License, c.Milage, COUNT( m.process_id ) AS count_nr
----------------------------------------------------------------^
FROM maintenances AS m LEFT JOIN
users AS u
ON u.id = m.user_id LEFT JOIN
cars AS c
ON c.id = m.car_id
WHERE maintenance_date = (SELECT MAX(maintenance_date) FROM maintenances WHERE car_id = m.car_id);
It is an aggregation query. Without a group by, only one row is returned (all the rows are in one group). So, add the group by:
SELECT m. * , u.username, c.Model, c.Make, c.License, c.Milage, COUNT( m.process_id ) AS count_nr
FROM maintenances AS m LEFT JOIN
users AS u
ON u.id = m.user_id LEFT JOIN
cars AS c
ON c.id = m.car_id
WHERE maintenance_date = (SELECT MAX(m2.maintenance_date) FROM maintenances m2 WHERE m2.car_id = m.car_id);
GROUP BY c.id
I also fixed the correlation statement, to be clear that it is correlated to the outer query.
add GROUP BY u.username .
WHERE
maintenance_date = (SELECT MAX(maintenance_date) FROM maintenances WHERE car_id = m.car_id)
GROUP BY u.username

Incorrect id returned on LEFT JOIN in Mysql statement

I need to get the id and timestamps of table sellers and all other columns (without knowing the column names) from these results returned from this MySql statement:
SELECT * FROM sellers a
LEFT JOIN users b ON a.user_id = b.id
LEFT JOIN country_types c ON a.country_type_id = c.id
LEFT JOIN language_types d ON a.language_type_id = d.id
WHERE a.email=?
The seller id though is incorrectly set because users, country_types, and language_types all have a value id. How can I set seller_id and seller_timestamp? I tried this but it is incorrect:
SELECT a.id seller_id, a.timestamp seller_timestamp, * FROM sellers a ...
You want this:
SELECT a.id as seller_id, a.timestamp as seller_timestamp, a.*, b.*, c.*, d.*
FROM sellers a
LEFT JOIN users b ON a.user_id = b.id
LEFT JOIN country_types c ON a.country_type_id = c.id
LEFT JOIN language_types d ON a.language_type_id = d.id
WHERE a.email=?
Im not sure but try alias, for example:
a.id AS seller_id
and etc.
In joins you can't select other columns in this way:
SELECT a.id seller_id, a.timestamp seller_timestamp, * FROM sellers a...
You need to write required column names.