Oracle 10g:如何有条件地将表A中的行插入到B中

时间:2018-05-23 12:32:44

标签: sql oracle oracle10g

得到一张像这样的表

|----------|----------|
|  DT      |  FLAG    |
|----------|----------|
| 2015-MAY |  E       |
| 2015-JUN |  H       |
| 2015-OCT |  S       |
| 2016-FEB |  E       |
|----------|----------|

我想在B中插入A的flag聚合数据与给定模式匹配的行。

此查询执行以下聚合:

     SELECT
            (lag(rep.flag) over (ORDER BY rep.DECLARATIONPERIOD) || flag) AS ERRCODE,
            (lag(rep.DECLARATIONPERIOD) over (ORDER BY rep.DECLARATIONPERIOD)) AS DECFROM, DECLARATIONPERIOD AS DECTO
    FROM  XE_ERR_OVLP rep;

结果(表A):

|----------|---------------|---------------|
|  FLAG    |  DTFROM       |  DTFTO        |
|----------|---------------|---------------|
|  VV      |    2014-02-01 |    2014-03-01 |
|  VE      |    2014-03-01 |    2014-04-01 |
|  EE      |    2014-04-01 |    2014-05-01 |
|  EV      |    2014-05-01 |    2014-06-01 |
|  VV      |    2014-06-01 |    2014-07-01 |
|  VS      |    2014-07-01 |    2014-08-31 |
|----------|---------------|---------------|

请参阅demo

我想从表(A)中填充此表(B),以获取仅匹配特定值的FLAG值(例如EEHH):

|----------|---------------|---------------|
|  FLAG    |  DTFROM       |  DTFTO        |
|----------|---------------|---------------|
|  ...     | ...           | ...           |
|----------|---------------| --------------|

如果可能的话(聚合时)。

任何有关正确欢迎的建议

2 个答案:

答案 0 :(得分:1)

这就是你所描述的:

insert into b (dt, flag)
    select dt, flag
    from a
    where flag in ('E', 'H');

我不确定它与查询的关系,这些查询比您的示例数据和问题复杂得多。

答案 1 :(得分:1)

这是一个操作顺序问题:注意我们在对其进行过滤之前使用派生表来实现分析的结果。在执行where子句之前,SELECT不会执行,因此where子句不知道ERRCODE别名。

可以在网上找到SQL操作顺序,我不会去restate;但在这种情况下,下面是重要的元素/顺序。您将注意到该链接明确说明了您的问题:窗口函数...不可用于WHERE子句,该子句在评估窗口函数之前发生。

  1. FROM
  2. WHERE
  3. 选择
  4. 这意味着WHERE子句还不知道ERRCODE;所以它不能限制它。这通常通过使用派生表/内联视图或公用表表达式来解决。

    这是内联视图/派生表:

       INSERT INTO XE_ERR_RANG
          SELECT Z.* 
          FROM (SELECT EMPLOYERID
                     , EMPLOYEEID
                     , lag(DECLARATIONPERIOD) over (ORDER BY DECLARATIONPERIOD) AS DECFROM
                     , DECLARATIONPERIOD AS DECTO
                     , lag(flag) over (ORDER BY DECLARATIONPERIOD) || flag AS ERRCODE
                FROM XE_ERR_OVLP) Z
          WHERE Z.ERRCODE in ('HS', 'SE'); 
    

    使用公用表表达式(CTE)的替代方法:

    未经测试:但你说oracle 10g似乎支持CTE;但不是递归;如果它支持CTE之前的插入语法,那么应该工作...

    INSERT INTO XE_ERR_RANG
    
    WITH Z as (SELECT EMPLOYERID
                    , EMPLOYEEID
                    , lag(DECLARATIONPERIOD) over (ORDER BY DECLARATIONPERIOD) AS DECFROM
                    , DECLARATIONPERIOD AS DECTO
                    , lag(flag) over (ORDER BY DECLARATIONPERIOD) || flag AS ERRCODE
               FROM XE_ERR_OVLP)
    
    SELECT * 
    FROM Z
    WHERE ERRCODE in ('HS', 'SE');