繁体   English   中英

在 Oracle PL/SQL 中复制 SAS DO 循环

[英]Replicating SAS DO loop in Oracle PL/SQL

我正在尝试将 DO 循环从 SAS 复制到 Oracle PL/SQL。 基本上,这个 DO 循环遍历表并为单个员工创建多行。 我对 PL/SQL 中的循环不是很熟悉,因此感谢您提供任何帮助。 除了创建多个表然后组合它们之外,我想不出任何方法来重新创建它。 我会在最后解释更多关于我的想法; 现在,请查看数据示例以及 SAS DO 循环正在执行的操作。

HIST_EMPLOYEE 表:

+----------+----------+--------+
| EMPLOYEE | START_YR | END_YR |
+----------+----------+--------+
| JOHN     |     2013 |   2014 |
| WILL     |     2012 |   2016 |
| MARK     |     2012 |   2012 |
+----------+----------+--------+

SAS 中的 DO 循环:

DATA HIST_EMPLOYEE_NEW;
SET HIST_EMPLOYEE;
    DO YR = START_YR TO END_YR;
OUTPUT;
END;
RUN;

输出:

+----------+----------+--------+------+
| EMPLOYEE | START_YR | END_YR |  YR  |
+----------+----------+--------+------+
| JOHN     |     2013 |   2014 | 2013 |
| JOHN     |     2013 |   2014 | 2014 |
| WILL     |     2012 |   2016 | 2012 |
| WILL     |     2012 |   2016 | 2013 |
| WILL     |     2012 |   2016 | 2014 |
| WILL     |     2012 |   2016 | 2015 |
| WILL     |     2012 |   2016 | 2016 |
| MARK     |     2012 |   2012 | 2012 |
+----------+----------+--------+------+

我解决这个问题的方法(这在任何方面都没有效率)是创建在END_YR < START_YR + i上过滤的表,其中i is from 0 to 10 ,然后创建YR列,然后组合所有表。 我可以进一步讨论这个,但我已经觉得这是做事的糟糕方式。

只需制作一张 YR 值从最小值到最大值不等的表格,然后加入该表格。

所以像:

with years as (
        select 2012 + rownum - 1 as YR
        from dual
        connect by rownum < (2016 - 2012)
    )
select a.*,b.YR
from HIST_EMPLOYEE a
  inner join years b
  on a.start_yr <= b.yr and b.yr <= a.end_yr
;

只需更改下限 (2012) 和上限 (2016) 即可更改您想要生成的年数。

看到这个问题: 如何在 Oracle 中填充日历表?

这是一种方法。 “with”子句称为公共表表达式 (CTE),它只是为每个条目设置具有唯一 id 的测试数据。

查询使用 CONNECT BY,可以将其视为返回的每一行的循环机制。 它带有一个名为“level”的变量,每次迭代都会增加一次(从 1 开始)。 定义每行“循环”多少次是表达式 (end_yr-start_yr+1)。 对于 JOHN,我们需要循环 2 次,因为我们需要 2 行,WILL 5 行等。“PRIOR ID”子句有助于处理每个原始行的多行。

with hist_employee(id, employee, start_yr, end_yr) as (
  select 1, 'JOHN', 2013, 2014 from dual union all
  select 2, 'WILL', 2012, 2016 from dual union all
  select 3, 'MARK', 2012, 2012 from dual
)
select employee, start_yr, end_yr, (start_yr + (level-1)) as YR
from hist_employee
connect by level <= end_yr-start_yr+1
  and prior id = id
  and prior sys_guid() is not null
order by id;


EMPLOYEE   START_YR     END_YR         YR
-------- ---------- ---------- ----------
JOHN           2013       2014       2013
JOHN           2013       2014       2014
WILL           2012       2016       2012
WILL           2012       2016       2013
WILL           2012       2016       2014
WILL           2012       2016       2015
WILL           2012       2016       2016
MARK           2012       2012       2012

8 rows selected.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM