I'm just 3 months of experience in MySQL. Here I'm trying to generate a report based on log and part table. When trying to join the "Part" table twice, the "Log" table Quantity gets doubled. Kindly let me know where I'm doing wrong.
Log Table
Part Table
Expected Report
Query Used
SELECT
report.*,
(SUM(report.quantity)) AS totalQuantity,
normalPart.price AS normalPrice,
premiumPart.price AS premiumPrice
FROM
log AS report
LEFT JOIN
(SELECT
*
FROM
part AS normalPart
WHERE
normalPart.type = 'normal'
GROUP BY normalPart.partNumber , normalPart.genId) AS normalPart ON report.partNumber = normalPart.partNumber
AND report.genId = normalPart.genId
AND normalPart.cat = report.fromCat
LEFT JOIN
(SELECT
*
FROM
part AS premiumPart
WHERE
premiumPart.type = 'premium'
GROUP BY premiumPart.partNumber , premiumPart.genId) AS premiumPart ON report.partNumber = premiumPart.partNumber
AND report.genId = premiumPart.genId
AND premiumPart.cat = report.toCat;
Query Result
This answers the original version of the question.
Aggregate before you join:
select l.*, p.normal_price, p.premium_price
from (select genid, partnumber, sum(quantity) as quantity
from log
group by genid, partnumber
) l left join
(select partnumber, genid,
max(case when type = 'normal' then price end) as normal_price,
max(case when type = 'premium' then price end) as premium_price
from part
group by partnumber, genid
) p
on p.partnumber = l.partnumber and p.genid = l.genid
Related
i have one tables attendance
main table
i created 2 views from attendance table attend view and leaved view
view:attend
select `dbtest`.`employee`.`empId` AS `empId`,`dbtest`.`attendance`.`timeAttendnace` AS `timeAttendnace` from (`dbtest`.`employee` left join `dbtest`.`attendance` on(`dbtest`.`attendance`.`empId` = `dbtest`.`employee`.`empId` and `dbtest`.`attendance`.`statusAttendnace` = 'In'))
view:leaved
select `dbtest`.`employee`.`empId` AS `empId`,`dbtest`.`attendance`.`timeAttendnace` AS `timeAttendnace` from (`dbtest`.`employee` left join `dbtest`.`attendance` on(`dbtest`.`attendance`.`empId` = `dbtest`.`employee`.`empId` and `dbtest`.`attendance`.`statusAttendnace` = 'Out'))
after that i used this code to merge attend and leaved view
select `attend`.`empId` AS `empId`,`attend`.`timeAttendnace` AS `clockIn`,`leaved`.`timeAttendnace` AS `clockOut` from (`dbtest`.`attend` join `dbtest`.`leaved` on(`attend`.`empId` = `leaved`.`empId`)) group by `attend`.`timeAttendnace` order by `attend`.`empId`
the result was like this
result
i need each employee has attend time and leaved time in same day
This following query will return you employee wise daily In and Out Time in a single row.
SELECT
cast(TimeAttendence AS DATE),
empid,
MIN(CASE WHEN StatusAttendence = 'In' THEN TimeAttendence END) InTime,
MAX(CASE WHEN StatusAttendence = 'Out' THEN TimeAttendence END) OutTime
FROM main_table
GROUP BY cast(TimeAttendence AS DATE),empid
I have a mysql query which is to return the only 1 record that need to cross multiple table. However, the mysql query is slow when executing.
Query:
SELECT *,
(SELECT TreeName FROM sys_tree WHERE TreeId = Mktg_Unit_Booking.ProjectLevelId) AS PhaseName,
(CASE WHEN ProductType = 'U' THEN (SELECT UnitNo FROM prop_unit pu WHERE pu.UnitId = mktg_unit_booking.UnitId)
ELSE (SELECT BayNo FROM prop_car_park pcp WHERE pcp.CarParkId = UnitId) END) AS UnitNo,
(SELECT CustomerName FROM mktg_customer mc WHERE mc.CustomerId = mktg_unit_booking.CustomerId) AS CustomerName
FROM Mktg_Unit_Booking
WHERE IsDeleted <> '1' AND IsApproved = '1'
AND UnitId = 1110 AND ProductType = 'U'
ORDER BY UnitNo
I have run EXPLAIN in the query and I got this:
Any other suggestion on how to improve the speed of the query?
Thank you!
you are doing the cross product, instead of that you should use join.
Don't use sub-queries in select statement instead use proper join on Mktg_Unit_Booking in after from statement.
you query should something look like :
select
sys_tree.TreeName AS PhaseName,
case
WHEN Mktg_Unit_Booking.ProductType = 'U' then prop_unit.UnitNo
else prop_car_park.BayNo
end as UnitNo,
mktg_customer.CustomerName AS CustomerName
FROM Mktg_Unit_Booking
left join sys_tree on sys_tree.TreeId = Mktg_Unit_Booking.ProjectLevelId
left join prop_unit on prop_unit.UnitId = Mktg_Unit_Booking.UnitId
left join prop_car_park on prop_car_park.CarParkId = Mktg_Unit_Booking.UnitId
left join mktg_customer on mktg_customer.CustomerId = Mktg_Unit_Booking.CustomerId
WHERE IsDeleted <> '1' AND IsApproved = '1'
AND UnitId = 1110 AND ProductType = 'U'
ORDER BY UnitNo;
I have assumed that each table consists of only 1 matching tuple. If there are more then your logic needs to be modified.
I'm trying to Sum column only if id is different.
I tried like this, but it is not working:
SUM(CASE WHEN
DISTINCT empLeaves.ApprovedLeaveID
THEN empLeaves.TotalLeavesTaken END) AS Total
What Would be the proper way to SUM it?
Here is the total query, I am working on:
SELECT
E.employee_id AS EmployeeID,
E.employee_code AS EmployeeCode,
E.full_name AS EmployeeName,
empLeaves.LeavesFromDate,
empLeaves.LeavesToDate,
-- COUNT(empLeaves.ApprovedLeaveID) AS TotalApprovedApplications,
ATT.`in_date` AS InDate,
ATT.`out_date` AS OutDate,
SUM(CASE WHEN DISTINCT empLeaves.ApprovedLeaveID THEN empLeaves.TotalLeavesTaken END) AS Total
FROM employee E
LEFT JOIN `attendence` ATT ON ATT.`employee_id` = E.`employee_id`
LEFT JOIN (
SELECT
LA.`leave_approval_id` AS ApprovedLeaveID,
E.`employee_id` AS EmployeeID,
LA.`approved_from` AS LeavesFromDate,
LA.`approved_to` AS LeavesToDate,
DATEDIFF(LA.approved_to,approved_from) AS TotalLeavesTaken
FROM leave_application APP
INNER JOIN leave_approval LA
ON LA.`leave_application_id` = APP.`application_id` AND LA.`trashed` = 0 AND LA.`status` = 2
INNER JOIN employee E
ON E.`employee_id` = APP.`employee_id` AND E.`trashed` = 0 AND E.`enrolled` = 1
INNER JOIN ml_leave_type MLLT
ON MLLT.`ml_leave_type_id` = APP.`ml_leave_type_id` AND MLLT.`trashed` = 0
) empLeaves ON E.`employee_id` = empLeaves.EmployeeID
WHERE
E.`enrolled` = 1 AND E.`trashed` = 0
GROUP BY
E.`employee_id`,empLeaves.EmployeeID
When which ID is different from what?
In general, when you have a value in a field and you want to add them together except for those in a particular set of rows, you simply set the unwanted values to 0:
sum( case otherfield when somevalue then row.field else 0 end ) as SumOfValues
So when otherfield shows that this is the row you want included in the total, you expose the field you want to add (row.field in this example). Otherwise, you expose a zero. Of course, if the value you're testing is to find the rows you don't want in the total, just put the zero after the then and the field after the else.
I've been stuck on this problem for far too long.
I have to merge 3 tables and do some counting of distinct values.
I have 3 tables
1.User_me
profileId( String )
responded( int 1 or 0)
2.Profiles
profileId ( String )
idLocation ( int )
3.lookup_location
id ( int )
location (String )
I can join User_me and Profiles ON User_me.profileId = Profiles.profileId
I can join Profiles and lookup_location ON Profiles.idLocation = lookup_location.id
Under Profiles I need to count the number of distinct values for idLocation where User_me.profileId = Profiles.profileId
I also need to count the number of Profiles.idLocation that have User_me.responded = 1
I have this:
SELECT lookup.location, count(*) as total
FROM User_me user
JOIN Profiles
ON user.profileId= profiles.profileId
JOIN lookup_location lookup
ON profiles.idLocation = lookup.id
GROUP BY profiles.idLocation
but I still need to have the column giving me the count where User_me.responded = 1
Something like:
SELECT lookup.location, count(*) as total, count(*) responded
If I'm understanding your question correctly, you can you a case statement in the count aggregate:
SELECT lookup.location, count(*) as total,
count(case when user.responded = 1 then 1 end) as responded
FROM User_me user
JOIN Profiles
ON user.profileId= profiles.profileId
JOIN lookup_location lookup
ON profiles.idLocation = lookup.id
GROUP BY profiles.idLocation
Since you're using MySQL, you can also use something like sum(user.responded = 1).
i have a table with data title and date of the data inserted.
and right now i want to do count to make the statistic out of it.
can i do multiple count in one sql statement?
like from, the column date, i want to count how many on this month, and how many in this year, until month selected. is it possible? if yes, how?
this is what i have come up, for now.
SELECT a.trigger_type_code
, c.trigger_name
, COUNT(*) AS number
FROM issue_trigger a
INNER JOIN cs_issue b
ON b.issue_id = a.issue_id
INNER JOIN ref_trigger_type c
ON c.trigger_type_code = a.trigger_type_code
WHERE MONTH(b.created_date) = '05'
AND YEAR(b.created_date) = '2011'
GROUP BY trigger_type_code,trigger_name
by this is only for one count.help.:(
You could use a case:
select sum(case when MONTH(b.created_date) = '05'
AND YEAR(b.created_date) = '2011' then 1 end) as Count_2011_05
, sum(case when YEAR(b.created_date) = '2011'
then 1 end) as Count_2011
from ... etc ...
I think you could go like this:
SELECT
a.trigger_type_code,
c.trigger_name,
COUNT(MONTH(b.created_date) < 5 OR NULL) AS before_the_month,
COUNT(MONTH(b.created_date) = 5 OR NULL) AS in_the_month
FROM issue_trigger a
INNER JOIN cs_issue b
ON b.issue_id = a.issue_id
INNER JOIN ref_trigger_type c
ON c.trigger_type_code = a.trigger_type_code
WHERE YEAR(b.created_date) = 2011
GROUP BY a.trigger_type_code, c.trigger_name