which is the best / efficient way to execute MySQL query - mysql

1st approach :-
SELECT
clipComment.commentId,
clipComment.commentedBy,
clipComment.clipId AS commentTypeId,
'clip' AS commentType,
clipComment.commentDescription,
clipComment.commentCreatedDateTime,
clipComment.commentModifiedDateTime,
clipComment.commentLikeCount,
userProfile.userName,
userProfile.firstName,
userProfile.LastName,
userProfile.profilePicUrl,
userProfile.themeForeground,
userProfile.themeBackground,
IF(derCommentLike.commentId = clipComment.commentId,
1,
0) likedByMe
FROM
clipComment
LEFT JOIN
(SELECT
*
FROM
clipCommentLikes
WHERE
commentLikedBy = 16) derCommentLike
ON
derCommentLike.commentId = clipComment.commentId
LEFT JOIN
userProfile
ON
userProfile.userId = clipComment.commentedBy
WHERE
clipComment.clipId = 141
2nd approach :-
SELECT
clipComment.commentId,
clipComment.commentedBy,
clipComment.clipId AS commentTypeId,
'clip' AS commentType,
clipComment.commentDescription,
clipComment.commentCreatedDateTime,
clipComment.commentModifiedDateTime,
clipComment.commentLikeCount,
userProfile.userName,
userProfile.firstName,
userProfile.LastName,
userProfile.profilePicUrl,
userProfile.themeForeground,
userProfile.themeBackground,
IF( derCommentLike.commentId = clipComment.commentId , 1 , 0 ) AS likedByMe
FROM
(SELECT
*
FROM
clipCommentLikes
WHERE
commentLikedBy = 16) derCommentLike
RIGHT OUTER JOIN clipComment
ON derCommentLike.commentId = clipComment.commentId
RIGHT OUTER JOIN userProfile
ON clipComment.commentedBy = userProfile.userId
WHERE
clipComment.clipId = 141
both query returns same result, but just want to know which approach should i follow & which one is more efficient to follow. record set will contain millions of record, so i want to use best way. or i am doing work then please correct me. thank you in advance.
explain statement 1st approach
explain statement 2nd approach
explain statement 1st approach

IF(derCommentLike.commentId = clipComment.commentId, 1, 0) likedByMe
...
LEFT JOIN
(SELECT *
FROM clipCommentLikes
WHERE commentLikedBy = 16
) derCommentLike
ON derCommentLike.commentId = clipComment.commentId
-->
( EXISTS SELECT * FROM clipCommentLikes
WHERE commentId = clipComment.commentId
) AS likedByMe
Explanation:
JOIN ( SELECT ... ) has no index to make it efficient
LEFT JOIN ( ... ) begs for evaluating the subquery after the left table, thereby begging for the subquery to be evaluated repeatedly.
SELECT * (in your subquery) is gathering lots of stuff that is not used. (SELECT * in EXISTS does not mean to fetch everything; the * is just a place holder.)
EXISTS evaluates to 1 (true) or 0 (false), which seems to be what you want.

Related

Problems Summing up result of MySQL query

The following query returns what is displayed in the attached image.
What I thought would be very simple has turned out to be very complex. All I simply want to do is now total up the result into one row and column. In this case the sum would be 161. How do I do this? I've literally tried everything. I hope I've provided enough information.
SELECT
TRUNCATE
(
SUM(
`assignment`.`percentage_achieved` *(
SELECT
`unitComponentWeighting`.`percentage_weighting` / 100
FROM
`unitComponentWeighting`
WHERE
`assignment`.`assignment_component_id` = `unitComponentWeighting`.`component_lookup_id`
LIMIT 1
)
),
2
) AS `unit_percentage_grade`
FROM
`assignment`
LEFT JOIN `assignmentType` ON `assignment`.`assignment_type_id` = `assignmentType`.`id`
LEFT JOIN `assignmentComponentLookup` ON `assignmentComponentLookup`.`id` = `assignment`.`assignment_component_id`
LEFT JOIN `unit` ON `unit`.`id` = `assignment`.`unit_id`
LEFT JOIN `assignmentSequence` ON `assignmentSequence`.`id` = `assignment`.`assignment_sequence_id`
LEFT JOIN `yearGroup` ON `yearGroup`.`id` = `unit`.`year_group_id`
WHERE
`yearGroup`.`id` = 1
GROUP BY
`assignment`.`unit_id`
try removing this part
" GROUP BY
assignment.unit_id "

