合并多个表以生成视图

时间:2019-01-19 17:34:00

标签: php mysql sql

我有4张桌子,3张用于进钱,1张用于进钱

credittable1

uid | amnt | dat
1   | 50   |31-02-2016
2   | 40   |22-03-2017
...and so on

credittable2

uid | amnt | dat
1   | 60   |01-03-2016
2   | 20   |22-02-2017
...and so on

credittable3

uid | amnt | dat
1   | 70   |03-03-2016
2   | 10   |21-03-2017
...and so on 

可借记

uid | amnt | dat
1   | 120  |12-04-2016
2   | 80   |25-02-2017
...and so on 

我需要将所有4张表组合在一起,以看上去像是贷方和借方的帐簿以及该交易在每个用户按日期排序的余额。例如,我要打印uid 1的账簿,那么他的所有交易都应像账簿一样按信贷或借记交易发生的日期以及该交易的余额金额打印(就像银行存折一样) )。

所有表都非常繁琐,有大量记录,因此我正在寻找一种快速(性能良好)的解决方案。

最终实现需要在 Codeigniter 中完成。

用户可能在表1中获得10个(或任意数量)交易,依此类推在所有表中。每个表中每个用户的记录数可能会有所不同。

输出看起来像这样:

uid | date | credit | debit | balance amount

请提出实现此目标的方法。我无法决定是否应该使用Joins或其他策略来完成该操作。

3 个答案:

答案 0 :(得分:1)

您可以union all四个表,并取反debittable中的金额:

SELECT uid, amt,      dat FROM credittable1 UNION ALL
SELECT uid, amt,      dat FROM credittable2 UNION ALL
SELECT uid, amt,      dat FROM credittable3 UNION ALL
SELECT uid, -1 * amt, dat FROM debittable

答案 1 :(得分:0)

所有表上的UNION ALL为您提供了基础(您应该考虑重新设计架构,从一开始就只使用一个这样的表)。

对于余额,可以使用子查询,该子查询获取“上一个”金额的总和。这里的“上一个”是指日期小于或等于当前预订日期的预订。由于一天中可能会有更多的预订,因此我们需要另一个标准来区分它们。这就是sno发挥作用的地方-它也必须小于或等于当前值。为了确保sno在整个集合中(而不只是它来自的表)是唯一的,我们会添加一个唯一的表标识符。

在MySQL 8.0中,可以使用窗口加总和来简化操作。但是我认为您使用的是次要版本。

SELECT x.amnt,
       x.dat,
       (SELECT coalesce(sum(amnt), 0)
               FROM (SELECT concat('c1-', sno) sno
                            amnt,
                            dat
                            FROM credittable1
                            WHERE uid = 1
                     UNION ALL
                     SELECT concat('c3-', sno) sno,
                            amnt,
                            dat
                            FROM credittable2
                            WHERE uid = 1
                     UNION ALL
                     SELECT concat('c3-', sno) sno,
                            amnt,
                            dat
                            FROM credittable3
                            WHERE uid = 1
                     UNION ALL
                     SELECT concat('d1-', sno) sno,
                            -1 * amnt,
                            dat
                            FROM debittable
                            WHERE uid = 1) y
               WHERE y.dat <= x.dat
                     AND y.sno <= x.sno) bal
       FROM (SELECT concat('c1-', sno) sno,
                    amnt,
                    dat
                    FROM credittable1
                    WHERE uid = 1
             UNION ALL
             SELECT concat('c2-', sno) sno,
                    amnt,
                    dat
                    FROM credittable2
                    WHERE uid = 1
             UNION ALL
             SELECT concat('c3-', sno) sno,
                    amnt,
                    dat
                    FROM credittable3
                    WHERE uid = 1
             UNION ALL
             SELECT concat('d1-', sno) sno,
                    -1 * amnt,
                    dat
                    FROM debittable
                    WHERE uid = 1) x
       ORDER BY x.dat;

答案 2 :(得分:0)

我想我会这样做以获得基本数据:

select uid, date, sum(credit) as credit, sum(debit) as debit
from ((select uid, dat amt as credit, 0 as debit
       from credittable1
      ) union all
      (select uid, dat amt as credit, 0 as debit
       from credittable2
      ) union all
      (select uid, dat amt as credit, 0 as debit
       from credittable3
      ) union all
      (select uid, dat, 0, - amt
       from debittable
      )
     ) ad
group by uid, dat
order by uid, date;

然后您可以使用变量获取余额:

select uid, date,
       (@b := if(@u = uid, @u + credit + debit,
                 if(@u := uid, credit + debit, credit + debit)
                )
       ) as balance
from (select uid, date, sum(credit) as credit, sum(debit) as debit
      from ((select uid, dat amt as credit, 0 as debit
             from credittable1
            ) union all
            (select uid, dat amt as credit, 0 as debit
             from credittable2
            ) union all
            (select uid, dat amt as credit, 0 as debit
             from credittable3
            ) union all
            (select uid, dat, 0, - amt
             from debittable
            )
           ) ad
      group by uid, date
      order by uid, date
     ) ud cross join
     (select @u := -1, @b := 0) balance;

或者在MySQL 8+中,您可以使用累积总和:

sum(debit + credit) over (partition by uid order by date)