sum over values by month from two table - mysql

How to sum over values by month from two table?
I have two table:
1)costs_1
-id
-total
-updated_at(timestamp)
2)costs_2
-id
-total_1
-updated_at_1(timestamp)
The result table need have next columns:
-total
-total_1
-month
For example, if I have one table I do next query:
SELECT SUM(total), MONTH(updated_at), YEAR(updated_at) FROM product_sale GROUP BY MONTH(updated_at), YEAR(updated_at) ORDER by MONTH(updated_at)

I believe you want something like this.
SELECT t1.y year,
t1.m month,
t1.total,
t2.total
FROM
(
SELECT YEAR(updated_at) y,
MONTH(updated_at) m,
SUM(total) total
FROM costs_1
GROUP BY YEAR(updated_at), MONTH(updated_at)
) t1
JOIN
(
SELECT YEAR(updated_at_1) y,
MONTH(updated_at_1) m,
SUM(total_1) total
FROM costs_2
GROUP BY YEAR(updated_at_1), MONTH(updated_at_1)
) t2 ON t1.y = t2.y and t1.m = t2.m
However, in this solution, you will miss a month if costs_1 or costs_2 does not have any record with the month. If you want FULL JOIN you have to emulate it in mysql using two OUTER JOINS like this:
SELECT t1.y year,
t1.m month,
COALESCE(t1.total, 0),
COALESCE(t2.total, 0)
FROM
(
SELECT YEAR(updated_at) y,
MONTH(updated_at) m,
SUM(total) total
FROM costs_1
GROUP BY YEAR(updated_at), MONTH(updated_at)
) t1
LEFT JOIN
(
SELECT YEAR(updated_at_1) y,
MONTH(updated_at_1) m,
SUM(total_1) total
FROM costs_2
GROUP BY YEAR(updated_at_1), MONTH(updated_at_1)
) t2 ON t1.y = t2.y and t1.m = t2.m
UNION
SELECT t2.y year,
t2.m month,
COALESCE(t1.total, 0),
COALESCE(t2.total, 0)
FROM
(
SELECT YEAR(updated_at) y,
MONTH(updated_at) m,
SUM(total) total
FROM costs_1
GROUP BY YEAR(updated_at), MONTH(updated_at)
) t1
RIGHT JOIN
(
SELECT YEAR(updated_at_1) y,
MONTH(updated_at_1) m,
SUM(total_1) total
FROM costs_2
GROUP BY YEAR(updated_at_1), MONTH(updated_at_1)
) t2 ON t1.y = t2.y and t1.m = t2.m

Try this:
SELECT total, total_1, MONTHNAME(costs_1.updated_at) from costs_1 INNER JOIN costs_2
ON
MONTH(costs_1.updated_at)=MONTH(costs_2.updated_at)

Related

Count all from another table

I have one table like this:
a. tbl_cdr
b. tbl_wo_notification_contacts
What I want was count all from tbl_wo_notification_contacts and tbl_cdr. Here is my query.
SELECT SUBSTRING(n.last_attempt,1,10) AS DATE,
SUM(IF(n.STATUS=1, 1,0)) AS 'Success',
SUM(IF(n.STATUS=2, 1,0)) AS 'Failed',
COUNT(*) AS 'TotalCalls'
FROM tbl_wo_notification_contacts n
WHERE n.last_attempt >= '2019-05-01' AND n.last_attempt <= '2019-07-01'
GROUP BY SUBSTRING(n.last_attempt,1,10);
The problem is I want to add new column called 'Total Duration' where it counts all from tbl_cdr based on the query condition.
Group tbl_cdr by ContactsID to get the counts.
SELECT SUBSTRING(n.last_attempt,1,10) AS DATE,
SUM(IF(n.STATUS=1, 1,0)) AS 'Success',
SUM(IF(n.STATUS=2, 1,0)) AS 'Failed',
COUNT(*) AS 'TotalCalls',
IFNULL(c.TotalDuration, 0) AS TotalDuration
FROM tbl_wo_notification_contacts n
LEFT JOIN (
SELECT ContactID, COUNT(*) AS TotalDuration
FROM tbl_cdr
GROUP BY ContactID) AS c ON c.ContactID = n.id
WHERE n.last_attempt >= '2019-05-01' AND n.last_attempt <= '2019-07-01'
GROUP BY SUBSTRING(n.last_attempt,1,10);

