MySql COUNT datediff values in complex function - mysql

I have this SQL Query that returns datediff of number of week
SELECT
ROUND(DATEDIFF((
SELECT t.date FROM actividad_newsletters t WHERE t.id_newsletter = t1.id_newsletter AND t1.id_desc = 3 AND (t.id_desc = 5 OR t.id_desc = 7) AND t.date > t1.date ORDER BY t.date LIMIT 1),
MIN(t1.date)
)/7, 0) as weeks
FROM actividad_newsletters t1
INNER JOIN newsletter t2 ON t1.id_newsletter = t2.id
GROUP BY id_newsletter
HAVING weeks IS NOT NULL
And gets this results:
0
0
0
0
0
1
1
1
1
1
1
2
2
3
3
3
3
3
3
3
3
3
3
3
.
.
.
117
117
118
119
119
I want do a count for same result like:
total week
----- ----
5 0
6 1
2 2
11 3
. .
. .
. .
2 117
1 118
2 119
How should I do it?
I tried with count(weeks) but isn't working

Try This
Select weeks, count(*) from (SELECT
ROUND(DATEDIFF((
SELECT t.date FROM actividad_newsletters t WHERE t.id_newsletter = t1.id_newsletter AND t1.id_desc = 3 AND (t.id_desc = 5 OR t.id_desc = 7) AND t.date > t1.date ORDER BY t.date LIMIT 1),
MIN(t1.date)
)/7, 0) as weeks
FROM actividad_newsletters t1
INNER JOIN newsletter t2 ON t1.id_newsletter = t2.id
GROUP BY id_newsletter
HAVING weeks IS NOT NULL) as t group by weeks

SOLVED:
SELECT weeks, COUNT(weeks) FROM (
SELECT
ROUND(DATEDIFF((
SELECT t.date FROM actividad_newsletters t WHERE t.id_newsletter = t1.id_newsletter AND t1.id_desc = 3 AND (t.id_desc = 5 OR t.id_desc = 7) AND t.date > t1.date ORDER BY t.date LIMIT 1),
MIN(t1.date)
)/7, 0) as weeks
FROM actividad_newsletters t1
INNER JOIN newsletter t2 ON t1.id_newsletter = t2.id
GROUP BY id_newsletter
HAVING weeks IS NOT NULL ) AS count GROUP BY weeks

Related

Convert mySQL partition query to mySQL 5.7 Compatible query where there are two sums in one query

I have the following query that works perfectly in mysql 8:
SELECT
J.JobID, Month(WH.DateStart) as MonthCharged, Year(WH.DateStart) as YearCharged, sum(WH.Duration) as HoursWorkedInMonth, sum(WH.Duration) over (partition by J.JobID order by Month(WH.DateStart), Year(WH.DateStart)) as CumulativeJobHoursWorked
FROM
tblJob J
JOIN tblTask T ON CONCAT('JOB-', RIGHT(YEAR(J.DateCreated), 2), '-', LPAD(J.JobID, 4, '0')) = T.SourceID
LEFT JOIN xrefTasktoEmployee XT ON T.TaskID = XT.TaskID
LEFT JOIN tblWorkHistory WH ON XT.WorkHistoryID = WH.WorkHistoryID
LEFT JOIN tblRates R ON XT.rateID = R.RateID
Where WH.Duration is not NULL
Group by J.JobID, Month(WH.DateStart), Year(WH.DateStart)
And it produces the following results:
Job ID
Month Charged
Year Charged
HoursWorkedInMonth
CumulativeJobHoursWorked
1
3
2021
23.98
23.98
1
4
2021
24.98
47.96
2
3
2021
8
8
3
2
2021
8
8
4
3
2021
1
1
5
2
2021
10
10
Notice how I am summing the hours worked in the month & year for a particular job, then I need the cumulative for that Job for the year.
I can't seem to figure out how to do this in MySQL 5.7 by using variables. Does anyone have any insights?
Thanks
Here is what I finally got to work:
SELECT
J.JobID, Month(WH.DateStart) as MonthCharged, Year(WH.DateStart) as YearCharged, sum(WH.Duration) as HoursWorkedInMonth, (SELECT
sum(WH2.Duration)
FROM
tblJob J2
JOIN tblTask T2 ON CONCAT('JOB-', RIGHT(YEAR(J2.DateCreated), 2), '-', LPAD(J2.JobID, 4, '0')) = T2.SourceID
LEFT JOIN xrefTasktoEmployee XT2 ON T2.TaskID = XT2.TaskID
LEFT JOIN tblWorkHistory WH2 ON XT2.WorkHistoryID = WH2.WorkHistoryID
Where WH2.Duration is not NULL and J2.JobID = J.JobID and DATE_FORMAT(WH2.DateStart, '%m-%Y') <= DATE_FORMAT(WH.DateStart, '%m-%Y')) as CumulativeJobHoursWorked
FROM
tblJob J
JOIN tblTask T ON CONCAT('JOB-', RIGHT(YEAR(J.DateCreated), 2), '-', LPAD(J.JobID, 4, '0')) = T.SourceID
LEFT JOIN xrefTasktoEmployee XT ON T.TaskID = XT.TaskID
LEFT JOIN tblWorkHistory WH ON XT.WorkHistoryID = WH.WorkHistoryID
Where WH.Duration is not NULL
Group by J.JobID, Month(WH.DateStart), Year(WH.DateStart)

