Oracle 中的等效习语?

3 oracle google-bigquery

我正在阅读这篇关于Google BigQuery 的文章:

探索强大的 SQL 模式:ARRAY_AGG、STRUCT 和 UNNEST

他们使用了几个函数,我试图弄清楚 Oracle 等价物是什么(如果它们存在的话)。

我正在挖掘 Oracle 文档,发现类似于ARRAY_AGGOracle 中的一些内容,称为LISTAGG.

我一直没能找到是惯用当量STRUCTUNNEST

有没有STRUCTUNNEST我必须自己写的东西做同样的事情?

Mic*_*utz 8

技术翻译

在一个 RDBMS 中解决问题的技术并不总是能很好地转化为另一个。

我遇到了与文章中类似的代码的性能问题。因此,我的评论是“这种技术会降低 Oracle 的性能”。

我没有看到CAST(MULTISET())(Oracle 的 版本ARRAY_AGG)被过度使用。因此,在您获得晋升后,您的替代者可能无法维护该代码。

翻译术语

翻译是这样的

  • STRUCT在大数据中是TYPE在 Oracle 中
  • ARRAY_AGG在大数据中是CAST(MULTISET())在 Oracle 中
  • UNNEST在大数据中是TABLE()在 Oracle 中
  • UNNESTXML 数据XMLTABLE()在 Oracle 中
  • UNNESTJSON 数据JSON_TABLE()在 Oracle (12c+) 中

您无法即时创建结构。你必须提前定义它。

例子

创建单行结构:

create type emp_t as object (
  EMPNO             NUMBER(4),    
  ENAME             VARCHAR2(10) ,
  JOB               VARCHAR2(9)  ,
  MGR               NUMBER(4)    ,
  HIREDATE          DATE         ,
  SAL               NUMBER(7,2)  ,
  COMM              NUMBER(7,2)  ,
  DEPTNO            NUMBER(2)  
);
/
Run Code Online (Sandbox Code Playgroud)

基于上述创建一组行的结构:( nested table)

create type emp_tt as table of emp_t;
/
Run Code Online (Sandbox Code Playgroud)

使用 CAST(MULTISET())

select d.deptno
  ,cast(multiset(
           select * from scott.emp e where e.deptno=d.deptno
        ) as emp_tt) as emp_table
from dept d
;
Run Code Online (Sandbox Code Playgroud)

使用 TABLE()

with data as (
  select d.deptno
    ,cast(multiset(
             select * from scott.emp e where e.deptno=d.deptno
           ) as emp_tt) AS emp_table
  from dept d
)
select b.*
from data a, table( a.emp_table ) b
order by empno;
Run Code Online (Sandbox Code Playgroud)

甲骨文的解决方案

业务需求:我希望飓风第一次达到其最大类别及其位置。

“GROUP BY”的其他推断标识符除了飓风名称之外还包括季节、盆地、子盆地。

在 Oracle 中解决此问题的一种方法是使用 Analytics。

由于我无法访问飓风数据,因此我必须即兴发挥。

  select deptno as hurricane_name
        ,2017   as season
        ,'NA'   as basin
        ,'WP'   as subbasin
        ,sal    as category
        ,ename  as position
        ,rownum as time
  from scott.emp
Run Code Online (Sandbox Code Playgroud)

我们做的第一件事是使用解析函数RANK()category(降序)和time(升序)对所有行进行排名season,但按basinsubbasin、 和hurricane_name

  select h.*
    ,RANK() over (partition by season, basin, subbasin, huricane_name
                  order by category desc, time)
      as rank_score
  from huricane_data h
Run Code Online (Sandbox Code Playgroud)

最后,我们将只选择最好的 (rank_score=1)

select *
from analyized_data
where rank_score=1
order by season, basin, subbasin, hurricane_name, time
Run Code Online (Sandbox Code Playgroud)

把这一切放在一起

with hurricane_data as (
  select deptno as hurricane_name
        ,2017   as season
        ,'NA'   as basin
        ,'WP'   as subbasin
        ,sal    as category
        ,ename  as position
        ,rownum as time
  from scott.emp
), analyized_data as (
  select h.*
    ,RANK() over (partition by season, basin, subbasin, hurricane_name
                  order by category desc, time) rank_score
  from hurricane_data h
)
select *
from analyized_data
where rank_score=1
-- place season/basin/subbasin filters here
order by season, basin, subbasin, hurricane_name, time;
Run Code Online (Sandbox Code Playgroud)

  • @Jarrod `LAG` 和 `LEAD` 以及一般的窗口函数都很棒,并且是 Oracle 的典型惯用语。熟悉尝试从其他地方导入的本地习语要好得多,这条路线有很多痛苦。 (3认同)