SQL - Divide One Query by Another

I am trying to create a query which returns the workout percentage completion...
Workout Percentage Completion =
((Sum of LogEntries WHERE date = IN list of dates and WorkoutID =1 ) /
(Sum of all set numbers WHERE WorkoutID = 1))
x 100
Below is what I currently have, at the moment it is only returning the result of the first query.
What should I change for the query to run correctly?
SELECT
(
(
SELECT COUNT(LogEntriesID)
FROM LogEntriesTable
LEFT JOIN ExerciseWorkoutJunctionTable
ON ExerciseWorkoutJunctionTable.ExerciseWorkoutJunctionID =
LogEntriesTable.JunctionID
WHERE LogEntriesTable.date IN (
"14-05-2020", "15-05-2020", "16-05-2020", "17-05-2020",
"18-05-2020", "19-05-2020", "20-05-2020"
)
AND ExerciseWorkoutJunctionTable.WorkoutID = 1
) / (
SELECT sum(SetNumber)
FROM ExerciseWorkoutGoalsTable
LEFT JOIN ExerciseWorkoutJunctionTable
ON ExerciseWorkoutJunctionTable.ExerciseWorkoutJunctionID =
ExerciseWorkoutGoalsTable.JunctionID
WHERE ExerciseWorkoutJunctionTable.WorkoutID = 1
)
)
Your first SELECT statement is doing an OUTER JOIN but then you have a WHERE clause that is selecting non-NULL values from the ExerciseWorkoutJunctionTable table, so I suspect you might as well be doing an INNER JOIN.
When you have two queries, try:
SET #sum = (SELECT SUM(SetNumber) etc ....);
SELECT (COUNT(LogEntriesID) * 100 / #sum) AS percentage
FROM etc.
If you are using MySQL >= 8.0 you should be able to use window functions like this which breakdown your query into more readable sections.
with entries as (
SELECT COUNT(LogEntriesID) as log_entry_count
FROM LogEntriesTable as l
LEFT JOIN ExerciseWorkoutJunctionTable as e ON
e.ExerciseWorkoutJunctionID = l.JunctionID
WHERE l.date IN ("14-05-2020","15-05-2020","16-05-2020","17-05-2020","18-05-2020","19-05-2020","20-05-2020")
AND e.WorkoutID = 1
),
sets as (
SELECT sum(SetNumber) as set_sum
FROM ExerciseWorkoutGoalsTable as eg
LEFT JOIN ExerciseWorkoutJunctionTable ej
ON ej.ExerciseWorkoutJunctionID = eg.JunctionID
WHERE ej.WorkoutID = 1
)
select ((select log_entry_count from entries) / (select set_sum from sets)) * 100 as workout_completion_pct

Converting select statement to update (including exists & having)

Im trying to change some records in my database but sadly my sql knowledge is a bit limited. After googling and reading stuff online I have managed to write a select statement in which i can find the records that I want to update but i dont understand the logic to write the update statement to do it. I have to make several similar update statements so I hope this one I can figure out the rest myself
This is the select statement I have:
SELECT
MG.id,
MG.status,
MG.fin,
MG.execDateTime,
EXISTS
(
SELECT 1
FROM Mtask T
JOIN MTaskHis TH ON TH.t_id= T.id
WHERE T.tg_id = MG.id
AND YEAR(TH.dateTime) = 2019
) AS hasExecStart,
NMG.id,
NMG.execDateTime,
EXISTS
(
SELECT 1
FROM Mtask T
JOIN MTaskHis TH ON TH.t_id = T.id
WHERE T.tg_id = NMG.id
AND YEAR(TH.dateTime) = 2019
) AS hasExecNext
FROM Management_Group MG
JOIN MT_Groupman MTGM ON
MG.tgm_id = MTGM.id
LEFT JOIN Management_Group NMG ON MTGM.id =
NMG.tgm_id AND YEAR(NMG.execDateTime) = 2019
JOIN Management_Man MM ON MTGM.man_id = MM.id
JOIN Location L ON MM.location_id = L.id
WHERE L.org_id = 69
AND MG.stat != 'DELETED'
AND YEAR(MG.execDateTime) = 2018
AND MM.Type= 9
AND MG.fin != 1
AND EXISTS
(
SELECT 1
FROM Mtask T
WHERE T.tg_id = MG.id
AND T.stat = 'execution'
)
HAVING hasExecNext = 0 AND hasExecStart = 1
I know standard updates in sql:
UPDATE <TABLENAME>
SET <fieldName> = <value>
WHERE <conditons>
Except I do not know how to convert this select statement I have made into an update statement, reason for that is:
- Where do I put the exist alias in the update statement
- I also dont understand when or where to put all the JOINS in the from statement
- What about the HAVING
What is the best way to do joined updates like this?
In an UPDATE you can join the table you want to update to a sub-query that contains your current query.
UPDATE YourTable t
JOIN
(
<< add your query here >>
) q ON q.SomeKeyField = t.SomeKeyField
SET t.FieldName = q.FieldNameFromSubquery,
t.OtherFieldName = q.OtherFieldNameFromSubquery

Include another select column based on data - MySQL

How do I include SUM((pm.Quantity * bl.TotalQty)) AS NextBOMItemCount WHERE projectbomlist.ParentPartNum = bl.PartNum?
The data should not be changed, the same data should be retrieved, the however additional column has to be included.
VIEW: `NEWprojectBOMItemCount
select
`pm`.`ProjectCode` AS `ProjectCode`,
`bl`.`PartNum` AS `PartNum`,
sum((`pm`.`Quantity` * `bl`.`TotalQty`)) AS `BOMItemCount`,
`bl`.`mp` AS `mp`,
`p`.`complete` AS `complete`,
`bl`.`RMInd` AS `RMInd`,
`bl`.`M_PartNum` AS `M_PartNum`
from
(
(`projectmachine` `pm` join `projectbomlist` `bl`)
join `projects` `p`
)
where
(
(`pm`.`MachineListID` = `bl`.`MachineListID`)
and (`pm`.`ProjectCode` = `bl`.`ProjectCode`)
and (`pm`.`ProjectCode` = `p`.`ProjectCode`)
and (`p`.`AfterProjectHeirarchyInd` = 'Y')
)
and and pm.ProjectCode = 'AB212323'
group by
`pm`.`ProjectCode` ,
`bl`.`PartNum`
order by
`pm`.`ProjectCode` ,
`bl`.`PartNum`
Or, another option can be, please consider above view used in below query, please suggest changes to the below query as shown above (repeating here)
`sum((pm.Quantity * bl.TotalQty)) AS NextBOMItemCount where projectbomlist.ParentPartNum = bl.PartNum` - in place of `(select-NextBOMItemCount)`?
Please see PBLH.ParentPartNum is the column that I should compare with BL.ProjectCode to get NextBOMItemCount value.
QUERY calling view: NEWprojectBOMItemCount
Select
BL.PartNum PartNumber,
PBLH.ParentPartNum NextBOM,
(select-NextBOMItemCount),
BOMItemCount TotalQty,
PL.Description,
BL.MP as PartType,
PL.Vendor,
PL.QBType
from
NEWprojectBOMItemcount BL,
bomwiz.partslist PL,
bomwiz.projectbomlistheirarchy PBLH
Where
BL.PartNum = PL.PartNum
And BL.PartNum = PBLH.PartNum
And BL.ProjectCode = PBLH.ProjectCode
And BL.projectCode = 'AB212323'
Order By PartNumber
I think that you are looking for conditional aggregation. Your requirement could be expressed as follows:
SUM(
CASE WHEN blh.ParentPartNum = bl.PartNum
THEN pm.Quantity * bl.TotalQty
ELSE 0
END
) AS NextBOMItemCount
Let me pinpoint other issues with your query:
you have unwanted parentheses all around, and I am suspicious about the syntax of the JOINs ; you need to move conditions to the ON clause of the relevant JOIN.
every non-aggregated column must appear in the GROUP BY clause - you have missing columns there
backquotes are usually not needed
Here is an updated version of the query:
SELECT
pm.ProjectCode AS ProjectCode,
bl.PartNum AS PartNum,
SUM(pm.Quantity * bl.TotalQty) AS BOMItemCount,
SUM(
CASE WHEN blh.ParentPartNum = bl.PartNum
THEN pm.Quantity * bl.TotalQty
ELSE 0
END
) AS NextBOMItemCount,
bl.mp AS mp,
p.complete AS complete,
bl.RMInd AS RMInd,
bl.M_PartNum AS M_PartNum
FROM
projectmachine AS pm
INNER JOIN projectbomlist AS bl
ON pm.MachineListID = bl.MachineListID
AND pm.ProjectCode = bl.ProjectCode
INNER JOIN join projects AS p
ON pm.ProjectCode = p.ProjectCode
AND p.AfterProjectHeirarchyInd = 'Y'
INNER JOIN projectbomlistheirarchy blh
ON bl.ProjectCode = blh.ProjectCode
WHERE
pm.ProjectCode = 'AB212323'
GROUP BY
pm.ProjectCode,
bl.PartNum,
bl.mp,
p.complete,
bl.RMInd,
bl.M_PartNum
ORDER BY
pm.ProjectCode,
bl.PartNum

MySQL How to deal with Error: Subquery returns more than 1 row?

I'm trying to write a query where it selects all records from a table where certain complex/nested criteria are met. The logic in my query I think is correct, but the problem I'm running into is the final subquery (see example) is returning more than 1 row, which is what I would expect/need. So, the problem is, how do I deal with this? Does MySQL support some kind of looping or set criterion?
SELECT c.primary_key
FROM esjp_content c
WHERE template_id = (
SELECT DISTINCT esjp_content.template_id
FROM esjp_content
INNER JOIN esjp_hw_config ON esjp_content.template_id = esjp_hw_config.proc_id
INNER JOIN esjp_assets ON esjp_hw_config.primary_key = esjp_assets.hw_config_id
WHERE
esjp_content.summary_id > 0
AND
(esjp_assets.asset_label='C001498500' OR esjp_assets.asset_label='H0065' OR esjp_assets.asset_label='L0009')
)
AND
EXISTS (SELECT 1 FROM esjp_content c2 WHERE c2.summary_id = c.primary_key)
AND
c.primary_key != (
/* This subquery returns more than 1 result. */
SELECT esjp_signoffs.content_id
FROM esjp_signoffs
INNER JOIN esjp_assets ON esjp_signoffs.asset_id = esjp_assets.primary_key
WHERE
esjp_signoffs.user_id=1
AND
(esjp_assets.asset_label='C001498500' OR esjp_assets.asset_label='H0065' OR esjp_assets.asset_label='L0009')
);
For additional details on my tables, see this other StackOverflow post I made earlier today. (This is an entirely different question.)
If i understan correctly the
c.primary_key != (
/* This subquery returns more than 1 result. */
SELECT esjp_signoffs.content_id
FROM esjp_signoffs
INNER JOIN esjp_assets ON esjp_signoffs.asset_id = esjp_assets.primary_key
WHERE
esjp_signoffs.user_id=1
AND
(esjp_assets.asset_label='C001498500' OR esjp_assets.asset_label='H0065' OR esjp_assets.asset_label='L0009')
);
return more then a row .. you could use not in ..
c.primary_key not in (
or
inner join ( ..... ) t on c.primary_key != t.the_column_you_need