【问题标题】:How to generate sum report from joining of 2 tables where the join key is not unique如何从连接键不唯一的 2 个表的连接中生成总和报告
【发布时间】:2013-03-03 16:28:44
【问题描述】:

我有 2 个表格来收集积分事件记录。

CREATE TABLE report_one
(
  date timestamp,
  point_id bigint,
  income int
 )
CREATE TABLE report_two
(
  date timestamp,
  point_id bigint,
  spent int
 )

我想生成一个总和报告(和其他报告)。我想使用join,因为我需要支持分页、排序...

问题是连接键(报告的点 id)不是 1:1 ,所以我得到的同一行不止一个。

insert into report_one values('2013-1-1',1,1)
insert into report_two values('2013-1-1',1,1)
insert into report_two values('2013-1-2',1,1)

select * from report_one r1 left join report_two r2 on r1.point_id  = r2.point_id

将有 2 行表 report_one ,但总共我只需要一个。 我希望能够创建表之间某种连接的视图,其中每行只有一次。

**我想要这样的输出:

1 (pid) , 1,1,0,0 - 这个来自 report_one

1 (pid) ,0,0,1,1——来自report_two

1 (pid) ,0,0,1,1 -- 这来自 report_two **

Union all 可以很好,但我在两个表中没有相同的列类型。

附言。真正的表格有很多列,而 pk 不止一列,我只是为了这个问题而简单

【问题讨论】:

  • 您要查找的预期输出数据是什么?
  • 我添加了预期的输出
  • 您为什么不能有一个report_id 而不是为每个报告创建表格?那你就不用加入了,可以按report_id分组吗?

标签: sql join


【解决方案1】:

为什么不试试下面的。

CREATE TABLE report
(
  report_id bigint,
  date varchar(20),
  point_id bigint,
  amount int,
  amount_type varchar(20)
 );

那么

   insert into report values (1,'2013-01-01',1,1,'income');
   insert into report values (2,'2013-01-01',1,1,'expense');
   insert into report values (2,'2013-01-02',1,1,'expense');

终于

SELECT report_id,amount_type,SUM(point_id) FROM report GROUP BY report_id,amount_type

输出将对每个报告/amount_type 的 point_id 求和,然后更容易绘制每个日期范围等的统计信息,并且创建表和连接的开销也将最小化。

输出:SQL Fiddle Demo

【讨论】:

  • 我无法更改表格。这就是我所拥有的 - 2 个保存事件数据的表。
【解决方案2】:

我认为这对我有用:

select date d1,point_id p1,0 income ,spent spent from report_one
union ALL
select date d2,point_id p2,income,0 spent from report_two

我不必有零。我为演示添加了它们,说明它们的列不是来自同一类型

【讨论】:

    【解决方案3】:

    您可以先按 point_id 对表进行分组,为所需字段选择更合适的聚合函数,然后相互连接:

    select r1.point_id, r1.date, r1.income, r2.spent
    from
    (
       select point_id, max(date) date, sum(income) income
       from report_one
       group by point_id
    ) r1 
        inner join
        (
           select point_id, max(date) date, sum(spent) spent
           from report_two
           group by point_id
        ) r2 on r1.point_id = r2.point_id
    

    还有,UNION方式:

    select point_id, date, income sum, 1 is_income
       from report_one
    union all
    select point_id, date, spent sum, 0 is_income
           from report_two
    

    【讨论】:

    • 10x,但我想要查看所有记录。在视图上我做总数,因为有一些报告我需要做。所以首先需要生成包含 2 个表中所有记录的视图。
    • 那么 UNION 似乎更合适。 select point_id, max(date) date, sum(income) sum, 1 is_income from report_one union all select point_id, max(date) date, sum(spent) sum, 0 is_income from report_two
    • 答案中的“也联合方式”与您在评论中写的不一样,这是正确的,为什么需要is_income标志?
    • 在评论中我忘记删除分组函数(最大值,总和)。我无法更改评论,所以我决定添加它来回答。 "is_income" 字段用于区分所赚的钱和花费的钱,这将在联合后的一个字段 "sum" 中。
    • 我认为拥有这个标志不是一个好方法,看看我在自己的回答中做了什么。
    猜你喜欢
    • 1970-01-01
    • 2013-12-05
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多