Oracle SQL层次结构汇总

如何解决Oracle SQL层次结构汇总

我有一个TRANS表,其中包含以下记录:

TRANS_ID TRANS_DT     QTY    
1        01-Aug-2020  5
1        01-Aug-2020  1
1        03-Aug-2020  2
2        02-Aug-2020  1

预期输出:

TRANS_ID TRANS_DT     BEGBAL TOTAL END_BAL 
1        01-Aug-2020  0      6     6
1        02-Aug-2020  6      0     6      
1        03-Aug-2020  6      2     8
2        01-Aug-2020  0      0     0
2        02-Aug-2020  0      1     1      
2        03-Aug-2020  1      0     1

每个trans_id的起始余额为0(2020年8月1日)。对于后续的几天,期初余额是前一天的期末余额,依此类推。 我可以创建PL / SQL块来创建输出。是否可以在1条SQL语句中获得输出?

谢谢。

解决方法

使用CTE尝试以下脚本-

Demo Here

WITH CTE 
AS
(
    SELECT DISTINCT A.TRANS_ID,B.TRANS_DT
    FROM your_table A
    CROSS JOIN (SELECT DISTINCT TRANS_DT FROM your_table) B

),CTE2
AS
(
    SELECT C.TRANS_ID,C.TRANS_DT,SUM(D.QTY) QTY
    FROM CTE C
    LEFT JOIN your_table D 
        ON C.TRANS_ID = D.TRANS_ID 
        AND C.TRANS_DT = D.TRANS_DT
    GROUP BY C.TRANS_ID,C.TRANS_DT
    ORDER BY C.TRANS_ID,C.TRANS_DT
)

SELECT F.TRANS_ID,F.TRANS_DT,(    
    SELECT COALESCE (SUM(QTY),0) FROM CTE2 E 
    WHERE E.TRANS_ID = F.TRANS_ID AND E.TRANS_DT < F.TRANS_DT
) BEGBAL,0) FROM CTE2 E 
    WHERE E.TRANS_ID = F.TRANS_ID AND E.TRANS_DT = F.TRANS_DT
) TOTAL,0) FROM CTE2 E 
    WHERE E.TRANS_ID = F.TRANS_ID AND E.TRANS_DT <= F.TRANS_DT
) END_BAL 
FROM CTE2 F
,

您也可以这样做(我想它会快一点):Demo

with 
dt_between as (
  select mindt + level - 1 as trans_dt
  from (select min(trans_dt) as mindt,max(trans_dt) as maxdt from t)
  connect by level <= maxdt - mindt + 1
),dt_for_trans_id as (
  select *
  from dt_between,(select distinct trans_id from t)
),qty_change as (
  select distinct trans_id,trans_dt,sum(qty) over (partition by trans_id,trans_dt) as total,sum(qty) over (partition by trans_id order by trans_dt) as end_bal
  from t
  right outer join dt_for_trans_id using (trans_id,trans_dt)
)
select 
  trans_id,to_char(trans_dt,'DD-Mon-YYYY') as trans_dt,nvl(lag(end_bal) over (partition by trans_id order by trans_dt),0) as beg_bal,nvl(total,0) as total,nvl(end_bal,0) as end_bal
from qty_change q
order by trans_id,trans_dt

dt_between返回数据中min(trans_dt)max(trans_dt)之间的所有日期。

dt_for_trans_id将为您数据中的每个trans_id返回所有这些天。

qty_change会发现每天的差异(在您的示例中为TOTAL)和所有天的累计金额(在示例中为END_BAL)。

主选择从前一天取END_BAL并命名为BEG_BAL,它还会对最终输出进行一些格式化。

,

首先,您需要生成日期,然后需要通过TRANS_DT汇总您的值,然后使汇总数据与日期保持连接。获得所需总和的最简单方法是使用分析窗函数:

with dates(dt) as ( -- generating dates between min(TRANS_DT) and max(TRANS_DT) from TRANS
   select min(trans_dt) from trans
   union all
   select dt+1 from dates
   where dt+1<=(select max(trans_dt) from trans)
),trans_agg as ( -- aggregating QTY in TRANS
   select TRANS_ID,TRANS_DT,sum(QTY) as QTY
   from trans
   group by TRANS_ID,TRANS_DT
)
select -- using left join partition by to get data on daily basis for each trans_id:
   dt,trans_id,nvl(sum(qty) over(partition by trans_id order by dates.dt range between unbounded preceding and 1 preceding),0) as BEGBAL,nvl(qty,0) as TOTAL,nvl(sum(qty) over(partition by trans_id order by dates.dt),0) as END_BAL 
from dates
     left join trans_agg tr
          partition by (trans_id)
          on tr.trans_dt=dates.dt;

带有示例数据的完整示例:

alter session set nls_date_format='dd-mon-yyyy';
with trans(TRANS_ID,QTY) as (
select 1,to_date('01-Aug-2020'),5 from dual union all
select 1,1 from dual union all
select 1,to_date('03-Aug-2020'),2 from dual union all
select 2,to_date('02-Aug-2020'),1 from dual
),dates(dt) as ( -- generating dates between min(TRANS_DT) and max(TRANS_DT) from TRANS
   select min(trans_dt) from trans
   union all
   select dt+1 from dates
   where dt+1<=(select max(trans_dt) from trans)
),TRANS_DT
)
select 
   dt,0) as END_BAL 
from dates
     left join trans_agg tr
          partition by (trans_id)
          on tr.trans_dt=dates.dt;
,

您可以使用递归查询来生成整个日期范围,将其与单独的cross join列表一起tran_id,然后将表中带有left join。最后一步是聚合和窗口函数:

with all_dates (trans_dt,max_dt) as (
    select min(trans_dt),max(trans_dt) from trans group by trans_id
    union all
    select trans_dt + interval '1' day,max_dt from all_dates where trans_dt < max_dt
)
select
    i.trans_id,d.trans_dt,coalesce(sum(sum(t.qty)) over(partition by i.trans_id order by d.trans_dt),0) - coalesce(sum(t.qty),0) begbal,coalesce(sum(t.qty),0) total,0) endbal
from all_dates d
cross join (select distinct trans_id from trans) i
left join trans t on t.trans_id = i.trans_id and t.trans_dt = d.trans_dt
group by i.trans_id,d.trans_dt
order by i.trans_id,d.trans_dt

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-