I'm hoping to sort the items returned in the following query by the order they're entered into the IN() function

I'm hoping to sort the items returned in the following query by the order they're entered into the IN() function.
SELECT t1.product_id
, SUM(t1.quantity)
FROM tb_invoice_detail t1
, tb_products t2
WHERE t1.del_date > DATE_ADD(SYSDATE(), INTERVAL - 1 MONTH)
AND t1.del_f = '1'
and t1.product_id = t2.id
AND IFNULL(t2.price_discount, t2.price) BETWEEN 0 AND 100
and t2.rate >= 0
GROUP
BY t1.product_id
ORDER
BY SUM(t1.quantity) DESC;
Result:
product_id, SUM(t1.quantity)
100320 8
100004 7
100210 5
100226 5
100321 4
100418 3
100002 2
100000 2
100001 2
100474 2
100268 2
When I get list data using product_id
SELECT
id,
name,
thumbnail,
description,
price,
IFNULL(price_discount, price) AS price_discount,
rate,
number_total,
number_current,
(CASE
WHEN number_current = 0 THEN 2
WHEN (ROUND(number_current / number_total * 100) < 20) THEN 1
ELSE 0
END) AS state
FROM
tb_products
WHERE
id IN (100320 , 100004,
100210,
100226,
100321,
100418,
100002,
100000,
100001,
100474,
100268)
=>
SELECT
id,
name,
thumbnail,
description,
price,
IFNULL(price_discount, price) AS price_discount,
rate,
number_total,
number_current,
(CASE
WHEN number_current = 0 THEN 2
WHEN (ROUND(number_current / number_total * 100) < 20) THEN 1
ELSE 0
END) AS state
FROM
tb_products
WHERE
id IN (100320 , 100004,
100210,
100226,
100321,
100418,
100002,
100000,
100001,
100474,
100268)

MYSQL Query Select with condition & Join

I have these 3 tables ( with these structure):
outreach
id url profile_id
------------------------------------------
40 www.google.com 2
41 www.yahoo.com 3
42 www.test.com 1
outreach_links
id outreach_id end_date status
-----------------------------------------------
1 41 2016-01-12 Pending
2 40 2016-03-12 Pending
3 40 2016-02-12 Approved
comments
id outreach_id name
----------------------------
1 40
2 40
3 40
and I have this Query:
select o.*,
SUM(if(ol.status = "Approved" and (ol.end_date > now() or end_date is null), 1, 0)) as cond1,
SUM(if(ol.status = "Pending" and (ol.end_date != now() or end_date is null), 1, 0)) as cond2,
SUM(if(ol.status = "Pending" and (ol.end_date < now()), 1, 0)) as cond3
from outreach o
left join outreach_links ol on ol.outreach_id = o.id
where o.profile_id=2
group by o.id
having (cond1 = 0 and cond2 = 0) or (cond1 = 0 and (cond2 = 1 and cond3 >=1)) order by ol.end_date desc
I am trying to fix this Query and make it also select the following:
1). ol.* ONLY if MAX(end_date) and
2). Count(id.comment) count all comments for that particular row
is that possible?
right now here is the output
+"id": "40"
+"profile_id": "2"
+"url": "http://www.google.com"
+"created_at": "2016-12-05 21:55:10"
+"updated_at": "2016-12-05 22:49:56"
+"cond1": "0"
+"cond2": "0"
+"cond3": "5"
I want to add
+"max_date": get me max of end_date and the whole row of the row highlighted
+"Count(comments)": get me all the comments count for this one which is 3
Thanks
Are you trying to get the latest update date? The following query should give you the latest updated date.
However, I do not understand what you are trying to get for cond1, cond2, cond3, and what should be populated as created_date, and updated_date? Can you please give definitions for these fields?
SELECT o.*, ol.*, COUNT(c.id)
FROM outreach o
LEFT JOIN outreach_links ol ON ol.outreach_id = o.id
LEFT JOIN comments c ON c.outreach_id = o.id
WHERE ol.id = (SELECT ol2.id
FROM outreach_links ol2
WHERE ol2.outreach_id = ol.outreach_id
ORDER BY ol2.end_date, ol2.id DESC
LIMIT 1)
OR ol.id IS NULL
GROUP BY o.id, ol.id

Mysql union with aggregate functions

Please tell me a way to optimise the below query
Please help me someone to optimise the union query with aggrgate functions, the result should come in same column name
(SELECT `raw_id`, `enodeb`, hour( DATE_SUB(`interval`, INTERVAL 15 MINUTE) ) AS intervaltime,`id_sector`,`metric`, Sum(`interval_count`) as metric_value, `cuase_code`,`qci`, N.network_name as network_name FROM raw_metrics left join networks N on N.network_id = raw_metrics.network_id WHERE 1 AND DATE(DATE_SUB(`interval`, INTERVAL 15 MINUTE)) = "2015-03-12" and `metric` in(SELECT `measurement_name` FROM `c_xml_measurements` left join counter_types CT ON CT.counter_id = c_xml_measurements.counter_type WHERE CT.status = 1 and CT.counter_id in (1,2)) GROUP BY intervaltime, `id_sector`, metric)
UNION ALL
(SELECT `raw_id`, `enodeb`, hour( DATE_SUB(`interval`, INTERVAL 15 MINUTE) ) AS intervaltime,`id_sector`,`metric`, AVG(`metric_value`) as metric_value, `cuase_code`,`qci`, N.network_name as network_name FROM raw_metrics left join networks N on N.network_id = raw_metrics.network_id WHERE 1 AND DATE(DATE_SUB(`interval`, INTERVAL 15 MINUTE)) = "2015-03-12" and `metric` in(SELECT `measurement_name` FROM `c_xml_measurements` left join counter_types CT ON CT.counter_id = c_xml_measurements.counter_type WHERE ((CT.status = 1 and CT.counter_id not in (1,2)) OR (CT.status = 0 and CT.counter_id in (1,2))) and (aggregator= 'AVG' OR aggregator= '') ) GROUP BY intervaltime, `id_sector`, metric)
UNION ALL
(SELECT `raw_id`, `enodeb`, hour( DATE_SUB(`interval`, INTERVAL 15 MINUTE) ) AS intervaltime,`id_sector`,`metric`, MAX(`metric_value`) as metric_value, `cuase_code`,`qci`, N.network_name as network_name FROM raw_metrics left join networks N on N.network_id = raw_metrics.network_id WHERE 1 AND DATE(DATE_SUB(`interval`, INTERVAL 15 MINUTE)) = "2015-03-12" and `metric` in(SELECT `measurement_name` FROM `c_xml_measurements` left join counter_types CT ON CT.counter_id = c_xml_measurements.counter_type WHERE ((CT.status = 1 and CT.counter_id not in (1,2)) OR (CT.status = 0 and CT.counter_id in (1,2))) and (aggregator= 'MAX') ) GROUP BY intervaltime, `id_sector`, metric)
UNION ALL
(SELECT `raw_id`, `enodeb`, hour( DATE_SUB(`interval`, INTERVAL 15 MINUTE) ) AS intervaltime,`id_sector`,`metric`, MIN(`metric_value`) as metric_value, `cuase_code`,`qci`, N.network_name as network_name FROM raw_metrics left join networks N on N.network_id = raw_metrics.network_id WHERE 1 AND DATE(DATE_SUB(`interval`, INTERVAL 15 MINUTE)) = "2015-03-12" and `metric` in(SELECT `measurement_name` FROM `c_xml_measurements` left join counter_types CT ON CT.counter_id = c_xml_measurements.counter_type WHERE ((CT.status = 1 and CT.counter_id not in (1,2)) OR (CT.status = 0 and CT.counter_id in (1,2))) and (aggregator= 'MIN') ) GROUP BY intervaltime, `id_sector`, metric) ORDER BY raw_id DESC

