SQL:在不使用 ROWS UNBOUNDED PRECEDING 的情况下运行相同事务的总计

Posted

技术标签:

【中文标题】SQL:在不使用 ROWS UNBOUNDED PRECEDING 的情况下运行相同事务的总计【英文标题】:SQL : Running Total for identical transactions Without Using ROWS UNBOUNDED PRECEDING 【发布时间】:2017-08-17 18:15:18 【问题描述】:

我正在尝试计算“司机在特定日期赚取的出租车费”的总和。最初在 Netezza 上测试,现在尝试在 spark-sql 上编写代码。

但是,如果对于结构为 ((driver,day) --> fare) 的两行,如果 'fare' 值是相同,则 running_total 列始终显示 最终总和 !如果所有票价 不同 ,则计算得非常完美。有没有办法在不使用 rowsBetween(start,end) 的情况下实现这一点(在 ANSI SQL 或 Spark 数据帧中)?

样本数据:

    driver_id<<<<>>>>date_id  <<<<>>>>fare
    10001           2017-07-27        500
    10001           2017-07-27        500
    10001           2017-07-30        500
    10001           2017-07-30        1500

我触发的 SQL 查询来计算运行总计

    select driver_id, date_id, fare , 
    sum(fare)
    over(partition by date_id,driver_id 
    order by date_id,fare ) 
    as run_tot_fare
    from trip_info
    order by 2

结果:

  driver_id <<<<>>>> date_id <<<<>>>> fare <<<<>>>> run_tot_fare
  10001              2017-07-27       500           1000 --**Showing Final Total expecting 500**
  10001              2017-07-27       500           1000
  10001              2017-07-30       500           500 --**No problem here**
  10001              2017-07-30       1500          2000

如果有人可以告诉我,我做错了什么,如果不使用 Rows Unbounded Precedings/rowsBetween(b,e) 可以实现,那么我非常感谢。提前致谢。

【问题讨论】:

你能用range between unbounded preceding and current row吗? @gordon linoff 1. 理想情况下,我想避免这种情况,因为当我尝试时,spark-job 的速度几乎慢了 5 倍。另外请告诉我如何在 sql/spark-sql 中做到这一点。谢谢。 【参考方案1】:

SQL 中的传统解决方案是使用range 而不是rows

select driver_id, date_id, fare , 
       sum(fare) over (partition by date_id, driver_id 
                       order by date_id, fare
                       range between unbounded preceding and current rows
                      ) as run_tot_fare
from trip_info
order by 2;

如果没有,两级窗口函数或聚合和连接:

select driver_id, date_id, fare,
       max(run_tot_fare_temp) over (partition by date_id, driver_id ) as run_tot_fare
from (select driver_id, date_id, fare , 
             sum(fare) over (partition by date_id, driver_id 
                             order by date_id, fare
                            ) as run_tot_fare_temp
      from trip_info ti
  ) ti
order by 2;

max() 假定票价永远不会是负数。)

【讨论】:

你为什么用order by 2而不是date_id? @Hogan。 . .因为我复制了 OP 的查询,而外部 order by 与问题无关。 啊,我当然没有看所有OP的代码。 @Gordon Linoff --- 我尝试了 max() 解决方案,它根本不起作用,而且我相信你试图说 max(run_tot_fare_temp) over( date_id,driver_id) .无论如何,为了避免使用rowsBetween(),我将过滤我的输入表(数据框)以查找在同一驱动程序/date_id组中具有重复组合并且具有不同值的记录,然后运行一个带有rowsBetween()和一个没有......我希望它不会导致 spark 尝试保留所有以前的记录。

以上是关于SQL:在不使用 ROWS UNBOUNDED PRECEDING 的情况下运行相同事务的总计的主要内容,如果未能解决你的问题,请参考以下文章

Oracle开发之窗口函数 rows between unbounded preceding and current row

SQL性能调优

使用 SQL_CALC_FOUND_ROWS 的 Mysql 全文搜索性能

使用limit查询的同时取得总的记录数:SQL_CALC_FOUND_ROWS和FOUND_ROWS()

MySQL FOUND_ROWS() 方法的 SQL 等效项是啥?

我必须在调用* sql.Tx.Rollback()之前调用* sql.Rows.Close()吗?