有没有办法根据另一个表中某一列的累计总计来获取第一个表中的 ProcessDate 值?

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

我有2张桌子:

表1定义:

-- Table 1 Definition
drop table if exists #Table1
create table #Table1
(
    TREATY_COMPANY_CODE varchar(3),
    CURRENCY varchar(3),
    ProcessDate date,
    RowNumber int,
    Payment_Total decimal(20, 2)
)

insert into #Table1
values 
    ('165', 'USD', '2019-12-31', 1, 32929.92),
    ('165', 'USD', '2019-11-14', 2, 2400.0),
    ('165', 'USD', '2019-10-22', 3, 635.0),
    ('165', 'USD', '2019-03-28', 4, -21808.25),
    ('165', 'USD', '2019-02-13', 5, 54906.57)

表2定义:

drop table if exists #Table2
create table #Table2
(
    PolicyNo int null,
    ZeylRankNo int null,
    TreatyCompanyCode nvarchar(3) null,
    CurrencyType nvarchar(3) null,
    DisposedDate datetime null,
    ProvinceNo nvarchar(3) null,
    GWP decimal(20, 5) null,
    Commission_Received decimal(20, 5) null,
    PrKom decimal(20, 5) null
)
insert into #Table2
values
    ('50620211','0','165','USD',43717,'902','146.45','48.81','97.64'),
    ('12789054','0','165','USD',43717,'902','41.11','13.7','27.41'),
    ('12099876','0','165','USD',43717,'701','1312.44','437.44','875'),
    ('12125423','0','165','USD',43717,'701','0','0','0'),
    ('56718901','0','165','USD',43717,'719','1500','499.95','1000.05'),
    ('23456791','0','165','USD',43717,'720','1500','499.95','1000.05'),
    ('21090323','0','165','USD',43702,'720','2000','500','1500'),
    ('21201921','0','165','USD',43698,'719','1500','724.95','775.05'),
    ('45231905','0','165','USD',43698,'720','1500','724.95','775.05'),
    ('45129834','0','165','USD',43675,'719','1500','499.65','1000.35'),
    ('27819123','0','165','USD',43675,'720','8876','2219','6657'),
    ('28917634','0','165','USD',43675,'701','13953','3488.25','10464.75'),
    ('23179001','0','165','USD',43675,'720','2500','500','2000'),
    ('90030602','0','165','USD',43628,'720','1500','724.95','775.05'),
    ('30402213','0','165','USD',43596,'720','1500','725.1','774.9'),
    ('34244590','0','165','USD',43561,'902','262.22','102.27','159.95'),
    ('12893498','0','165','USD',43561,'701','0','0','0'),
    ('12357634','0','165','USD',43561,'720','1500','724.95','775.05'),
    ('19092334','0','165','USD',43561,'902','273.02','106.48','166.54'),
    ('19003023','0','165','USD',43561,'701','1571.76','612.99','958.77'),
    ('19917823','1','165','USD',43548,'720','-11029','-2680.05','-8348.95'),
    ('29912365','0','165','USD',43515,'902','519.4','103.88','415.52'),
    ('76290123','0','165','USD',43515,'701','1980.6','396.12','1584.48'),
    ('90817623','0','165','USD',43507,'720','13536','3289.25','10246.75'),
    ('23158723','0','165','USD',43442,'720','2500','500','2000'),
    ('23878123','0','165','USD',43341,'701','0','0','0'),
    ('23198323','0','165','USD',43341,'902','2994.9','748.73','2246.17'),
    ('14712345','0','165','USD',43302,'720','1500','724.95','775.05')

如果 Table2 中的 [Pr-Kom] 列中的累计总计超过了 table1 中的第一个数字 ( payment_total:32929,92) ,则将 ProcessDate 值带入所有行,然后移至下一个数字 (2400) ,计算累计总计并做同样的事!

这是我迄今为止尝试过的:

SELECT
       KT.*
       ,(
       CASE WHEN CumulativeTotal <= (SELECT Payment_Total FROM Table1 WHERE RowNumber = 1)  THEN CAST('2019-12-31' AS date)
       WHEN CumulativeTotal <= (SELECT Payment_Total FROM Table1 WHERE RowNumber = 2) THEN CAST('2019-11-14' AS date)
       WHEN CumulativeTotal <= (SELECT Payment_Total FROM Table1 WHERE RowNumber = 3) THEN CAST('2019-10-22' AS date)
       WHEN CumulativeTotal <= (SELECT Payment_Total FROM Table1 WHERE RowNumber = 4) THEN CAST('2019-03-28' AS date)
       WHEN CumulativeTotal <= (SELECT Payment_Total FROM Table1 WHERE RowNumber = 5) THEN CAST('2019-02-13' AS date)
       ELSE CAST('1900-01-01' AS date) END
       ) AS Date
FROM(
SELECT
       K.*
       ,SUM(K.[Pr-Kom]) OVER(ORDER BY K.RN) AS CumulativeTotal
FROM
(SELECT
       *,
       ROW_NUMBER() OVER(ORDER BY DisposedDate) AS RN
FROM Table2
WHERE TreatyCompanyCode='165'
AND CurrencyType='USD'
) AS K
) AS KT

预期结果应该是这样的:

sql sql-server window-functions
1个回答
0
投票

所以这不是一个非常优雅的答案,但这是我能想到的最好的答案。

