SQL按人,日期范围选择连接到另一个事件的每个事件

时间:2014-08-05 19:38:38

标签: sql sql-server tsql sql-server-2008-r2

我有一个SQL Server 2008 R2数据库,其中包含跟踪客户端注册,提供给这些客户端的服务事件以及每次注册的单个后续计费事件的表。

我无法为每个服务事件生成结算结果列表。任何指导都是天赐之物!

简化表格是:

注册

enrollment_rec_id
person_id
program_id
enrollment_start_date
enrollment_end_date

服务

service_rec_id
person_id
date_of_service
program_id 

(注意:service_rec_id未在任何其他表中引用)。

service.date_of_service必须介于enrollment.enrollment_start_dateenrollment.enrollment_end_date之间。

每个billing事件记录必须与至少1个service记录相关联,但每个service记录可以与许多或0个billing事件记录相关联。)

结算:

 billing_rec_id
 person_id
 billing date
 number_of services_billed_for
 date_of_one_of_those_services
 amount_billed
 amount_received
 enrollment_start_date
 enrollment_end_date
 enrollment_rec_id

date_of_one_of_those_services的服务显然是从包含的几个服务中输入这些记录的人随机选择的。这是对services记录的唯一直接引用。然后输入一个计数收取的服务费用以及为该人/注册计费和收取的总金额。此外,同一人/注册可以有多个计费事件记录。一个人可能会显示2个服务收费,另外3个服务收费,当注册有5个服务。还有许多注册根本没有计费事件记录,或者有计费事件记录列出的注册服务比注册日期范围内的服务事件少;

请求的输出包括哪些service.service_rec_id - 按人数 - 收费,并将按日期范围/人关联的service.service_rec_id个数与此billing.billing_rec_id进行比较。每个人的日期范围service.service_rec_id的数量是否为billing.number_of service_billed_for)。

所需的输出类似于

service.person_id, 
enrollment.program_id, 
enrollment.enrollment_start_date, 
enrollment.enrollment_end_date, 
service.service_rec_id, 
billing.billing date, 
billing.number_of services_billed_for,  
calculate_number_of_service_rec_id_for_this_billing_rec_id

有人能提出一个好的策略来追求吗?

1 个答案:

答案 0 :(得分:2)

进入战斗,让我们制作一些测试数据:

DECLARE @Enrollment TABLE
(   
    enrollment_rec_id INT,
    person_id INT,
    program_id INT,
    enrollment_start_date DATETIME,
    enrollment_end_date DATETIME
)

DECLARE @Service TABLE
(
    service_rec_id INT,
    person_id INT,
    date_of_service DATETIME,
    program_id INT
)

DECLARE @Billing TABLE
(
    billing_rec_id INT,
    person_id INT,
    billingdate DATETIME,
    number_of_services_billed_for INT,
    date_of_one_of_those_services DATETIME,
    amount_billed DECIMAL(19,6),
    amount_received DECIMAL(19,6),
    enrollment_start_date DATETIME,
    enrollment_end_date DATETIME,
    enrollment_rec_id INT
)

INSERT INTO @Enrollment
( enrollment_rec_id, person_id, program_id, enrollment_start_date, enrollment_end_date )
VALUES
( 1, 1, 1, '01-01-2014', '12-31-2014' ),
( 2, 1, 2, '01-01-2014', '12-31-2014' ),
( 3, 2, 3, '01-01-2014', '12-31-2014' );

INSERT INTO @Service
( service_rec_id, person_id, date_of_service, program_id )
VALUES
( 1, 1, '02-01-2014', 1 ),
( 2, 2, '03-01-2014', 1 ),
( 3, 1, '04-01-2014', 1 ),
( 4, 2, '05-01-2014', 2 ),
( 5, 1, '06-01-2014', 2 ),
( 6, 2, '06-01-2014', 2 );

INSERT INTO @Billing
( billing_rec_id, person_id, billingdate, number_of_services_billed_for, date_of_one_of_those_services, amount_billed, amount_received, enrollment_start_date, enrollment_end_date, enrollment_rec_id )
VALUES
( 1, 1, '10-01-2014', 3, '02-01-2014', 300.00, 150.00, '01-01-2014', '12-31-2014', 1),
( 2, 2, '10-01-2014', 3, '03-01-2014', 500.00, 333.00, '01-01-2014', '12-31-2014', 2);

现在我们可以加入我们的结算和注册表,当我们尝试加入第一条服务记录并获得最大服务记录数时:

SELECT 
    s.person_id,
    e.program_id,
    e.enrollment_start_date,
    e.enrollment_end_date,
    s.service_rec_id,
    b.billingdate,
    b.number_of_services_billed_for,
    ns.Num_Of_Services_For_Program_Id
FROM @Billing b
INNER JOIN @Enrollment e
    ON e.enrollment_rec_id = b.enrollment_rec_id
OUTER APPLY 
(
    SELECT TOP 1 * FROM @Service s 
    WHERE s.program_id = e.program_id
        AND s.date_of_service BETWEEN e.enrollment_start_date AND e.enrollment_end_date
) s
OUTER APPLY
(
    SELECT COUNT(*) Num_Of_Services_For_Program_Id FROM @Service s 
    WHERE s.program_id = e.program_id
        AND s.date_of_service BETWEEN e.enrollment_start_date AND e.enrollment_end_date
) ns

这是输出:

person_id   program_id  enrollment_start_date   enrollment_end_date service_rec_id  billingdate number_of_services_billed_for   Num_Of_Services_For_Program_Id
1   1   2014-01-01 00:00:00.000 2014-12-31 00:00:00.000 1   2014-10-01 00:00:00.000 3   3
2   2   2014-01-01 00:00:00.000 2014-12-31 00:00:00.000 4   2014-10-01 00:00:00.000 3   3

也许是处理问题的起点?