Transpile mysql query to laravel style - mysql

How would I transpile this query to Laravel style
SELECT
gr.name,
p.ma_status AS status,
COUNT(p.ma_status) AS total
FROM accounts u
LEFT JOIN accounts_prop p ON p.account_id = u.account_id
AND (
SELECT j.iid
FROM accounts_prop AS j
WHERE u.account_id = j.account_id
AND j.ma_status IS NOT NULL
ORDER BY j.von DESC LIMIT 1
) = p.iid
LEFT JOIN `deprecators` gr ON gr.id = p.group_id
LEFT JOIN `deprecators` unit ON unit.id = p.unit_id
LEFT JOIN `deprecators` team ON team.id = p.team_id
WHERE p.group_id IS NOT NULL
AND u.account_status = 'A'
GROUP BY p.ma_status, gr.id
I do not have any idea how would I go with the following statement
LEFT JOIN accounts_prop p ON p.account_id = u.account_id
AND (
SELECT j.iid
FROM accounts_prop AS j
WHERE u.account_id = j.account_id
AND j.ma_status IS NOT NULL
ORDER BY j.von DESC LIMIT 1
) = p.iid

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.

Select threads from forum based on comments

I've got the following sql that will return a list of forums. Under each forum it will select the thread with the latest comment. This works fine but when a new thread hasn't got any comments, nothing is returned.
How to tackle this problem?
SELECT f.Id AS forum_id,
f.name AS forum_name,
f.slug AS forum_slug,
f.image AS forum_image,
t.Id AS thread_id,
t.title AS thread_topic,
t.unixtime AS thread_timestamp,
p.Id AS post_id,
p.content AS post_content,
p.unixtime AS post_timestamp,
(SELECT COUNT(*) FROM a_comments o WHERE o.forumID=f.Id AND o.teamId = {$teamId}) comments_count,
(SELECT COUNT(*) FROM a_threads w WHERE w.forumID=f.Id AND w.teamId = {$teamId}) threads_count
FROM a_forums f
LEFT JOIN (SELECT t2.forumID, max(COALESCE(p2.unixtime, t2.unixtime)) as ts, COUNT(p2.unixtime) as post_count
FROM a_threads t2
LEFT JOIN a_comments p2 ON p2.threadId = t2.id
GROUP BY t2.forumId) max_p ON f.id = max_p.forumId
LEFT JOIN a_comments p ON max_p.ts = p.unixtime AND p.teamId = {$teamId} AND p.deleted = 0
LEFT JOIN a_threads t ON f.Id = t.forumID AND (max_p.post_count = 0 OR p.threadId = t.ID) AND t.teamId = {$teamId} AND t.deleted = 0
ORDER BY f.id
I think you just have to change the LEFT JOIN in the first subquery to a JOIN. With the LEFT JOIN, you'll get NULL or a non-valid time for the comment. This then throws off the rest of the logic -- I think.
SELECT f.Id AS forum_id, f.name AS forum_name, f.slug AS forum_slug, f.image AS forum_image,
t.Id AS thread_id, t.title AS thread_topic, t.unixtime AS thread_timestamp,
p.Id AS post_id, p.content AS post_content, p.unixtime AS post_timestamp,
(SELECT COUNT(*) FROM a_comments o WHERE o.forumID=f.Id AND o.teamId = {$teamId}) as comments_count,
(SELECT COUNT(*) FROM a_threads w WHERE w.forumID=f.Id AND w.teamId = {$teamId}) as threads_count
FROM a_forums f LEFT JOIN
(SELECT t2.forumID, max(p2.unixtime) as ts,
COUNT(p2.unixtime) as post_count
FROM a_threads t2 JOIN
a_comments p2
ON p2.threadId = t2.id
GROUP BY t2.forumId
) max_p
ON f.id = max_p.forumId LEFT JOIN
a_comments p
ON max_p.ts = p.unixtime AND p.teamId = {$teamId} AND
p.deleted = 0 LEFT JOIN
a_threads t
ON f.Id = t.forumID AND (max_p.post_count = 0 OR p.threadId = t.ID) AND t.teamId = {$teamId} AND t.deleted = 0
ORDER BY f.id

MySQL SELECT in a UNION statement is not able to refer to the parent table

