在 PL/SQL 程序中遇到问题

问题描述 投票:0回答:2

我有一张表(pay_period)如下

付款周期

period_id   list_id    start_date    end_date    price
1           100        2017-01-01    2017-08-31  100
2           100        2017-09-01    2017-12-31  110
3           101        2017-01-01    2017-08-31  75

现在我有list_id、checkin_date、checkout_date

list_id          100
checkin_date     2017-08-25
checkout_date    2017-09-10

我需要计算从入住日期到结帐日期期间的清单价格。 因此计算应该是

7 * 100 + 10 * 110

我想用for循环来做,如果有其他更好的方法,你能建议吗?

plsql period
2个回答
0
投票
  1. 您必须查看 checkin_date 和 checkout_date 是否属于同一 period_id。 1.1 如果是,则将价格乘以天数。 1.2 如果不是,您已经计算了 checkin_day 到周期 1 结束之间的天数,并乘以相应的价格,然后对 checkout_day 和下一个周期开始进行同样的操作。

注意:我猜想每个 list_id 可能有超过 2 个价格。例如:

period_id   list_id    start_date    end_date    price
1           100        2017-01-01    2017-04-30  100
2           100        2017-05-01    2017-09-30  110
3           100        2017-10-01    2017-12-31  120
4           101        2017-01-01    2017-08-31  75

计算周期为:

list_id          100
checkin_date     2017-03-01
checkout_date    2017-11-10

在这种情况下,是的,解决方案是有一个 CURSOR 来保存 list_id 和 period 的价格;循环遍历它并将 checkin_date 和 checkout_date 与每条记录进行比较。

最好的, 米克库图。


0
投票

您可以执行以下操作以获得更简洁的代码。虽然它是纯粹的sql,但我使用了一个函数来使其代码更好理解。

创建一个通用的

function
,它可以获取 2 个不同日期范围内重叠的天数。

CREATE OR REPLACE FUNCTION fn_count_range 
( p_start_date1 IN DATE, 
p_end_date1   IN DATE, 
p_start_date2 IN DATE, 
p_end_date2 IN DATE ) RETURN NUMBER AS 

v_days NUMBER;

BEGIN 
IF p_end_date1 < p_start_date1 OR p_end_date2 < p_start_date2 THEN 
 RETURN 0;
END IF;

SELECT COUNT(*) INTO v_days
FROM (
        (SELECT p_start_date1 + LEVEL - 1
         FROM dual CONNECT BY LEVEL <= p_end_date1 - p_start_date1 + 1 ) INTERSECT
        (SELECT p_start_date2 + LEVEL - 1
         FROM dual CONNECT BY LEVEL <= p_end_date2 - p_start_date2 + 1 ) );

RETURN v_days;

END;

/

现在,您计算总价的查询已简化。

WITH lists ( list_id,
             checkin_date,
             checkout_date) AS
  ( SELECT 100,
           TO_DATE('2017-08-25','YYYY-MM-DD'),
           TO_DATE('2017-09-10','YYYY-MM-DD')
   FROM dual) --Not required if you have a lists table.
SELECT l.list_id,
       SUM(fn_count_range(start_date,end_date,checkin_date,checkout_date) * price) total_price
FROM pay_period p
JOIN lists l ON p.list_id = l.list_id
GROUP BY l.list_id;
© www.soinside.com 2019 - 2024. All rights reserved.