Combining These MySQL Queries and SUM data with one Query - mysql

I need to combine these two queries and get records using the single mySQL query.
Here are my queries
select DATE_FORMAT(campaign_date, '%Y-%m' ) AS month
, sum(sms)
from table1
group
by month
it returns me, sum of all months e.g
2019-05 5400
2019-06 3200
2019-07 11505
etc
I have another query which gets data in same format but from a different table.
select DATE_FORMAT(trans_date, '%Y-%m' ) AS month
, sum(camp_sms)
from table2
group
by month
2019-05 3500
2019-06 7256
2019-07 35465
etc
is it possible to combine these two query and get data same like this below:
Date sum(sms) sum(camp_sms)
2019-05 5400 3500
2019-06 3200 7256
2019-07 11505 35465
I have done this using PHP loops & array and to get the same output, but i want to do it using mySQL.

Simply use join
select t1.month, t1.total, t2.total from (
select DATE_FORMAT(campaign_date, '%Y-%m' ) AS month, sum(sms) total from table1 group by month
) t1
join (
select DATE_FORMAT(trans_date, '%Y-%m' ) AS month, sum(camp_sms) from table2 group by month
) t2 on t1.month = t2.month

If you don't want to skip any data from table1, then you should LEFT JOIN similarly you can use other joins according to your requirements.

Related

MySQL Query to get each sales per month

I have 2 tables in Mysql. I want to regroup and count the Number of Orderid per month for each customer. If there is no order, I would like to add 0.
Customer Table
CustomerID
1
2
3
Order Table
OrderId CustomerID Date
1 1 2022-01-02
2 1 2022-01-04
3 2 2022-02-03
4 2 2022-03-03
Expect results
CustomerID Date CountOrderID
1 2022-01 2
2 2022-01 1
3 2022-01 0
1 2022-02 0
2 2022-02 1
3 2022-02 0
1 2022-03 0
2 2022-03 1
3 2022-03 0
How I can do this in Mysql?
SELECT customer.CustomerID,
year_month.y_m AS `Date`,
COUNT(order.OrderId) AS CountOrderID
FROM customer
CROSS JOIN (
SELECT DISTINCT DATE_FORMAT(`date`, '%Y-%m') AS y_m
FROM order
) AS year_month
LEFT JOIN order ON order.CustomerID = customer.CustomerID
AND DATE_FORMAT(order.`date`, '%Y-%m') = year_month.y_m
GROUP BY 1, 2;
If order table does not contains for some year and month then according row won't present in the output. If you need in it then you'd generate calendar table instead of year_month subquery.
you can reduce the number of cte's I added more here to explain the steps:
first you need the format year and month, for that I used DATE_FORMAT() function
since you need to have all the combination of dates and the year month you need a cross join. This will produce all the distinct dates with all the distinct customer id's. In other words all the pairs between dates and customer id
once you have a table with all the combinations you need to pass the actual data with the left join this will produce null where you actually don't have rows and hence will produce 0 when the count is performed
the last step is simply count function
with main as (
select distinct DATE_FORMAT(date,'%Y-%m') as year_month from order
),
calendar as (
select * from customer
cross join main
),
joining_all as (
select
calendar.*,
order. OrderId
left join order
on calendar.CustomerID = order.CustomerID
and calendar.year_month = DATE_FORMAT(order.date,'%Y-%m')
)
select
CustomerID,
year_month as Date,
count(OrderId) as CountOrderID
from joining_all
group by 1,2
maybe the shorter version can work with the code below. if runs into syntax you can use the one above
with main as (
select distinct DATE_FORMAT(date,'%Y-%m') as year_month from order
cross join customer
)
select
main.CustomerID,
main.year_month as Date,
count(order.OrderId) as CountOrderID
from main
left join order
on main.CustomerID = order.CustomerID
and main.year_month = DATE_FORMAT(order.date,'%Y-%m')
group by 1,2

MySQL: Is there a way to get data for all dates between two dates even when there are no date rows?