I'm trying to execute the following MySQL SELECT statement, to get the date of the last activity done against a every parent opportunity id.
The list of activities will be retrieved from 4 tables: calls, meetings, tasks, emails.
I'm getting a syntax error when I add the the condition "XXXXX.parent_id = opportunities.id" (in the inner 4 sub-SELECTS).
If I delete "XXXXX.parent_id = opportunities.id", the statements gets executed (but, of course, results are irrelevant to what I want).
Here is the code I'm tried:
SELECT
opportunities.id,
opportunities.name,
(
SELECT MAX(`last_activity_date`) FROM
(
SELECT c.date_end AS `last_activity_date`
FROM calls AS c
WHERE c.parent_type = 'Opportunities'
AND c.parent_id = opportunities.id
AND c.status IN ('Held')
AND c.deleted = '0'
UNION
SELECT m.date_end
FROM meetings AS m
WHERE m.parent_type = 'Opportunities'
AND m.parent_id = opportunities.id
AND m.status IN ('Held')
AND m.deleted = '0'
UNION
SELECT t.date_due
FROM tasks AS t
WHERE t.parent_type = 'Opportunities'
AND t.parent_id = opportunities.id
AND t.status IN ('Completed')
AND t.deleted = '0'
UNION
SELECT e.date_sent
FROM emails AS e
WHERE e.parent_type = 'Opportunities'
AND e.parent_id = opportunities.id
AND e.status IN ('sent', 'archived')
AND e.deleted = '0'
) AS `activities`
) AS "opportunities_activities"
FROM opportunities
WHERE opportunities.deleted = '0'
ORDER BY opportunities.id ASC
You can not use outer query fields inside the inner nested query as each inner query must be independent of any outer query.
Try query below for desired result.
SELECT
opportunities.id,
opportunities.name,
(
SELECT MAX(`last_activity_date`) FROM
(
SELECT c.date_end AS `last_activity_date`
FROM calls AS c
join opportunities o on c.parent_id = o.id
WHERE c.parent_type = 'Opportunities'
AND c.status IN ('Held')
AND c.deleted = '0'
UNION
SELECT m.date_end
FROM meetings AS m
join opportunities o on m.parent_id = o.id
WHERE m.parent_type = 'Opportunities'
AND m.status IN ('Held')
AND m.deleted = '0'
UNION
SELECT t.date_due
FROM tasks AS t
join opportunities o on t.parent_id = o.id
WHERE t.parent_type = 'Opportunities'
AND t.status IN ('Completed')
AND t.deleted = '0'
UNION
SELECT e.date_sent
FROM emails AS e
join opportunities o on e.parent_id = o.id
WHERE e.parent_type = 'Opportunities'
AND e.status IN ('sent', 'archived')
AND e.deleted = '0'
) AS `activities`
) AS "opportunities_activities"
FROM opportunities
WHERE opportunities.deleted = '0'
ORDER BY opportunities.id ASC

Using MAX shuffles records around

I have the following influences table:
I need to get the latest influence for a stakeholder...
I have the following query but it's mixing up the row data because MAX isn't returning a full record:
SELECT stakeholder_id, MAX(created_at) AS maxca, influence
FROM influences
WHERE
project_id = 1 AND
deleted_at IS NULL
GROUP BY stakeholder_id
You can see that the influence against that maxca and stakeholder_id should be 3, not 5.
How do I overcome this issue?
My full existing statement was this:
SELECT `stakeholders`.*, `influences`.`influence`
FROM `project_stakeholder`
INNER JOIN `stakeholders` ON `project_stakeholder`.`stakeholder_id` = `stakeholders`.`id`
INNER JOIN `stakeholder_profiles` ON `stakeholder_profiles`.`stakeholder_id` = `stakeholders`.`id`
LEFT JOIN `stakeholder_profile_tag` ON `stakeholder_profile_tag`.`stakeholder_profile_id` = `stakeholder_profiles`.`id`
LEFT JOIN `stakeholder_profile_group` ON `stakeholder_profile_group`.`stakeholder_profile_id` = `stakeholder_profiles`.`id`
LEFT JOIN `influences` ON `influences`.`stakeholder_id` = `stakeholders`.`id`
INNER JOIN `projects` ON `project_stakeholder`.`project_id` = `projects`.`id`
LEFT JOIN (
/*! This is the bit that doesn't work */
SELECT stakeholder_id, MAX(created_at) AS maxca
FROM influences
WHERE
project_id = 1 AND
deleted_at IS NULL
GROUP BY stakeholder_id
)
iu ON `iu`.`stakeholder_id` = influences.stakeholder_id AND
iu.maxca = influences.created_at
WHERE `projects`.`id` = '1'
GROUP BY `stakeholders`.`id`
This seems to work:
SELECT `stakeholders`.*, iu.influence
FROM `project_stakeholder`
INNER JOIN `stakeholders` ON `project_stakeholder`.`stakeholder_id` = `stakeholders`.`id`
INNER JOIN `stakeholder_profiles` ON `stakeholder_profiles`.`stakeholder_id` = `stakeholders`.`id`
LEFT JOIN `stakeholder_profile_tag` ON `stakeholder_profile_tag`.`stakeholder_profile_id` = `stakeholder_profiles`.`id`
LEFT JOIN `stakeholder_profile_group` ON `stakeholder_profile_group`.`stakeholder_profile_id` = `stakeholder_profiles`.`id`
INNER JOIN `projects` ON `project_stakeholder`.`project_id` = `projects`.`id`
LEFT JOIN (
select i1.*
from influences i1
join
(
SELECT stakeholder_id, MAX(created_at) AS maxca
FROM influences
WHERE project_id = 1
AND deleted_at IS NULL
GROUP BY stakeholder_id
) i2 on i1.stakeholder_id = i2.stakeholder_id
and i1.created_at = i2.maxca
) iu ON `iu`.`stakeholder_id` = stakeholders.id
WHERE `projects`.`id` = '1'
GROUP BY `stakeholders`.`id`
select i1.*
from influences i1
join
(
SELECT stakeholder_id, MAX(created_at) AS maxca
FROM influences
WHERE project_id = 1
AND deleted_at IS NULL
GROUP BY stakeholder_id
) i2 on i1.stakeholder_id = i2.stakeholder_id
and i1.created_at = i2.maxca

