【问题标题】:Populating Monthly cost to daily records将每月成本填充到每日记录
【发布时间】:2015-02-03 16:21:05
【问题描述】:

我有 3 列(日期、标志、成本) 日期从年初开始,标志是每日或每月以及费用。

对于每日价值,这很好。对于每月值,我想 将整个月标记值相加并除以该月的天数。结果率,在整个月内填充它

Date      Flag      Cost
1/1/2014        
1/2/2014  DAILY     10
1/3/2014  DAILY     15
1/4/2014  DAILY     56
1/5/2014  DAILY     22
1/6/2014  DAILY     32
1/7/2014        
1/8/2014  MONTHLY   3500
1/9/2014        
1/10/2014

结果应该是


Date        Cost
1/1/2014    112.9032258 
1/2/2014    122.9032258 
1/3/2014    127.9032258 
1/4/2014    168.9032258 
1/5/2014    134.9032258 
1/6/2014    144.9032258 
1/7/2014    112.9032258 
1/8/2014    112.9032258 
1/9/2014    112.9032258 
1/10/2014   112.9032258 
          .
          .
          .
1/30/2014   112.9032258 
1/31/2014   112.9032258

【问题讨论】:

  • 一个月的总天数还是表中出现的天数并有任何费用?
  • 该月的总天数,未出现在表格中。如果是 1 月,则为 31 日。
  • 您能否同时获得同一月份的每日值和每月值?
  • 将月值拆分为日并将其添加到当前日成本后,结果不再考虑月值。例如,2014 年 1 月 2 日的每日费用为 10,当天拆分的每月供款为 112.9032258,因此每日总费用为 122.9032258。希望得到答案。
  • @szakwani 这对夫妇(日期,国旗)是独一无二的吗?或者你可以在同一个月有几个每月的费用?同一天的几个日常费用?

标签: sql oracle


【解决方案1】:

如果我理解得很好,这应该会给你“每月”值的平均每天:

SELECT "Cost" / EXTRACT(DAY FROM LAST_DAY("Date")) "cost_per_day",
       LAST_DAY("Date") "month"
FROM T
WHERE "Flag" = 'MONTHLY'

一旦你有了它,你的最终查询可以写成:

WITH monthly AS (
    SELECT "Cost" / EXTRACT(DAY FROM LAST_DAY("Date")) "cost_per_day",
           LAST_DAY("Date") "month"
    FROM T
    WHERE "Flag" = 'MONTHLY'
)

SELECT T."Date", NVL("Cost",0) + NVL("cost_per_day",0) "cost"
FROM T FULL JOIN monthly ON LAST_DAY(T."Date") = "month"
WHERE T."Flag" = 'DAILY'
ORDER BY T."Date";

http://sqlfiddle.com/#!4/cea34/14

关于获得“一个月中的每一天”,这已经回答了好几次了(oracle sql query to list all the dates of previous monthGenerate a range of dates using SQL

【讨论】:

  • 这将产生平均但仅一个月,我正在寻找一个动态的结果,它将承担接下来的几个月。我也希望每天填充结果,就像示例一样。
【解决方案2】:

这个解决方案怎么样?

SELECT THE_DATE, Flag, COST, 
    CASE Flag
    WHEN 'DAILY' THEN COST
    WHEN 'MONTHLY' THEN
        COST/EXTRACT(DAY FROM LAST_DAY(THE_DATE))
    ELSE NULL
    END AS AVG_COST
FROM THE_TABLE;

【讨论】:

  • 我想在月份的相应日期填充拆分。
【解决方案3】:

首先让我们查看 ROW GENERATOR 以获取该月所有日期的列表,包括相等数量的 COST 存储桶 平均分配给该月的每一天.

为了便于演示,我对值“3500/3”进行了硬编码。在您的原始查询中,您只需加入您的表并从表中获取 **MONTHLY" 值。

SQL> WITH DATA AS
  2    (SELECT to_date('01/01/2014', 'DD/MM/YYYY') date1,
  3      to_date('31/01/2014', 'DD/MM/YYYY') date2
  4    FROM dual
  5    )
  6  SELECT TO_CHAR(date1+level-1, 'DD/MM/YYYY') the_date,
  7    3500/31 AS "cost"
  8  FROM data
  9    CONNECT BY LEVEL <= date2-date1+1
 10  /

THE_DATE         cost
---------- ----------
01/01/2014 112.903226
02/01/2014 112.903226
03/01/2014 112.903226
04/01/2014 112.903226
05/01/2014 112.903226
06/01/2014 112.903226
07/01/2014 112.903226
08/01/2014 112.903226
09/01/2014 112.903226
10/01/2014 112.903226
11/01/2014 112.903226
12/01/2014 112.903226
13/01/2014 112.903226
14/01/2014 112.903226
15/01/2014 112.903226
16/01/2014 112.903226
17/01/2014 112.903226
18/01/2014 112.903226
19/01/2014 112.903226
20/01/2014 112.903226
21/01/2014 112.903226
22/01/2014 112.903226
23/01/2014 112.903226
24/01/2014 112.903226
25/01/2014 112.903226
26/01/2014 112.903226
27/01/2014 112.903226
28/01/2014 112.903226
29/01/2014 112.903226
30/01/2014 112.903226
31/01/2014 112.903226

31 rows selected.

SQL>

您需要做的就是将 nvl("cost", 0) 添加到上面的 cost 中。您可以对您的表执行 OUTER JOIN 并为那些具有“cost”值的行添加 nvl("cost", 0)

【讨论】:

    【解决方案4】:

    这个请求会只对表中已经存在的行进行

    SELECT TO_CHAR(D.DAY, 'MM/DD/YYYY') "Date",
           NVL(D.COST, 0) + M.COST / EXTRACT(DAY FROM LAST_DAY(M.DAY)) "Cost"
        FROM SO28292226 D
        JOIN SO28292226 M ON EXTRACT(MONTH FROM M.DAY) = EXTRACT(MONTH FROM D.DAY)
        WHERE NVL(D.FLAG, 'DAILY') = 'DAILY'
            AND M.FLAG = 'MONTHLY';
    

    【讨论】: