New to SQL. I am trying to get some week-over-week trends to compare various metric points. This is what I have so far. The runtime is bad because it goes through the entire table 4 times and this is only for the past 4 weeks. Is there any way to improve this process and also get metrics for all the past weeks (not just the last 4) ?
Edit: This is MySQL.
Sample Data:
Timestamp
Metric Hits
Metric Total
Metric Value
2022-09-20 06:50:01.332000
4
4
1
2022-08-31 08:49:59.086000
2
3
0.6666
2022-08-09 04:50:12.430000
1
2
0.5
SELECT
sum(metric_hits) as metric_hits_sum,
sum(metric_total) as metrics_total_sum,
avg(metric_value) as metric_value_avg
from metric_events
where timestamp >= DATEADD(DAY, -7-DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date) and timestamp < DATEADD(DAY, -DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date)
UNION
SELECT
sum(metric_hits) as metric_hits_sum,
sum(metric_total) as metrics_total_sum,
avg(metric_value) as metric_value_avg
from metric_events
where timestamp >= DATEADD(DAY, -14-DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date) and timestamp < DATEADD(DAY, -7-DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date)
UNION
SELECT
sum(metric_hits) as metric_hits_sum,
sum(metric_total) as metrics_total_sum,
avg(metric_value) as metric_value_avg
from metric_events
where timestamp >= DATEADD(DAY, -21-DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date) and timestamp < DATEADD(DAY, -14-DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date)
UNION
SELECT
sum(metric_hits) as metric_hits_sum,
sum(metric_total) as metrics_total_sum,
avg(metric_value) as metric_value_avg
from metric_events
where timestamp >= DATEADD(DAY, -28-DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date) and timestamp < DATEADD(DAY, -21-DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date)
This should get you closer. I'll leave you to add more features (like week begin and end dates)
select floor((daysold - DATEPART(WEEKDAY, GETDATE()::date)) / 7) as weeksold
, sum(metric_hits) as metric_hits_sum
, sum(metric_total) as metrics_total_sum
, avg(metric_value) as metric_value_avg
from (
SELECT datediff(day, [timestamp], GETDATE()::date) as daysold
, metric_hits
, metric_total
, metric_value
from metric_events
where [timestamp] < DATEADD(DAY, -DATEPART(WEEKDAY, GETDATE()::date), GETDATE()::date)
) q
group by floor((daysold - DATEPART(WEEKDAY, GETDATE()::date)) / 7)
order by 1
I use following query to give me the earned commission of our sales agents.
SELECT * FROM
(SELECT agent,
COUNT(*) as sales,
(4*(SELECT COUNT(*)
FROM Sales Sales2
WHERE Sales2.agent=Sales.agent AND finalized_at BETWEEN '2020-11-01 00:00:00' AND '2020-11-27 23:59:59' AND flow=117))
/
(SELECT SUM(uren) FROM Uren WHERE datum BETWEEN '2020-11-01 00:00:00' AND '2020-11-27 23:59:59' AND agent=Sales.agent) as sph
FROM Sales
WHERE finalized_at BETWEEN '2020-11-27 00:00:00' AND '2020-11-27 23:59:59' AND flow=117
GROUP BY agent ) r
ORDER BY sales * sph desc;
Now I want the output to be sorted by (sales * sph * factor). Where factor is 10 if sph > 1.5 and else 7.5.
Is it possible to implement this in the query. If yes how do I achieve this?
It would also be good if calculation would be done in the SELECT statement like (sales * sph * factor) as commission and then just use SORT BY commission.
I hope my question makes any sense.
You could use condition in order by eg using a case when
SELECT *
FROM (
SELECT agent,
COUNT(*) as sales,
(4*(SELECT COUNT(*)
FROM Sales Sales2
WHERE Sales2.agent=Sales.agent AND finalized_at BETWEEN '2020-11-01 00:00:00' AND '2020-11-27 23:59:59' AND flow=117))
/
(SELECT SUM(uren) FROM Uren WHERE datum BETWEEN '2020-11-01 00:00:00' AND '2020-11-27 23:59:59' AND agent=Sales.agent) as sph
FROM Sales
WHERE finalized_at BETWEEN '2020-11-27 00:00:00' AND '2020-11-27 23:59:59' AND flow=117
GROUP BY agent ) r
ORDER BY sales * sph * (case when sph > 1.5 then 10 else 7.5 end ) desc;
I know I could use min(date) to find the oldest date between a columns but how can I select the oldest date between 3 different columns?
Example:
Select date_1, date_2, date_3, do_something(oldest_date) from table;
EDIT: Actually my query is a little bit more complicated.
SELECT
(SELECT
IF(test.OLD = 1, DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y'), IF(revalidation.recognized = 0, DATE_FORMAT(DATE_ADD(revalidation.DATE_test, INTERVAL revalidation.VALIDITY YEAR), '%d-%m-%Y'), IF(test.DATE_EXPIRATION = ''
OR test.DATE_EXPIRATION IS NULL, DATE_FORMAT(DATE_ADD(test.DATE_test, INTERVAL test.VALIDITY YEAR), '%d-%m-%Y'), DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y')))) AS VENCIMIENTO
FROM
eva_compet revalidation
LEFT JOIN eva_compet test ON (revalidation.recognized = test.EVA_LAB_ID)
WHERE
revalidation.TYPO_EVA_ID = 1
AND revalidation.LABORAL_ID = cl.laboral_id
LIMIT 1) AS DATE_1,
(SELECT
IF(test.OLD = 1, DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y'), IF(revalidation.recognized = 0, DATE_FORMAT(DATE_ADD(revalidation.DATE_test, INTERVAL revalidation.VALIDITY YEAR), '%d-%m-%Y'), IF(test.DATE_EXPIRATION = ''
OR test.DATE_EXPIRATION IS NULL, DATE_FORMAT(DATE_ADD(test.DATE_test, INTERVAL test.VALIDITY YEAR), '%d-%m-%Y'), DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y')))) AS VENCIMIENTO
FROM
eva_compet revalidation
LEFT JOIN eva_compet test ON (revalidation.recognized = test.EVA_LAB_ID)
WHERE
revalidation.TYPO_EVA_ID = 2
AND revalidation.LABORAL_ID = cl.laboral_id
LIMIT 1) AS DATE_2,
(SELECT
IF(test.OLD = 1, DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y'), IF(revalidation.recognized = 0, DATE_FORMAT(DATE_ADD(revalidation.DATE_test, INTERVAL revalidation.VALIDITY YEAR), '%d-%m-%Y'), IF(test.DATE_EXPIRATION = ''
OR test.DATE_EXPIRATION IS NULL, DATE_FORMAT(DATE_ADD(test.DATE_test, INTERVAL test.VALIDITY YEAR), '%d-%m-%Y'), DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y')))) AS VENCIMIENTO
FROM
eva_compet revalidation
LEFT JOIN eva_compet test ON (revalidation.recognized = test.EVA_LAB_ID)
WHERE
revalidation.TYPO_EVA_ID = 3
AND revalidation.LABORAL_ID = cl.laboral_id
LIMIT 1) AS DATE_3,
CASE WHEN DATE_1 <= DATE_2 AND DATE_1 <= DATE_3 THEN DATE_1
WHEN DATE_2 <= DATE_1 AND DATE_2 <= DATE_3 THEN DATE_2
ELSE DATE_3
END AS TERMINO
FROM
table
WHERE
table_id = 1001;
I tried to use the CASE as suggested but I am getting:
Error Code: 1054. Unknown column 'date_1' in 'field list'
SOLUTION (I followed the solution provided by #joe-stefanelli and the suggestion from #Uueerdo, THANKS ):
SELECT
DATE_1,
DATE_2,
DATE_3,
CASE WHEN DATE_1 <= DATE_2 AND DATE_1 <= DATE_3 THEN DATE_1
WHEN DATE_2 <= DATE_1 AND DATE_2 <= DATE_3 THEN DATE_2
ELSE DATE_3
END AS OLDEST_DATE
FROM
(SELECT
(SELECT
IF(test.OLD = 1, DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y'), IF(revalidation.recognized = 0, DATE_FORMAT(DATE_ADD(revalidation.DATE_test, INTERVAL revalidation.VALIDITY YEAR), '%d-%m-%Y'), IF(test.DATE_EXPIRATION = ''
OR test.DATE_EXPIRATION IS NULL, DATE_FORMAT(DATE_ADD(test.DATE_test, INTERVAL test.VALIDITY YEAR), '%d-%m-%Y'), DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y')))) AS VENCIMIENTO
FROM
eva_compet revalidation
LEFT JOIN eva_compet test ON (revalidation.recognized = test.EVA_LAB_ID)
WHERE
revalidation.TYPO_EVA_ID = 1
AND revalidation.LABORAL_ID = cl.laboral_id
LIMIT 1) AS DATE_1,
(SELECT
IF(test.OLD = 1, DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y'), IF(revalidation.recognized = 0, DATE_FORMAT(DATE_ADD(revalidation.DATE_test, INTERVAL revalidation.VALIDITY YEAR), '%d-%m-%Y'), IF(test.DATE_EXPIRATION = ''
OR test.DATE_EXPIRATION IS NULL, DATE_FORMAT(DATE_ADD(test.DATE_test, INTERVAL test.VALIDITY YEAR), '%d-%m-%Y'), DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y')))) AS VENCIMIENTO
FROM
eva_compet revalidation
LEFT JOIN eva_compet test ON (revalidation.recognized = test.EVA_LAB_ID)
WHERE
revalidation.TYPO_EVA_ID = 2
AND revalidation.LABORAL_ID = cl.laboral_id
LIMIT 1) AS DATE_2,
(SELECT
IF(test.OLD = 1, DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y'), IF(revalidation.recognized = 0, DATE_FORMAT(DATE_ADD(revalidation.DATE_test, INTERVAL revalidation.VALIDITY YEAR), '%d-%m-%Y'), IF(test.DATE_EXPIRATION = ''
OR test.DATE_EXPIRATION IS NULL, DATE_FORMAT(DATE_ADD(test.DATE_test, INTERVAL test.VALIDITY YEAR), '%d-%m-%Y'), DATE_FORMAT(test.DATE_EXPIRATION, '%d-%m-%Y')))) AS VENCIMIENTO
FROM
eva_compet revalidation
LEFT JOIN eva_compet test ON (revalidation.recognized = test.EVA_LAB_ID)
WHERE
revalidation.TYPO_EVA_ID = 3
AND revalidation.LABORAL_ID = cl.laboral_id
LIMIT 1) AS DATE_3,
CASE WHEN DATE_1 <= DATE_2 AND DATE_1 <= DATE_3 THEN DATE_1
WHEN DATE_2 <= DATE_1 AND DATE_2 <= DATE_3 THEN DATE_2
ELSE DATE_3
END AS TERMINO
FROM
table
WHERE
table_id = 1001)
AS table_2;
SELECT CASE WHEN date_1 <= date_2 AND date_1 <= date_3 THEN date_1
WHEN date_2 <= date_1 AND date_2 <= date_3 THEN date_2
ELSE date_3
END AS oldest_date
FROM table;
This answers the original post:
select date_1, date_2, date_3, do_something(a) from table, (select least(date_1, date_2, date_3) a from table) b;
I'm not going to try to figure out the complexities of the edit.
If all you want is the results of your function, then this:
select do_something(a) from (select least(date_1, date_2, date_3) a from table) b;
Okay, I took a stab at it with the complexities. I'm not sure if this will work:
SELECT DATE_1, DATE_2, DATE_3, do_something(a) FROM b,
( SELECT LEAST(DATE_1, DATE_2, DATE_3) a FROM
( SELECT (...) as DATE_1, (...) as DATE_2, (...) as DATE_3 )
FROM table WHERE table_id = 1001
) AS b
) AS c;
I need to fetch some data from mySql evergreen period (total - some prmo periods) ;
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND YEAR(trxDate) = '2018'
Total : 462
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2017-03-03' AND trxDate <= '2017-09-12'
0
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-09-11' AND trxDate <= '2019-01-03'
5
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-07-01' AND trxDate <= '2018-09-04'
218
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-08-01' AND trxDate <= '2018-08-18'
4
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-07-01' AND trxDate <= '2018-07-31'
4
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-06-15' AND trxDate <= '2018-06-30'
2
Now I need to fetch Total - (All periods) My query is
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND 1 AND (trxDate < '2018-09-11' OR trxDate > '2018-10-25') AND (trxDate < '2018-07-01' OR trxDate > '2018-09-04') AND (trxDate < '2018-08-01' OR trxDate > '2018-08-18') AND (trxDate < '2018-07-01' OR trxDate > '2018-07-31') AND (trxDate < '2018-06-15' OR trxDate > '2018-06-30')
My desired Output is
462-0-5-218-4-4-2 = 229 But i am getting 237
When I hit queries for 1 or 2 date range it show fine result but all together not.
What is the issue in my query.
Why not just union all your queries together to get the final sum?
SELECT SUM(tUniquePageViews) FROM
(
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND YEAR(trxDate) = '2018'
union all
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2017-03-03' AND trxDate <= '2017-09-12'
union all
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-09-11' AND trxDate <= '2019-01-03'
union all
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-07-01' AND trxDate <= '2018-09-04'
union all
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-08-01' AND trxDate <= '2018-08-18'
union all
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-07-01' AND trxDate <= '2018-07-31'
union all
SELECT SUM(view) AS tUniquePageViews FROM store_report_per_day WHERE tpi = 'SE0541' AND trxDate >= '2018-06-15' AND trxDate <= '2018-06-30'
) a;
You can try using conditional aggregation
SELECT
SUM(case when YEAR(trxDate) = '2018' then view end)-
SUM(case when trxDate >= '2017-03-03' AND trxDate <= '2017-09-12' then view end) -
SUM(case when trxDate >= '2018-09-11' AND trxDate <= '2019-01-03' then view end)-
SUM(case when trxDate >= '2018-07-01' AND trxDate <= '2018-09-04' then view end)-
SUM(case when trxDate >= '2018-08-01' AND trxDate <= '2018-08-18' then view end)-
SUM(case when trxDate >= '2018-07-01' AND trxDate <= '2018-07-31' then view end)-
SUM(case when trxDate >= '2018-06-15' AND trxDate <= '2018-06-30' then view end)
AS tUniquePageViews
FROM store_report_per_day WHERE tpi = 'SE0541'