Complex querying on table with multiple userids

I have a table like this:
score
id week status
1 1 0
2 1 1
3 1 0
4 1 0
1 2 0
2 2 1
3 2 0
4 2 0
1 3 1
2 3 1
3 3 1
4 3 0
I want to get all the id's of people who have a status of zero for all weeks except for week 3. something like this:
Result:
result:
id w1.status w2.status w3.status
1 0 0 1
3 0 0 1
I have this query, but it is terribly inefficient on larger datasets.
SELECT w1.id, w1.status, w2.status, w3.status
FROM
(SELECT s.id, s.status
FROM score s
WHERE s.week = 1) w1
LEFT JOIN
(SELECT s.id, s.status
FROM score s
WHERE s.week = 2) w2 ON w1.id=w2.id
LEFT JOIN
(SELECT s.id, s.status
FROM score s
WHERE s.week = 3) w3 ON w1.id=w3.id
WHERE w1.status=0 AND w2.status=0 AND w3.status=1
I am looking for a more efficient way to calculate the above.
select id
from score
where week in (1, 2, 3)
group by id
having sum(
case
when week in (1, 2) and status = 0 then 1
when week = 3 and status = 1 then 1
else 0
end
) = 3
Or more generically...
select id
from score
group by id
having
sum(case when status = 0 then 1 else 0 end) = count(*) - 1
and min(case when status = 1 then week else null end) = max(week)
You can do using not exists as
select
t1.id,
'0' as `w1_status` ,
'0' as `w2_status`,
'1' as `w3_status`
from score t1
where
t1.week = 3
and t1.status = 1
and not exists(
select 1 from score t2
where t1.id = t2.id and t1.week <> t2.week and t2.status = 1
);
For better performance you can add index in the table as
alter table score add index week_status_idx (week,status);
In case of static number of weeks (1-3), group_concat may be used as a hack..
Concept:
SELECT
id,
group_concat(status) as totalStatus
/*(w1,w2=0,w3=1 always!)*/
FROM
tableName
WHERE
totalStatus = '(0,0,1)' /* w1=0,w2=1,w3=1 */
GROUP BY
id
ORDER BY
week ASC
(Written on the go. Not tested)
SELECT p1.id, p1.status, p2.status, p3.status
FROM score p1
JOIN score p2 ON p1.id = p2.id
JOIN score p3 ON p2.id = p3.id
WHERE p1.week = 1
AND p1.status = 0
AND p2.week = 2
AND p2.status = 0
AND p3.week = 3
AND p3.status = 1
Try this, should work