Use join for three tables

I have three tables and I would like sum over values by month from three tables.
The structure of database:
1)costs_1
-id
-total
-updated_at(timestamp)
2)costs_2
-id
-total_1
-updated_at_1(timestamp)
3)costs_3
-id
-total_2
-updated_at_2(timestamp)
Structure of result table: 1)total; 2)total_1; 3)total_2; 4)month
I have code that work for two tables, but don't know how to adapte it
SELECT t1.y year,
t1.m month,
COALESCE(t1.total, 0),
COALESCE(t2.total, 0)
FROM
(
SELECT YEAR(date_month) y,
MONTH(date_month) m,
SUM(total) total
FROM market_costs
GROUP BY YEAR(date_month), MONTH(date_month)
) t1
LEFT JOIN
(
SELECT YEAR(date_month) y,
MONTH(date_month) m,
SUM(total) total
FROM general_costs
GROUP BY YEAR(date_month), MONTH(date_month)
) t2 ON t1.y = t2.y and t1.m = t2.m
UNION
SELECT t2.y year,
t2.m month,
COALESCE(t1.total, 0),
COALESCE(t2.total, 0)
FROM
(
SELECT YEAR(date_month) y,
MONTH(date_month) m,
SUM(total) total
FROM market_costs
GROUP BY YEAR(date_month), MONTH(date_month)
) t1
RIGHT JOIN
(
SELECT YEAR(date_month) y,
MONTH(date_month) m,
SUM(total) total
FROM general_costs
GROUP BY YEAR(date_month), MONTH(date_month)
) t2 ON t1.y = t2.y and t1.m = t2.m
Combine the 3 tables using UNION ALL then group the data:
SELECT
YEAR(t1.date_month) y
, MONTH(t1.date_month) m
, SUM(t1.total) total
, SUM(t1.total_1) total_1
, SUM(t1.total_2) total_2
FROM (
SELECT
date_month
, total
, NULL as total_1
, NULL as total_2
FROM costs
UNION ALL
SELECT
date_month
, NULL as total
, total_1
, NULL as total_2
FROM costs_1
UNION ALL
SELECT
date_month
, NULL as total
, NULL as total_1
, total_2
FROM costs_2
) t1
GROUP BY
YEAR(t1.date_month)
, MONTH(t1.date_month)
added
SELECT
YEAR(t1.date_month) y
, MONTH(t1.date_month) m
, SUM(t1.total) total
, SUM(t1.total_1) total_1
, SUM(t1.total_2) total_2
FROM (
SELECT
date_month
, total
, NULL as total_1
, NULL as total_2
FROM costs
UNION ALL
SELECT
date_month
, NULL as total
, total as total_1 -- changed
, NULL as total_2
FROM costs_1
UNION ALL
SELECT
date_month
, NULL as total
, NULL as total_1
, total as total_2 -- changed
FROM costs_2
) t1
GROUP BY
YEAR(t1.date_month)
, MONTH(t1.date_month)

Join of two tables where result displays on min() field of table 2

