【问题标题】:Extracting several math operations outputs from single select query从单个选择查询中提取多个数学运算输出
【发布时间】:2020-09-17 10:09:45
【问题描述】:

我需要合并三个表以进行分析:活动、学生和账单。

“活跃”包含活跃学生的记录和他们活跃的科目,列:id(学生 id)int、时间(他们活跃的时间)时间戳和主题(活跃的主题)-文本

id   time                  subject
1    2020-04-23 06:53:30   Math
2    2020-05-13 09:51:22   Physics
2    2020-02-26 17:34:56   History

'Students' 是海量数据库,包含:id (student id) int, group(学生被分配到 a/b 测试的组)- text

id   group     
1    A       
2    B 
3    A
4    A

“账单”记录学生购买的课程的所有交易:id(学生 ID)int、sale_time(学生购买课程的时间)时间戳、主题(购买课程的主题)文本、金钱(支付的金额)。

id     sale_time              subject     money
1      2020-03-04 08:54:55    Math        4300
1      2020-04-08 20:43:56    Math        3200
2      2020-05-09 13:43:12    Law         8900

基本上,我们有一个学生数据库(学生),其中一些购买了课程(账单)。而一些购买的人仍然活跃(活跃)。

我需要编写一个单一的查询,我可以提取以下按它们属于 A 组还是 B 组分组:

average revenue per user: sum (money) / count (distinct Students.id)
average revenue per active user: sum (money) / count (distinct Active.id)
conversion rate (%): count (distinct Bills.id) / count (distinct Students.id)
conversion rate (active) (%): count (distinct Bills.id) / count (distinct Active.id)
conversion rate (Math) (%) (count (distinct Bills.id) where Bills.subject = Math) / (count (distinct Active.id) where Active.subject = Math)

所有这些都在一个查询中!

我用过

select sum (money)/count (distinct Students.id)
  from Students
     left join Bills using (id)
        left join Active using (id)
            group by group, Students.id

但我不知道如何在使用过滤器选择后立即进行这些数学计算。

请帮忙!

SQL 小提琴:https://www.db-fiddle.com/f/NPQR6aBf8H36XvrefJY2J/0

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    你只需要这个:

    select s.[group], sum (money)/  NULLIF( count (distinct s.id),0) as 
       AvgPerUser,
       sum (money) /  NULLIF(count (distinct a.id),0) as AvgActUser,
       count (distinct b.id) /  NULLIF(count (distinct a.id),0) as CovRate,
       count (distinct b.id) /  NULLIF(count (distinct a.id),0) as ConActRate,
       (select count(distinct b2.id) from Bills as b2 where b2.subject = 'Math') /  
       NULLIF((select count ( distinct a2.id) from Active as a2  where a2.subject 
       ='Math'),0) as ConRateMath
       from Students as s
       left join Bills as b on s.id = b.id
        left join Active as a on s.id = a.id
            group by s.[group]
    

    【讨论】:

    • 不幸的是,您的查询计算了由“左连接”产生的重复值,因此这些输出不正确(FIddle:db-fiddle.com/f/NPQR6aBf8H36XvrefJY2J/0
    • 哦..我找出问题所在。如果您在我的查询的最后一行删除 s.id 就可以了 :)
    • 对不起,它不起作用。它汇总所有重复值以计算平均值,转换率计算不正确。组“B”没有值
    • 但是我创建了您的表格并添加了确切的值,然后我运行了查询并得到了正确的结果。看看这个s6.uplod.ir/i/00992/r5ns5xzvv8c3.jpg
    • 谢谢,但它在这里不起作用:db-fiddle.com/f/NPQR6aBf8H36XvrefJY2J/0
    【解决方案2】:

    我建议在加入之前删除重复项,然后使用窗口函数:

    select s.group, avg(b.money)as AvgPerUser,
           sum(b.money) /  nullif(count(a.id), 0) as AvgActUser,
           count(b.id) / nullif(count(s.id), 0) as CovRate,
           count(b.id) / nullif(count(a.id),0) as ConActRate,
           count(b.id) filter (where s.subject = 'Math') * 1.0 / count(*) filter (where s.subject = 'Math') as ConRateMath
    from Students s left join
         (select b.id, sum(money) as money
          from bills b
          group by b.id
         ) b
         on s.id = b.id left join
         (select distinct a.id from active a
         ) a
         on s.id = a.id
    group by s.group;  
    

    注意:我认为您不希望 s.idGROUP BY 中。那真的不会聚合任何东西。

    【讨论】:

    • 谢谢,但它写道'列 s.money 不存在'
    • @Sam。 . .我懂了。它位于bills。这就是为什么您需要沿维度进行预聚合的更多原因。
    • 错误:缺少表“b”的 FROM 子句条目。为了您的方便,这里摆弄一下生成的数据:db-fiddle.com/f/NPQR6aBf8H36XvrefJY2J/0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 2016-11-14
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多