MYSQL按子查询分组,但需要所有数据

时间:2019-12-13 09:05:15

标签: mysql sql join mariadb

我有两个表,一个是交易,另一个是费用

交易表:

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

费用表:

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

两个表的总和,我在下面写了对我来说很好的查询。

(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

输出:

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

但是现在,如果我想从两个表中获取所有金额而不求和。我缺少日期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

输出:

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

在日期2019-11-13缺少一笔交易。

预期结果:

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

在这里,我怎么能得到我想要的结果?

2 个答案:

答案 0 :(得分:2)

如果运行的是MySQL 8.0,则可以将row_number()分配给每个具有created分区的表的记录,然后创建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

如果两个表中的任何一个表中的日期都可能不存在于另一个表中,则它会有些复杂。基本上,我们需要模拟MySQL中不存在的full join。这是使用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

答案 1 :(得分:0)

如果您不想求和,就不应该分组。其他rdbms会对此引发错误。 不进行分组,您应该获得所有记录。

但是我想您不会得到理想的结果,因为这些练习将在2019-11-13并入这两项交易中

相关问题