【发布时间】:2020-01-07 17:27:06
【问题描述】:
我有三张桌子。一张表告诉我何时与特定供应商签约。第二个告诉我我们与所有供应商签订的基本费用表。第三个告诉我具体合同是否对其中一项费用有不同的合同费率。表格如下所示:
CREATE TABLE [dbo].[Facility](
[FacilityID] [bigint] IDENTITY(1,1) NOT NULL,
[ProviderID] [varchar](50) NOT NULL,
[VendorID] [bigint] NOT NULL,
[FacilityName] [varchar](300) NOT NULL,
[FacilityAddress1] [varchar](300) NOT NULL,
[FacilityAddress2] [varchar](300) NOT NULL,
[FacilityCity] [varchar](300) NOT NULL,
[FacilityState] [char](2) NOT NULL,
[FacilityZip] [varchar](10) NOT NULL,
[ContractEffectiveDate] [date] NOT NULL,
[ContractTermDate] [date] NOT NULL,
CONSTRAINT [PK_Facility] PRIMARY KEY CLUSTERED
(
[FacilityID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[BaseFeeSchedule](
[BaseFeeScheduleID] [int] IDENTITY(1,1) NOT NULL,
[FeeCode] [varchar](10) NOT NULL,
[Description] [varchar](800) NOT NULL,
[Rate] [money] NOT NULL,
[CategoryID] [int] NOT NULL,
[RateEffectiveDate] [date] NOT NULL,
[RateTermDate] [date] NOT NULL,
CONSTRAINT [PK_BaseFeeSchedule] PRIMARY KEY CLUSTERED
(
[BaseFeeScheduleID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[OverrideFeeSchedule](
[OverrideFeeScheduleID] [bigint] IDENTITY(1,1) NOT NULL,
[FacilityID] [bigint] NOT NULL,
[FeeCode] [varchar](10) NOT NULL,
[OverrideRate] [money] NOT NULL,
[RateEffectiveDate] [date] NOT NULL,
[RateTermDate] [date] NOT NULL,
CONSTRAINT [PK_OverrideFeeSchedule] PRIMARY KEY CLUSTERED
(
[OverrideFeeScheduleID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[OverrideFeeSchedule] WITH CHECK ADD CONSTRAINT [FK_OverrideFeeSchedule_Facility] FOREIGN KEY([FacilityID])
REFERENCES [dbo].[Facility] ([FacilityID])
GO
ALTER TABLE [dbo].[OverrideFeeSchedule] CHECK CONSTRAINT [FK_OverrideFeeSchedule_Facility]
GO
我们有一个现有系统,其中一张表如下所示:
CREATE TABLE [dbo].[FeeSchedule](
[FeeScheduleID] [int] IDENTITY(1,1) NOT NULL,
[VendorID] [int] NULL,
[FeeCd] [varchar](10) NOT NULL,
[StartDate] [date] NOT NULL,
[EndDate] [date] NOT NULL,
[ContractedAmount] [money] NOT NULL,
[ProgramTypeID] [int] NULL,
CONSTRAINT [PK_FeeSchedule] PRIMARY KEY CLUSTERED
(
[FeeScheduleID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
该表在代码中用于确定支付给每个供应商的正确费率。我的工作是更新该表,但事实证明这是有问题的,因为不同的设施在不同的日期签订了合同。每份合同都包括基本费用表。但是,合同允许某些费用被不同的费用“覆盖”(当有折扣时通常低于正常的合同费用,当需要添加附加费时偶尔会更高)。这三个表是我构建的存储所有当前数据的表,我一直在使用它们来构建软件所需的 FeeSchedule 表。处理更改很容易,但我的任务是验证 FeeSchedule 表中的数据是否准确。
FeeSchedule 表不仅包括新数据(这是我唯一更改的),还包括以前的数据。因此,计划是获取三个表中的数据,运行查询以合并日期范围(其中 OverrideFeeSchedule 表中的费用优先于 BaseFeeSchedule 表中的费用)
一个例子:
INSERT INTO Facility(VendorID,ContractEffectiveDate,ContractTermDate,...)
VALUES(1,'1/1/2017','12/31/9999',...) --Assume FacilityID=1
INSERT INTO BaseFeeSchedule(FeeCode,Rate,RateEffectiveDate,RateTermDate,...)
VALUES('1',100,'1/1/2015','10/15/2016',...),
('1',120,'10/16/2016','4/5/2018',...),
('1',140,'4/6/2018','12/31/9999',...)
INSERT INTO OverrideFeeSchedule(FacilityID,FeeCode,OverrideRate,RateEffectiveDate,RateTermDate,...)
VALUES(1,'1',50,'3/1/2017','5/31/2018',...),
(1,'1',70,'7/1/2018','12/31/9999',...)
And from this data, I would want:
INSERT INTO FeeSchedule(VendorID, FeeCd, StartDate,EndDate,ContractedAmount)
VALUES(1,'1','1/1/2017','2/28/2017',120), --From BaseFeeSchedule
(1,'1','3/1/2017','5/31/2018',50), --From OverrideFeeSchedule
(1,'1','6/1/2018','6/30/2018',140), --From BaseFeeSchedule
(1,'1','7/1/2018','12/31/9999',70) --From OverrideFeeSchedule
我已验证 OverrideFeeSchedule 表中没有单个 Facility/FeeCode 组合的数据重叠,并且 BaseFeeSchedule 中没有单个 FeeCode 的数据重叠。我目前的解决方案需要永远。我正在执行以下操作:
建立一个自第一个签约设施开始以来的每一天的表格。 (BigTable 只是一个包含大约一百万条记录的表,我只需要从与供应商签订合同的第一个日期到一年后的每一天。但是,由于最大递归大约是 20,000 ,当从第一个签约供应商到从今天开始的一年的范围超过 20,000 天时,我可能会因为违反最大递归而出错。所以,我希望有一个不同的解决方案。
SELECT DATEADD(DAY,ROW_NUMBER() OVER (ORDER BY A.TableID) - 1,B.MinDate) CheckDate
INTO #DatesToCheck
FROM BigTable A
CROSS JOIN
(SELECT MIN(ContractEffectiveDate) MinDate
FROM Facility) B
WHERE DATEADD(DAY,ROW_NUMBER() OVER (ORDER BY A.TableID) - 1,B.MinDate) < DATEADD(YEAR,1,GETDATE())
将此表与其他表连接起来,构建一个包含每天、当天签约的每个设施、当天应收费的每个 FeeCode 以及当天的具体费率的大型表。那个join的代码我就不费心了,不过写起来不难。
接下来,我使用此处描述的技术来合并日期范围: StackOverflow
虽然这种技术有效,但速度极慢。有没有更直接的方法来生成我正在寻找的结果集?基本上,我正在寻找如何修改该链接中的方法,以考虑与不同优先级(基本与覆盖)的潜在重叠,就像我提供的示例中一样。
【问题讨论】:
标签: sql-server tsql intervals aggregation schedule