Sql 如何编写一个程序以获得所需的输出?
现有数据:Sql 如何编写一个程序以获得所需的输出?,sql,oracle,plsql,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
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过程来获得此输出?您可能需要以下内容:
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
这将插入第二个表中的所有行,为每一行计算有效性结束(如果存在);如果不存在,则使用行中已存在的结束日期。不需要PL/SQL,您可以在纯SQL中执行 您需要使用LAST_DAY函数从
列获取VALID_中日期值的当月最后一天行号仅用于处理最长日期的情况,即您需要神奇的日期9999年12月31日
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>
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
更新:
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
输出:
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
您还没有解释要做什么,也没有解释如何将有效\u设置为
日期的逻辑。总是在下一次开始前一天从开始生效?如果间隔不是一个月(缺少一行,或者不是从1号开始),该怎么办?OP似乎希望最后一个定义的期间保留神奇的值结束日期。虽然它不是很清楚…我认为这是一个打字错误,但如果OP希望这样,那么它将需要一个窗口功能。我看到了使用滞后/超前的其他答案,但我认为最后一天更合适,只是最大有效时间应该有神奇的日期。除非记录中有差距,或者它们不总是从1号开始。但目前尚不清楚这是否可能发生,或者如果发生,产出应该是什么。如果从
开始的有效日期是每个月的第一天,那么是的,只是不确定可以从有限的信息中安全地假定这一点*8-)是的,你是对的。就目前的问题范围而言,我已经编辑了我的答案。