Let's say I have an SELECT query like the following:
SELECT orders.date
, SUM(orders.amount) AS total_amount
FROM orders
WHERE orders.date >= '2021-04-01'
AND orders.date <= '2021-04-05';
GROUP BY orders.date
In the table, let's say I don't have any records for the dates 2021-04-03 and 2021-04-04, obviously there won't be any sum data returned for those two dates.
My question, is it possible to have a query that would return the blank dates as 0 total_amount so I can get the results like this?
date
total_amount
2021-04-01
11111
2021-04-02
22222
2021-04-03
0
2021-04-04
0
2021-04-05
12345
Thank you!
You may generate a "calendar" table containing all dates which you want to appear in your final report. Then, left join it to your current table and take the sums. In lieu of an actual calendar table, we can use an inline subquery:
SELECT
d.date,
COALESCE(SUM(o.amount), 0) AS total_amount
FROM
(
SELECT '2021-04-01' AS date UNION ALL -- replace this ad-hoc table
SELECT '2021-04-02' UNION ALL -- with a bona-fide table
SELECT '2021-04-03' UNION ALL -- containing all dates
SELECT '2021-04-04' UNION ALL
SELECT '2021-04-05'
) d
LEFT JOIN orders o
ON o.date = d.date
GROUP BY
d.date
ORDER BY
d.date;

MYSQL union how to maintain date field order when date came from 2 fields?

I have two tables Transactions and Expenses. I have written a query to get date wise transaction statement. Here Transactions table is deposit table. For this query I am getting my desire result without order date.
SELECT IFNULL(date(t1.created), date(ex.created)) as Date , sum(t1.amount) as ReceiveAmount,ex.amount as ExpensesAmount
FROM transactions as t1
LEFT JOIN (
SELECT sum(e.amount) as amount, created
FROM expenses as e
group by date(e.created)
) as ex
ON date(ex.created) = date(t1.created)
GROUP BY date(t1.created)
UNION
SELECT IFNULL(date(t1.created), date(ex.created)) as Date, sum(t1.amount) as Receive,ex.amount as ExpensesAmount
FROM transactions as t1
RIGHT JOIN (
SELECT sum(e.amount) as amount, created
FROM expenses as e
group by date(e.created)
) as ex
ON date(t1.created) = date(ex.created)
GROUP BY date(t1.created)
OUTPUT :
Date ReceiveAmount ExpensesAmount
2018-12-04 600 NULL
2019-08-01 500 NULL
2019-10-18 500 NULL
2019-11-18 820 500 <== that should come at last.
2019-11-04 NULL 100
I need to see date ASC order. Here last 2 date 2019-11-18 and 2019-11-04 not maintaining ORDER. How can I solve this problem ?
You may add an ORDER BY clause to your union query, after placing both halves of the union in parentheses:
(SELECT IFNULL(t1.created, DATE(ex.created)) AS Date, SUM(t1.amount) AS ReceiveAmount,
ex.amount AS ExpensesAmount
FROM transactions as t1
LEFT JOIN
...
)
UNION ALL
(SELECT IFNULL(t1.created, DATE(ex.created)), SUM(t1.amount), ex.amount
FROM transactions as t1
RIGHT JOIN
...
)
ORDER BY Date
I assume here that you really want a UNION ALL, and not a UNION. Note that in most other RDBMS you would have to use a formal subquery to apply an ORDER BY clause to the entire union query.

how to marge two sql results in one sql query?

