如何编写程序来获得我想要的输出?

时间:2016-02-25 10:36:43

标签: sql oracle plsql

现有数据:

A              VALID_FROM    VALID_TO
------------   -----------   -----------
ARN-1          01-APR-2015   31-DEC-9999
ARN-1          01-MAY-2015   31-DEC-9999
ARN-1          01-JUN-2015   31-DEC-9999 

必需的输出:

A              VALID_FROM    VALID_TO
------------   -----------   -----------
ARN-1          01-APR-2015   30-APR-2015
ARN-1          01-MAY-2015   31-MAY-2015
ARN-1          01-JUN-2015   31-DEC-9999

如何编写Oracle PL / SQL过程来获取此输出?

3 个答案:

答案 0 :(得分:1)

不需要 PL / SQL ,您可以在纯 SQL 中执行此操作。

您需要 LAST_DAY 功能才能获取该VALID_FROM列中日期值的当月最后一天。 ROW_NUMBER 只是为了处理您需要魔法日期31-DEC-9999的最大日期情况。

SQL> WITH sample_data AS(
  2  SELECT 'ARN-1' A, DATE '2015-04-01' VALID_FROM, DATE '9999-12-31' VALID_TO FROM dual
  3  UNION ALL
  4  SELECT 'ARN-1' A, DATE '2015-05-01' VALID_FROM, DATE '9999-12-31' VALID_TO FROM dual
  5  UNION ALL
  6  SELECT 'ARN-1' A, DATE '2015-06-01' VALID_FROM, DATE '9999-12-31' VALID_TO FROM dual
  7  UNION ALL
  8  SELECT 'ARN-1' A, DATE '2015-07-01' VALID_FROM, DATE '9999-12-31' VALID_TO FROM dual
  9  )
 10  -- end of sample_data mimicking real table
 11  SELECT a,
 12    valid_from,
 13    CASE
 14      WHEN rn = 1
 15      THEN DATE '9999-12-31'
 16      ELSE valid_to
 17    END valid_to
 18  FROM
 19    (SELECT A,
 20      valid_from,
 21      row_number() OVER(ORDER BY valid_from DESC) rn,
 22      last_day(valid_from) valid_to
 23    FROM sample_data
 24    )
 25  ORDER BY valid_from;

A     VALID_FROM  VALID_TO
----- ----------- -----------
ARN-1 01-APR-2015 30-APR-2015
ARN-1 01-MAY-2015 31-MAY-2015
ARN-1 01-JUN-2015 30-JUN-2015
ARN-1 01-JUL-2015 31-DEC-9999

SQL>

答案 1 :(得分:0)

你可能需要这样的东西:

insert into tableB
select A,
       valid_from,
       nvl(lead(valid_from)  over (partition by a order by valid_from asc) -1, valid_to)
from tableA

这将插入第二个表中的所有行,为每一行评估有效性的结束(如果存在);如果它不存在,则使用该行上已存在的结束日期。

答案 2 :(得分:0)

Oracle安装程序

CREATE TABLE table_name ( A, VALID_FROM, VALID_TO ) AS
SELECT 'ARN-1', DATE '2015-04-01', DATE '9999-12-31' FROM DUAL UNION ALL
SELECT 'ARN-1', DATE '2015-05-01', DATE '9999-12-31' FROM DUAL UNION ALL
SELECT 'ARN-1', DATE '2015-06-01', DATE '9999-12-31' FROM DUAL;

<强>更新

UPDATE table_name t
SET valid_to = ( SELECT NVL( next_valid_from, valid_to )
                 FROM   (
                   SELECT a,
                          valid_from,
                          LEAD( valid_from ) OVER ( PARTITION BY a ORDER BY valid_from )
                            - INTERVAL '1' SECOND -- Change to DAY if you prefer
                            AS next_valid_from,
                          valid_to
                   FROM   table_name
                 ) n
                 WHERE  t.a = n.a
                 AND    t.valid_from = n.valid_from
               );

<强>输出

SELECT * FROM table_name;

A     VALID_FROM            VALID_TO            
----- --------------------- ---------------------
ARN-1 2015-04-01 00:00:00   2015-04-30 23:59:59   
ARN-1 2015-05-01 00:00:00   2015-05-31 23:59:59   
ARN-1 2015-06-01 00:00:00   9999-12-31 00:00:00