Satu Sultana
Satu Sultana

Reputation: 537

MYSQL group by in subquery but need all data

I have two table , One is transactions and another is expenses

Transactions table :

id  amount  created
1   300     2019-10-01 00:00:00
2   200     2019-11-01 00:00:00
3   230     2019-11-13 00:00:00
4   130     2019-11-13 00:00:00

Expenses Table :

id  amount  created
1   600     2019-11-13 00:00:00

Summation amount for both table, I have written below query which is working fine for me.

(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)) ORDER BY Date

Output :

Date        ReceiveAmount   ExpensesAmount  
2019-10-01  300             NULL
2019-11-01  200             NULL
2019-11-13  360             600

But now if I want to fetch all amount from both table without summation. I am missing one transaction for date 2019-11-13.

(SELECT IFNULL(date(t1.created), date(ex.created)) as Date , t1.amount as ReceiveAmount,ex.amount as ExpensesAmount 
FROM transactions as t1
LEFT JOIN (
    SELECT 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, t1.amount as Receive,ex.amount as ExpensesAmount 
FROM transactions as t1

RIGHT JOIN (
    SELECT 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)) ORDER BY Date

Output :

2019-10-01  300     NULL
2019-11-01  200     NULL
2019-11-13  230     600

Here one transaction is missing for date 2019-11-13.

Expected result :

2019-10-01  300     NULL
2019-11-01  200     NULL
2019-11-13  230     600
2019-11-13  130     NULL

Here, How can I get my desire result ?

Upvotes: 3

Views: 72

Answers (2)

GMB
GMB

Reputation: 222622

If you are running MySQL 8.0, you could assign row_number()s to the records coming from each table with created partitions, and then make a left join:

select t.created, t.amount, e.amount
from (
    select 
        t.*, 
        row_number() over(partition by created order by id)  rn 
    from transactions t
) t
left join (
    select
        e.*, 
        row_number() over(partition by created order by id)  rn 
    from expenses e
) e
    on e.created = t.created and e.rn = t.rn

If any of the two tables may have dates that do not exist in th the other table, then it is a bit more complicated. Basically we need to emulate full join, which does not exist in MySQL. Here is one way to do it with union all:

select created, max(t_amount) t_amount, max(e_amount) e_amount
from (
    select 
        created,
        amount t_amount,
        null e_amount,
        row_number() over(partition by created order by id)  rn 
    from transactions
    union all
    select 
        created,
        null,
        amount,
        row_number() over(partition by created order by id)
    from expenses
) d
group by created, rn

Upvotes: 2

Turo
Turo

Reputation: 4924

If you dont't want to sum, you shouldn't group. Other rdbms would throw an error on this. Without grouping you should get all the records.

But i think you will not get the desired result, since the exepnses will be joined to both transactions on 2019-11-13

Upvotes: 0

Related Questions