Working with sql procedure and encountering a problem to which not finding solution.
There is table A with fields a,b,c.
And a table B with fields a, w, x, y, z.
Here, I want the result of join of both tables where A.a = B.a and select fields like c, x, y, z in output where w is minimum. w is an integer.
Following code is helping but when i want to display more fields from table 2, getting an error saying Group by clause not included.
SELECT OutO.routingSequence,
tbl2.a AS parentOrderNumber,
tbl2.c AS operationNumber,
tbl2.d as headerStatus,
tbl2.e as orderNumber
FROM Operation OutO
JOIN (
SELECT a, MIN(c) c
FROM (
SELECT h.parentordernumber a, o.operationNumber c
FROM header h , operation o
WHERE o.ordernumber=h.Parentordernumber
AND (
SELECT DATEDIFF(day,o.scheduledStartDate, GETDATE()) AS DiffDate
) < 3
AND (
SELECT DATEDIFF(day,o.scheduledStartDate, GETDATE()) AS DiffDate
) > -5
) tbl
GROUP BY a
) tbl2
ON OutO.ordernumber = tbl2.a
WHERE OutO.operationnumber = tbl2.c
Please help on this!!!
Try it with distinct instead of group by
Select DISTINCT OutO.routingSequence, tbl2.a as parentOrderNumber, tbl2.c as operationNumber from Operation OutO
Updated SQL you have to select fields from inner select if you want to get it as output
SELECT OutO.routingSequence,
tbl2.a AS parentOrderNumber,
tbl2.c AS operationNumber,
tbl2.d as headerStatus,
tbl2.e as orderNumber
FROM Operation OutO
JOIN (
SELECT a, MIN(c) c,MIN(d) AS d,MIN(e) as e
FROM (
SELECT h.parentordernumber as a, o.operationNumber as c ,h.headerStatus as d, h.orderNumber as e
FROM header h inner join operation o
on o.ordernumber=h.Parentordernumber
AND (
SELECT DATEDIFF(day,o.scheduledStartDate, GETDATE()) AS DiffDate
) < 3
AND (
SELECT DATEDIFF(day,o.scheduledStartDate, GETDATE()) AS DiffDate
) > -5
) tbl
GROUP BY a
) tbl2
ON OutO.ordernumber = tbl2.a
WHERE OutO.operationnumber = tbl2.c
sorry but i don't understand where is d and e and w columns is your sql
you can use row_number and partition by, to get ordered by min value first row like this
SELECT OutO.routingSequence,
tbl2.a AS parentOrderNumber,
tbl2.c AS operationNumber,
tbl2.d as headerStatus,
tbl2.e as orderNumber
FROM Operation OutO
JOIN (
select a,c,e,d from (
SELECT h.parentordernumber a, o.operationNumber c,
something1 as d,
something2 as e,
-- where this = 1 there is your minimum row
row_number() over (partition by h.parentordernumber
order by w ) Rn
FROM header h , operation o
WHERE o.ordernumber=h.Parentordernumber
AND (
SELECT DATEDIFF(day,o.scheduledStartDate, GETDATE()) AS DiffDate
) < 3
AND (
SELECT DATEDIFF(day,o.scheduledStartDate, GETDATE()) AS DiffDate
) > -5
) where Rn = 1 -- here we need only first row in every windows
) tbl2
ON OutO.ordernumber = tbl2.a
WHERE OutO.operationnumber = tbl2.c

Why is MySQL cumulative sum producing wrong results

