我有一个表活动_calc。
CREATE TABLE Activity_Calc (
person_id INTEGER NOT NULL PRIMARY KEY,
Activity_start_date DATE,
Activity_End_Date DATE
);
INSERT INTO Activity_Calc
VALUES (123,TO_DATE( '05-23-2020', 'MM-DD-YYYY' ), TO_DATE( '11-19-2020', 'MM-DD-YYYY' ) );
INSERT INTO Activity_Calc
VALUES (890,TO_DATE( '01-06-2021', 'MM-DD-YYYY' ), TO_DATE( '07-05-2021', 'MM-DD-YYYY' ) );
INSERT INTO Activity_Calc
VALUES (231,TO_DATE( '02-14-2020', 'MM-DD-YYYY' ), TO_DATE( '08-12-2020', 'MM-DD-YYYY' ) );
Activity_start_date和Activity_end_date之间的差异始终为180天。
我需要创建一个类似于下面的表:
在这里T1表示最近一个月。例如,对于Person_ID 123,T1是11月,他在11月活跃了19天。因此,对于Person_ID 123,T1获得了价值19。依此类推。从11月开始的上个月,他活跃了8天。因此T7需要8。
对于很少的客户来说,这可能会发生,T7甚至不会出现。只有T1至T6就足够了。在那种情况下,T7取0。
I have a table Activity_Calc.
CREATE TABLE Activity_Calc (
person_id INTEGER NOT NULL PRIMARY KEY,
Activity_start_date DATE,
Activity_End_Date DATE
);
INSERT INTO Activity_Calc
VALUES (123,TO_DATE( '05-23-2020', 'MM-DD-YYYY' ), TO_DATE( '11-19-2020', 'MM-DD-YYYY' ) );
INSERT INTO Activity_Calc
VALUES (890,TO_DATE( '01-06-2021', 'MM-DD-YYYY' ), TO_DATE( '07-05-2021', 'MM-DD-YYYY' ) );
INSERT INTO Activity_Calc
VALUES (231,TO_DATE( '02-14-2020', 'MM-DD-YYYY' ), TO_DATE( '08-12-2020', 'MM-DD-YYYY' ) );
The difference between the Activity_start_date and the Activity_End_Date is always 180 days.
I need to create a table like below:

Here T1 means the most recent month. For example, for person_id 123, T1 is November, and he was active for 19 days in November. So for person_Id 123, T1 takes the value 19. He was active for whole of October which is my T2 here for person_id 123. So T2 takes 31(Total number of days in October). So on and so forth. And the last month, going backward, starting from November, is May in which he was active for 8 days. Hence T7 takes 8.
It might happen for few customers, T7 won't even appear. Only T1 to T6 will suffice. In that case T7 takes 0.
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=f128f82f5ffbe53a76f93c23e6f71876
发布评论
评论(4)
您可以使用子句的Connect生成12个数字,然后将其视为几个月。然后加入您的表格并生成所需的行 -
You can generate 12 numbers using CONNECT BY Clause and then treat them as months. Then join your table back and generate the desired rows -
Demo.
您可以在此期间使用递归查询进行迭代,并找到每个月的开始和结束,然后计算天数:
对于示例数据:
输出:输出:
db<> fiddle 在这里
You can use a recursive query to iterate over the period and find the start and end for each month and then calculate the days:
Which, for the sample data:
Outputs:
db<>fiddle here
NB:看起来您的T7不正确或您尚未详细解释为什么您不在第一个月的整个天数。
DBFiddle: https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=571b019196a91dc556b880302c7a2576
NB: Looks like your T7 is not correct or you haven't explained in details why you don't count all days of the first month.
您可以以封闭的形式解决此问题 - 稍微约会算术(纸上的铅笔)可以节省代码中的大量计算。
请注意我对问题的解释(在问题下的评论中详细说明):如果您包括开始日期和结束日期,则在示例数据中显示的时间为181天。更常见的惯例是,最后一个日期是排除:一个19-Nov-2020的“日期”是指午夜 一天的开始,所以该人是那天不活跃。 11月的活跃日子的计数应为18岁,而不是19岁。同样,如果结束日期为4月1日,那么该人在3月31日午夜不活动 - 因此,“上个月”活动的“上个月”因为那个人必须是三月,而不是四月。
如果“ 180天”是正确的,但是您必须包括结束日期,则必须排除开始日期 - 这是没有意义的。或您的期间是181天,而不是180天,如果您必须在计数中包括开始日期和结束日期。所有这些不同的惯例都将导致不同的结果,但是可以为任何一个调整查询。
因此,无论如何 - 这是可以适用于我的解释的查询。为了更容易遵循输出,我也包括了与您的“周期”相对应的几个月;您可以从
中删除该列,如果需要,请选择
。如果您的数据具有有意义的大小,则可能需要尝试不同的解决方案并比较执行速度。
You can solve this problem in closed form - a little bit of date arithmetic (pencil on paper) can save a lot of computations in code.
Note my interpretation of the problem (detailed in Comments under your question): The periods you show in your sample data are 181 days if you include both the start and the end date. The much more common convention is that the last date is excluded: A "date" of 19-Nov-2020 means midnight at the beginning of the day, so the person was NOT active on that day. The count of active days in November should be 18, not 19. Also with this understanding, if the end date is say April 1, then the person becomes inactive at midnight at the end of March 31 - therefore the "last month" of activity for that person must be March, not April.
If "180 days" is correct but you must include the end date, then you must exclude the start date - which doesn't make sense. Or your periods are 181 days, not 180, if you must include both the start and the end date in the count. All these different conventions will lead to different results, but the query can be adapted for any of them.
So, anyway - here is the query that will work for my interpretation. To make it easier to follow the output, I included the months corresponding to your "periods" too; you can remove that column from
select
if needed.If your data is of meaningful size, you may want to try the different solutions and compare speed of execution.