I am working on a project where I need to write validation query to validate data.
so I have two tables 1. Input table(raw data) 2. Output table(Harmonized data)
Currently, as a validation query, I am using below two queries to fetch results & then copy both results into excel file to validate if there is any difference in data or not.
1 Query
Select Date,sum(Val),sum(Vol)
From Input_table
Group by Date
2 Query
Select Date,sum(Val),sum(Vol)
From Output_table
Group by Date
Is there any way where I can put both these results in one query and also create one calculated column like.... (sum(Input_table.VAL)-sum(Output_table.VAL)) as Validation_Check.
So output will be like:
Date | sum(Input_table.Val) | sum(Output_table.Val) | Validation_Check
thanks.
It looks like you need to full join your results like:
select
ifnull(I.[Date], O.[Date]) as Date,
I.Val as Input_Val,
O.Val as Output_Val,
ifnull(I.Val, 0) - ifnull(O.Val, 0) as Validation_Check
from
(
Select Date,sum(Val) as Val,sum(Vol) as Vol
From Input_table
Group by Date
) as I
full outer join
(
Select Date,sum(Val) as Val,sum(Vol) as Vol
From Output_table
Group by Date
) as O on O.[Date] = I.[Date]
Use UNION. This will join two query on the condition that the two query have the same datatypes in the columns.
Use this Statement:
select Date, sum(Val), sum(Vol) from (
Select Date,Val,Vol
From Input_table
union
Select Date,Val,Vol
From Input_table
)
Group by Date
This will concat the data of both tables in the inner select and then Group it to one result
SELECT Date, SUM(VAL) as SUM_VAL, SUM(VOL) as SUM_VOL, SUM(VAL-VOL) as Validation_Check from
(Select Date,val,vol
From Input_table
UNION ALL
Select Date,val, vol
From Output_table
) X
group by Date
I suggest using a UNION ALL instead of a UNION here since there may be similar results fetched from both queries.
For example, your query 1 has a result like
May 01, 2017 | 5 | 5
and your query 2 has a result with the same values
May 01, 2017 | 5 | 5
If you use union, you'd only get 1 instance of
May 01, 2017 | 5 | 5
instead of 2 instances of
May 01, 2017 | 5 | 5
May 01, 2017 | 5 | 5
If your MySQL Supports FULL JOIN then you can use
SELECT
IFNULL(a.Date, b.Date) AS Date,
SUM(IFNULL(a.Val, 0)) AS Input_Val_Sum,
SUM(IFNULL(b.Val, 0)) AS Output_Val_Sum,
SUM(IFNULL(a.Val, 0) - IFNULL(b.Val, 0)) AS Validation_Check
FROM Input_table AS a
FULL OUTER JOIN Output_table AS b
ON a.Date = b.Date
GROUP BY IFNULL(a.Date, b.Date)

Order By month and Year for 2 columns in mysql

Employee table is listed below...
Name DOJ DOL
............ ............... ............
Ram 2014-01-12 2014-02-12
Kiran 2014-02-05 2014-07-05
Jhon 2014-01-25 2014-10-01
Expected Output is....
Month Joining_count Leaving_count
........... ................ .................
Jan-2014 2 0
Feb-2014 1 1
. . .
. . .
. . .
I tried with below Mysql Query but i am not able get expected output
please help me
SELECT monthname(current_date) as month,
count( `DATE_OF_JOINING`) as 'Joining_count' ,
count( `DATE_OF_LEAVING`) as 'leaving_count' ,
group by year(`DATE_OF_JOINING`),month('DATE_OF_JOINING`),
year(`DATE_OF_LEAVING),month(`DATE_OF_LEAVING)
You are performing two different aggregations on the same data - so you'd need two aggregate queries joined.
Unfortunately, mysql doesn't have a full outer join, so it's a bit of a hassle to handle both months where someone left but nobody joined and months somebody joined by nobody left. I solves this with three joins - one query to get all the possible dates, and another two for each aggregation, although there are other ways.
SELECT my_table.d, COALESCE(join_count, 0), COALESCE(leave_count, 0)
FROM (SELECT DISTINCT DATE_FORMAT(doj, '%b-%y') AS d
FROM my_table
UNION
SELECT DISTINCT DATE_FORMAT(dol, '%b-%y')
FROM my_table) dates
LEFT JOIN (SELECT DATE_FORMAT(doj, '%b-%y') d, COUNT(*) AS join_count
FROM my_table
GROUP BY DATE_FORMAT(doj, '%b-%y')
) joins ON dates.d = joins.d
LEFT JOIN (SELECT DATE_FORMAT(dol, '%b-%y') d, COUNT(*) AS leave_count
FROM my_table
GROUP BY DATE_FORMAT(dol, '%b-%y')
) leaves ON dates.d = leaves.d
Basically, you need two queries, one for grouping the joining dates and one for the leaving dates. You can combine both results using UNION ALL and treat the combined result as a new table and select (and SUM) the values then.
SELECT
s.month,
SUM(s.Joining_count) AS Joining_count,
SUM(s.Leaving_count) AS Leaving_count
FROM
(
SELECT
DATE_FORMAT(doj, '%b-%y') as `month`,
COUNT(ej.doj) as 'Joining_count',
0 AS 'Leaving_count'
FROM employee ej
GROUP BY `month`
UNION ALL
SELECT
DATE_FORMAT(dol, '%b-%y') as `month`,
0 as 'Joining_count',
COUNT(el.dol) as 'Leaving_count'
FROM employee el
GROUP BY `month`
) s
GROUP BY s.`month`;
Output will be
month Joining_count Leaving_count
---------------------------------------------
Feb-2014 1 1
Jan-2014 2 0
Jul-2014 0 1
Oct-2014 0 1