I need to find the cumulative sum for the following data:
Following query:
SELECT created, COUNT( * )
FROM `transactions`
GROUP BY created
Gives me:
created COUNT( * )
2015-8-09 1
2015-8-15 1
2015-8-16 2
2015-8-17 1
2015-8-23 1
I tried to do the cumulative sum like:
SELECT t1.created, COUNT( * ) , SUM( t2.totalcount ) AS sum
FROM transactions t1
INNER JOIN (
SELECT id, created c, COUNT( * ) AS totalcount
FROM transactions
GROUP BY created
ORDER BY created
)t2 ON t1.id >= t2.id
GROUP BY t1.created
ORDER BY t1.created
but the results it gives arent as expected:
created COUNT( * ) sum
2015-8-09 5 6
2015-8-15 3 4
2015-8-16 6 8
2015-8-17 1 1
2015-8-23 4 5
How do i produce the following result:
created COUNT( * ) sum
2015-8-09 1 1
2015-8-15 1 2
2015-8-16 2 4
2015-8-17 1 5
2015-8-23 1 6
select tmp.*, #sum := #sum + cnt as cum_sum
from
(
SELECT created, COUNT( * ) as cnt
FROM `transactions`
GROUP BY created
ORDER BY created
) tmp
cross join (select #sum := 0) s
Your inner query is selecting id without grouping on it. Let's rework it in terms of the date.
SELECT t1.created, COUNT( * ) AS daycount, SUM( t2.totalcount ) AS sum
FROM transactions t1
INNER JOIN ( SELECT created, COUNT( * ) AS totalcount
FROM transactions
GROUP BY created
) t2 ON t1.created >= t2.created
GROUP BY t1.created
ORDER BY t1.created;
Or you might want to put the totalcount inline:
SELECT t1.created, COUNT(*) AS daycount
, ( SELECT COUNT(*) FROM transactions t2
WHERE t2.created <= t1.created ) AS totalcount
FROM transactions t1
GROUP BY created
ORDER BY CREATED;

Select in select - Every derived table must have its own alias error

I'm trying to get from database information about orders grouped by date.
I have table sales_flat_order, where I have it's id, order creation date, total_paid for order, and order item count. And I have table sales_flat_order_item where are orders items with it prices.
I created script to get order information by day:
SELECT
DATE( sales_flat_order.created_at ) AS date,
SUM( sales_flat_order.total_paid ) AS sales,
SUM( sales_flat_order.total_item_count ) AS items
FROM
sales_flat_order,
sales_flat_order_payment
WHERE
sales_flat_order.status = 'complete'
AND sales_flat_order.entity_id = sales_flat_order_payment.parent_id
AND sales_flat_order_payment.method = 'checkmo'
GROUP BY DATE( sales_flat_order.created_at )
WITH ROLLUP
I get:
DATE SALES ITEMS
2013-03-05 72 3
2013-03-06 100 5
And I have script to count median price:
SELECT
avg(t1.price) as median_val
FROM
(
SELECT
#rownum:=#rownum+1 as `row_number`,
d.price
FROM
sales_flat_order_item d,
(SELECT #rownum:=0) r
WHERE 1
ORDER BY d.price
) as t1,
(
SELECT
count(*) as total_rows
FROM
sales_flat_order_item d
WHERE 1
) as t2
WHERE 1
AND t1.row_number>=total_rows/2
and t1.row_number<=total_rows/2+1;
Now I'm trying to combine this two script to get:
DATE SALES ITEMS median_item_price
2013-03-05 72 3 19
2013-03-06 100 5 10.5
Combined script:
SELECT
DATE( sales_flat_order.created_at ) AS date,
SUM( sales_flat_order.total_paid ) AS sales,
SUM( sales_flat_order.total_item_count ) AS items,
sales_flat_order_item.price as median_item_price
FROM
sales_flat_order,
sales_flat_order_payment,
(
SELECT
avg(t1.price) as median_val
FROM
(
SELECT
#rownum:=#rownum+1 as `row_number`,
d.price
FROM
sales_flat_order_item d,
(SELECT #rownum:=0) r
WHERE 1
ORDER BY d.price
) as t1,
(
SELECT
count(*) as total_rows
FROM
sales_flat_order_item d
WHERE 1
) as t2
WHERE 1
AND t1.row_number>=total_rows/2
and t1.row_number<=total_rows/2+1
) as sales_flat_order_item
WHERE
sales_flat_order.status = 'complete'
AND sales_flat_order.entity_id = sales_flat_order_payment.parent_id
AND sales_flat_order_payment.method = 'checkmo'
AND DATE(sales_flat_order_item.created_at) = DATE(sales_flat_order.created_at)
GROUP BY DATE( sales_flat_order.created_at )
WITH ROLLUP
and get error: #1248 - Every derived table must have its own alias
here is database: http://sqlfiddle.com/#!2/7dfec
Can anyone help?
Solution:
SELECT
DATE( sales_flat_order.created_at ) AS date,
SUM( sales_flat_order.total_paid ) AS sales,
SUM( sales_flat_order.total_item_count ) AS items,
MAX( median.median_val ) as median_item_price
FROM
sales_flat_order,
sales_flat_order_payment,
(
SELECT DATE(sq.created_at) as median_date, avg(sq.price) as median_val FROM (
SELECT t1.row_number, t1.price, t1.created_at FROM(
SELECT IF(#prev!=d.created_at, #rownum:=1, #rownum:=#rownum+1) as `row_number`, d.price, #prev:=d.created_at AS created_at
FROM sales_flat_order_item d, (SELECT #rownum:=0, #prev:=NULL) r
ORDER BY d.price
) as t1 INNER JOIN
(
SELECT count(*) as total_rows, created_at
FROM sales_flat_order_item d
GROUP BY created_at
) as t2
ON t1.created_at = t2.created_at
WHERE 1=1
AND t1.row_number>=t2.total_rows/2 and t1.row_number<=t2.total_rows/2+1
)sq
group by DATE(sq.created_at)
) as median
WHERE
sales_flat_order.status = 'complete'
AND sales_flat_order.entity_id = sales_flat_order_payment.parent_id
AND sales_flat_order_payment.method = 'checkmo'
AND median.median_date = DATE( sales_flat_order.created_at )
GROUP BY DATE( sales_flat_order.created_at )
WITH ROLLUP