MySQL exclusion join when join condition is in other table

I'm trying to order a grouped resultset. Problem is that one of the join conditions references another table. Specifically, I need to select records from table_a that have the highest value within a group, but the group id is a field in a different table.
Below are some of the things I tried, in different variations. Whenever I add GROUP BY pr.id, some results that know should be in the top 3, are excluded. When I do not add it I get more than 1 record per group.
Any help much appreciated.
SELECT * FROM ivalues AS iv
INNER JOIN mprod AS p ON (p.id = iv.p_id)
INNER JOIN contact AS pr ON (pr.id = p.pr_id)
LEFT OUTER JOIN ivalues i2
ON i2.p_id = p2.id
AND i2.period = iv.period
AND i2.current = iv.current
AND i2.cert = iv.cert
AND i2.exists = iv.exists
AND iv.value > i2.value
WHERE
iv.period = 0
AND iv.current = 1
AND iv.cert = 1
AND p.type_id = 15747
AND iv.exists = 1
AND i2.id IS NULL
GROUP BY pr.id
ORDER BY iv.value ASC
LIMIT 10;
SELECT * FROM ivalues AS iv
INNER JOIN mprod AS p ON (p.id = iv.p_id)
INNER JOIN contact AS pr ON (pr.id = p.pr_id)
LEFT OUTER JOIN contact pr2
ON pr2.id = p.pr_id
LEFT OUTER JOIN mprod p2
ON p2.type_id = p.type_id
LEFT OUTER JOIN ivalues i2
ON i2.p_id = p2.id
AND i2.period = iv.period
AND i2.current = iv.current
AND i2.cert = iv.cert
AND i2.exists = iv.exists
AND iv.value > i2.value
WHERE
iv.period = 0
AND iv.current = 1
AND iv.cert = 1
AND p.type_id = 15747
AND iv.exists = 1
AND i2.id IS NULL
ORDER BY iv.value ASC
LIMIT 10;
SELECT * FROM ivalues AS iv
INNER JOIN mprod AS p ON (p.id = iv.p_id)
INNER JOIN contact AS pr ON (pr.id = p.pr_id)
LEFT OUTER JOIN contact p2
ON p2.pr_id = p.pr_id
AND p2.type_id = p.type_id
INNER JOIN mprod p2
ON p2.type_id = p.type_id
INNER JOIN ivalues i2
ON i2.p_id = p2.id
AND i2.period = iv.period
AND i2.current = iv.current
AND i2.cert = iv.cert
AND i2.exists = iv.exists
AND iv.value > i2.value
WHERE
iv.period = 0
AND iv.current = 1
AND iv.cert = 1
AND p.type_id = 15747
AND iv.exists = 1
ORDER BY iv.value ASC
LIMIT 3;
I think you will need to join ivalues and mprod as a subselect, either as an outer join to exclude non-maximum values, or as an inner group to find the maximum value. Hopefully it looks something like this:
SELECT * FROM contact
INNER JOIN mprod ON mprod.contact_id = contact.id
INNER JOIN ivalues ON ivalues.mprod_id = mprod.id
LEFT OUTER JOIN (
SELECT mprod.contact_id, ivalues.*
FROM mprod
INNER JOIN ivalues ON mprod.id = ivalues.mprod_id
WHERE ivalues.period = 0
AND ivalues.current = 1
AND ivalues.cert = 1
AND mprod.type_id = 15747
AND ivalues.exists = 1
) AS pv ON pv.contact_id = contact.id AND pv.value > ivalues.value
WHERE ivalues.period = 0
AND ivalues.current = 1
AND ivalues.cert = 1
AND mprod.type_id = 15747
AND ivalues.exists = 1
AND pv.id IS NULL
GROUP BY pr.id
ORDER BY iv.value ASC
LIMIT 10;