首先,需要注意的是。如果没有确定的方式来对行进行排序,我不相信这可以通过 SQL 实现。您需要能够识别一个分区的结束位置和另一个分区的开始位置,如果您没有办法知道哪一行在另一行之前,那么您根本无法做到这一点。

也许您可以更改数据处理机制以添加代理键或其他东西来强制执行顺序。如果那不可能,那我就一无所有了。

排除了这一点,也许有人可以想出一个更清晰的答案,但我无法想出任何不涉及可怕循环的答案。

对于每次迭代,我都会获得“剩余”记录的运行总数。在第一个循环中,这就是一切,从 RID = 1 开始。在第二个循环中,无论您在第一遍中设置什么,这都是从

after
开始的。 从那里,我得到最大 RID 加一,以说明您希望第一行

超过

表 1 中的阈值。 drop table if exists #T1 create table #T1 ( RowNumber int, ProcessDate date, PaymentTotal decimal(20, 2) ) drop table if exists #T2 create table #T2 ( RID int, PolicyNo int, DisposedDate datetime null, PrKom decimal(20, 5) null, PartitionRunningTotal decimal(20, 5) null, GroupId int null, -- Going to update this in a loopdy-loop to join #T1 to later ProcessDate date ) go insert into #T1 values (1,'2019-12-31',32929.92), (2,'2019-11-14',2400.0), (3,'2019-10-22',635.0), (4,'2019-03-28',-21808.25), (5,'2019-02-13',54906.57) insert into #T2 (RID, PolicyNo, DisposedDate, PrKom) values ( 1, 50620211, N'2019-09-11T00:00:00', 97.64000 ), ( 2, 12789054, N'2019-09-11T00:00:00', 27.41000 ), ( 3, 12099876, N'2019-09-11T00:00:00', 875.00000 ), ( 4, 12125423, N'2019-09-11T00:00:00', 0.00000 ), ( 5, 56718901, N'2019-09-11T00:00:00', 1000.05000 ), ( 6, 23456791, N'2019-09-11T00:00:00', 1000.05000 ), ( 7, 21090323, N'2019-08-27T00:00:00', 1500.00000 ), ( 8, 21201921, N'2019-08-23T00:00:00', 775.05000 ), ( 9, 45231905, N'2019-08-23T00:00:00', 775.05000 ), ( 10, 45129834, N'2019-07-31T00:00:00', 1000.35000 ), ( 11, 27819123, N'2019-07-31T00:00:00', 6657.00000 ), ( 12, 28917634, N'2019-07-31T00:00:00', 10464.75000 ), ( 13, 23179001, N'2019-07-31T00:00:00', 2000.00000 ), ( 14, 90030602, N'2019-06-14T00:00:00', 775.05000 ), ( 15, 30402213, N'2019-05-13T00:00:00', 774.90000 ), ( 16, 34244590, N'2019-04-08T00:00:00', 159.95000 ), ( 17, 12893498, N'2019-04-08T00:00:00', 0.00000 ), ( 18, 12357634, N'2019-04-08T00:00:00', 775.05000 ), ( 19, 19092334, N'2019-04-08T00:00:00', 166.54000 ), ( 20, 19003023, N'2019-04-08T00:00:00', 958.77000 ), ( 21, 19917823, N'2019-03-26T00:00:00', -8348.95000 ), ( 22, 29912365, N'2019-02-21T00:00:00', 415.52000 ), ( 23, 76290123, N'2019-02-21T00:00:00', 1584.48000 ), ( 24, 90817623, N'2019-02-13T00:00:00', 10246.75000 ), ( 25, 23158723, N'2018-12-10T00:00:00', 2000.00000 ), ( 26, 23878123, N'2018-08-31T00:00:00', 0.00000 ), ( 27, 23198323, N'2018-08-31T00:00:00', 2246.17000 ), ( 28, 14712345, N'2018-07-23T00:00:00', 775.05000 ) -- GroupID is synonymous with the RowNumber from #T1. declare @GroupId int select @GroupId = min(RowNumber) from #T1 declare @PaymentTotal decimal(20, 5), @ProcessDate date, @PartitionEndRID int -- While there are still rows for which we havn't filled in this data... while exists ( select 1 from #t2 where GroupId is null ) begin select @PaymentTotal = PaymentTotal, @ProcessDate = ProcessDate from #t1 where RowNumber = @GroupId -- Get the upper boundary of the current partition ;with a as ( select RID, PartitionRunningTotal = sum(PrKom) over (order by RID) from #t2 where GroupId is null ) select @PartitionEndRID = max(a.RID) + 1 -- +1 to account for the value needing to _exceed_ the Payment Total from a where PartitionRunningTotal < @PaymentTotal -- Update everything in T2 (that's not already set) where the RID is less than the upper boundary update #T2 set GroupId = @GroupId, ProcessDate = @ProcessDate where GroupId is null and RID <= @PartitionEndRID -- Go again select @GroupID += 1 end -- This yields the output table select RID, PolicyNo, DisposedDate, PrKom, RunningTotal = sum(PrKom) over (order by RID), PartitionRunningTotal = sum(PrKom) over (partition by GroupId order by RID), GroupId, ProcessDate from #T2 order by RID

我很想想出一种更优雅的方法来做到这一点,但这是我得到的最好的方法。

© www.soinside.com 2019 - 2024. All rights reserved.