I want to do the following using a LEFT JOIN (please do not suggest UNION ALL)
SELECT o.*, s.col1, s.col2 FROM order o
INNER JOIN user u ON o.user_id = u.id
IF o.date less than '2011-01-01'
JOIN subscribe s ON u.key = s.key
ELSE
JOIN subscribe s ON u.email = s.email
END IF;
I used the following but can't test it.
SELECT o.*, COALESCE(s1.col1,s2.col1) AS
col1, COALESCE(s1.col2, s2.col2) AS col2
FROM order o INNER JOIN user u ON o.user_id = u.id
LEFT JOIN subscribe s1 ON
(u.key LIKE (CASE o.date >= '2011-01-01 00:00:00'
WHEN TRUE THEN s1.key ELSE NULL END))
LEFT JOIN subscribe s2 ON (u.email LIKE (CASE o.date <
'2011-01-01 00:00:00' WHEN TRUE THEN s.email
ELSE NULL END));
Please correct me if I am wrong.
Thanks.
You don't need to JOIN twice, do it like this:
SELECT o.*, s.col1, s.col2
FROM order o INNER JOIN user u ON o.user_id = u.id
LEFT JOIN subscribe s ON( ( o.date < '2011-01-01' AND u.key = s.key ) OR
( o.date >= '2011-01-01' AND u.email = s.email ) )
And here is a solution that will not do a full table scan if you have indexes on subscribe.key and subscribe.email:
SELECT * FROM
(
( SELECT 0 AS mode, o.date AS odate, o.*, s.col1, s.col2
FROM order o INNER JOIN user u ON o.user_id = u.id
LEFT JOIN subscribe s ON( u.key = s.key ) )
UNION
( SELECT 1 AS mode, o.date AS odate, o.*, s.col1, s.col2
FROM order o INNER JOIN user u ON o.user_id = u.id
LEFT JOIN subscribe s ON( u.email = s.email ) )
)
WHERE ( odate < '2011-01-01' AND mode = 0 ) OR
( odate >= '2011-01-01' AND mode = 1 )
Related
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
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.
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
I need my query to select unix timestamps which range from a particular past date till now?For example I need to select '2013-01-01' till current date. I was able to do it for a particular year. Any help would be appreciated.
SELECT mdl_user_info_data.data, mdl_user.firstname, mdl_user.lastname, mdl_user.id AS userid, SUM( mdl_quiz.fcpd ) AS cpdtotal
FROM mdl_grade_grades
INNER JOIN mdl_user ON mdl_grade_grades.userid = mdl_user.id
INNER JOIN mdl_grade_items ON mdl_grade_grades.itemid = mdl_grade_items.id
INNER JOIN mdl_quiz ON mdl_grade_items.itemname = mdl_quiz.name
INNER JOIN mdl_course ON mdl_grade_items.courseid = mdl_course.id
INNER JOIN mdl_user_info_data ON mdl_user.id = mdl_user_info_data.userid
WHERE mdl_user_info_data.fieldid =1
AND mdl_grade_items.itemname IS NOT NULL
AND YEAR( FROM_UNIXTIME( mdl_grade_grades.timemodified ) ) =2013
GROUP BY mdl_user.id
To check for a timestamp value between a given datetime in the past, and the current datetime, something like this:
AND mdl_grade_grades.timemodified >= '2013-07-25 15:30'
AND mdl_grade_grades.timemodified < NOW()
Simply replace this line:
AND YEAR(FROM_UNIXTIME(mdl_grade_grades.timemodified)) = 2013
to:
AND FROM_UNIXTIME(mdl_grade_grades.timemodified)
BETWEEN '2012-01-01 12:00'
AND now()
It seems that you are storing unix timestamp in your timemodified column. You should consider changing it to timestamp type - this will allow to take advantage of index on that field. Now, your query (and this query as well) is slow because it has to compute FROM_UNIXTIME() on every row in that table and only then compare year or date.
UPDATE:
If you don't want to change types, using this should make your query work much faster (provided that there is an index on timemodified column):
AND mdl_grade_grades.timemodified
BETWEEN unix_timestamp('2012-01-01 12:00')
AND unix_timestamp(now())
try below query
SELECT mdl_user_info_data.data, mdl_user.firstname, mdl_user.lastname, mdl_user.id AS userid, SUM( mdl_quiz.fcpd ) AS cpdtotal
FROM mdl_grade_grades
INNER JOIN mdl_user ON mdl_grade_grades.userid = mdl_user.id
INNER JOIN mdl_grade_items ON mdl_grade_grades.itemid = mdl_grade_items.id
INNER JOIN mdl_quiz ON mdl_grade_items.itemname = mdl_quiz.name
INNER JOIN mdl_course ON mdl_grade_items.courseid = mdl_course.id
INNER JOIN mdl_user_info_data ON mdl_user.id = mdl_user_info_data.userid
WHERE mdl_user_info_data.fieldid =1
AND mdl_grade_items.itemname IS NOT NULL
AND mdl_grade_grades.timemodified < date('d-m-Y')
GROUP BY mdl_user.id
You can create a Stored Procedure and pass the date as parameter to it.
Here I made it more flexible by adding end date too.
CREATE PROCEDURE `NewProc`(IN StartDate date,IN EndDate date)
BEGIN
SELECT mdl_user_info_data.data, mdl_user.firstname, mdl_user.lastname, mdl_user.id AS userid, SUM( mdl_quiz.fcpd ) AS cpdtotal
FROM mdl_grade_grades
INNER JOIN mdl_user ON mdl_grade_grades.userid = mdl_user.id
INNER JOIN mdl_grade_items ON mdl_grade_grades.itemid = mdl_grade_items.id
INNER JOIN mdl_quiz ON mdl_grade_items.itemname = mdl_quiz.name
INNER JOIN mdl_course ON mdl_grade_items.courseid = mdl_course.id
INNER JOIN mdl_user_info_data ON mdl_user.id = mdl_user_info_data.userid
WHERE mdl_user_info_data.fieldid =1
AND mdl_grade_items.itemname IS NOT NULL
AND mdl_grade_grades.timemodified between StartDate and EndDate
GROUP BY mdl_user.id
END;
AND DATE(FROM_UNIXTIME(mdl_grade_grades.timemodified)) between '2013-01-01' and
DATE(NOW());
SELECT DISTINCT (
A.`id`
), A.`id` , A.`no` , B.amount, SUM( A.`outward` * A.`price` ) AS total, A.`outward_date`
FROM `outward` A
INNER JOIN franchisees B
INNER JOIN store C
INNER JOIN shoppe D
WHERE B.user_id = C.user_id
AND (C.pos_id = A.no)//(C.pos_id = A.no OR (D.id = A.no)
OR (D.id = A.no)
AND A.outward_date = '2012-02-10'
GROUP BY A.req_id
ORDER BY A.no ASC , A.`d` ASC , B.amount ASC
The problem in this query is that the SUM( A.outward * A.price ) AS total comes differently which is not related to
ouptut
id sum(outward * price)
12021030738-105 485.220000000000
1202104186-104 2504.410000000000
output displayed
12021030738-105 32557.33
1202104186-104 6307.86
i guess the problem is with the OR statement? can anyone find the issue with the query
Try below. enclose OR Conditions in a parenthesis:
SELECT DISTINCT (
A.`id`
), A.`id` , A.`no` , B.amount, SUM( A.`outward` * A.`price` ) AS total, A.`outward_date`
FROM `outward` A
INNER JOIN franchisees B
INNER JOIN store C
INNER JOIN shoppe D
WHERE B.user_id = C.user_id
AND ((C.pos_id = A.no) OR (D.id = A.no))
AND A.outward_date = '2012-02-10'
GROUP BY A.req_id
ORDER BY A.no ASC , A.`d` ASC , B.amount ASC