22,210
社区成员
发帖
与我相关
我的任务
分享
;WITH table1 ( SID, sDate, fDate, amount_plan )
AS (
SELECT '143EA571-3772-42DF-8E8F-6C638D8405B0','2017-06-26','2017-07-21',16000 UNION ALL
SELECT '2095DF0B-B5F0-48EC-A1C0-2A8E5EBAAD22','2017-02-09','2017-03-22',240000 UNION ALL
SELECT '3DC52EEC-9656-4BFE-8B09-CE25C8A402BE','2017-05-11','2017-06-13',192000 UNION ALL
SELECT '6E894637-B5F6-4DBB-BB68-5F1AF51C8913','2017-04-20','2017-05-10',120000 UNION ALL
SELECT '6F69296E-3DD5-44E8-8FF3-23455BB9BBA0','2017-07-24','2017-08-04',80000 UNION ALL
SELECT 'A2919D17-1876-4761-A5FA-CA3CC95E6744','2017-02-23','2017-04-19',320000 UNION ALL
SELECT 'A74985B1-3D8C-486B-9427-A0F0966D89B9','2017-01-12','2017-01-31',112000 UNION ALL
SELECT 'BC6BFFF7-58E3-47AA-B4BD-BF521DF9717C','2017-06-14','2017-07-07',56000 UNION ALL
SELECT 'DFB2C4AA-EE19-4BD6-9FB6-0AA34303B683','2017-01-12','2017-02-08',14000
),
z0 ( sDate, fDate )
AS ( SELECT MIN(sDate) AS sDate ,MAX(fDate) AS fDate
FROM table1
),
z1 ( sDate, fDate, MIN_sDate, MAX_fDate )
AS ( SELECT CASE WHEN DAY(sDate) <= 24
THEN DATEADD(month, -1,
DATEADD(day, 25 - DAY(sDate),
sDate))
ELSE DATEADD(day, 25 - DAY(sDate), sDate)
END ,
CASE WHEN DAY(sDate) <= 24
THEN DATEADD(day, 24 - DAY(sDate), sDate)
ELSE DATEADD(month, 1,
DATEADD(day, 24 - DAY(sDate),
sDate))
END ,sDate ,fDate
FROM z0
),
a ( aID, sDate, fDate )
AS ( -- 日期区间
SELECT n.number + 1 ,
CASE WHEN n.number = 0 THEN z1.MIN_sDate
ELSE DATEADD(month, n.number, z1.sDate)
END ,
CASE WHEN z1.MAX_fDate <= DATEADD(month,
n.number,
z1.fDate)
THEN z1.MAX_fDate
ELSE DATEADD(month, n.number, z1.fDate)
END
FROM z1
JOIN ( SELECT number
FROM master..spt_values
WHERE type = 'p'
) n ON DATEADD(month, n.number, sDate) < = MAX_fDate
),
b AS ( -- 切割日期区间
SELECT a.aID ,
CASE WHEN a.sDate > t.sDate THEN a.SDate
ELSE t.sDate
END AS sDate ,
CASE WHEN a.fDate < t.fDate THEN a.fDate
ELSE t.fDate
END AS fDate ,
DATEDIFF(day, t.sDate, t.fDate) + 1 AS totalDays ,
t.amount_plan AS totalAmount
FROM a
JOIN table1 t ON a.sDate <= t.fDate
AND t.sDate <= a.fDate
),
c ( aID, amount_plan )
AS ( -- 分隔 amount
SELECT aID ,CONVERT(MONEY, totalAmount * 1.0* ( DATEDIFF(day, sDate, fDate) + 1 )/ totalDays)
FROM b
),
d ( amount_plan )
AS ( -- 合计 amount
SELECT SUM(amount_plan)
FROM c
),
e ( aID, amount_plan )
AS ( -- 分段统计 amount
SELECT aID ,SUM(amount_plan)
FROM c
GROUP BY aID
),
f ( aID, amount_plan, LJamount_plan )
AS ( -- 分段统计 LJamount
SELECT e1.aID ,MAX(e1.amount_plan) ,SUM(e2.amount_plan)
FROM e e1
JOIN e e2 ON e2.aID <= e1.aID
GROUP BY e1.aID
)
SELECT a.aID,CONVERT(varchar(100), a.sDate, 23)sDate,CONVERT(varchar(100), a.fDate, 23)fDate,
f.amount_plan ,
f.LJamount_plan ,
ISNULL(F.amount_plan, 0)/ d.amount_plan AS Com_rate_plan,
ISNULL(F.LJamount_plan, 0) / d.amount_plan AS LJ_Com_rate_plan
FROM a
JOIN d ON 1 = 1
LEFT JOIN f ON a.aid = f.aid
...
a(aID,sDate,fDate) AS ( -- 日期区间
SELECT number + 1,
DATEADD(month,number,'2015-12-25'),
DATEADD(month,number,'2016-01-24')
FROM master..spt_values
WHERE type = 'p'
AND number < 6
),
...
aID sDate fDate amount LJamount Com_rate
----------- ---------- ---------- --------------------- --------------------- ---------------------
1 2015-12-25 2016-01-24 545.4545 545.4545 0.0519
2 2016-01-25 2016-02-24 1343.4344 1888.8889 0.1798
3 2016-02-25 2016-03-24 2938.441 4827.3299 0.4597
4 2016-03-25 2016-04-24 2849.1407 7676.4706 0.731
5 2016-04-25 2016-05-24 2352.9412 10029.4118 0.9551
6 2016-05-25 2016-06-24 470.5882 10500.00 1.00
WITH
/* 测试数据
table1(SID,sDate,fDate,amount) AS (
...
), */
z0(sDate,fDate) AS (
SELECT MIN(sDate) AS sDate,
MAX(fDate) AS fDate
FROM table1
),
z1(sDate,fDate,MIN_sDate,MAX_fDate) AS (
SELECT CASE WHEN DAY(sDate) <= 24
THEN DATEADD(month,-1, DATEADD(day,25-DAY(sDate),sDate) )
ELSE DATEADD(day,25-DAY(sDate),sDate)
END,
CASE WHEN DAY(sDate) <= 24
THEN DATEADD(day,24-DAY(sDate),sDate)
ELSE DATEADD(month,1, DATEADD(day,24-DAY(sDate),sDate) )
END,
sDate,
fDate
FROM z0
),
a(aID,sDate,fDate) AS ( -- 日期区间
SELECT n.number + 1,
CASE WHEN n.number = 0
THEN z1.MIN_sDate
ELSE DATEADD(month,n.number,z1.sDate)
END,
CASE WHEN z1.MAX_fDate <= DATEADD(month,n.number,z1.fDate)
THEN z1.MAX_fDate
ELSE DATEADD(month,n.number,z1.fDate)
END
FROM z1
JOIN (SELECT number
FROM master..spt_values
WHERE type = 'p'
) n
ON DATEADD(month,n.number,sDate) < = MAX_fDate
),
...
...
table1(SID,sDate,fDate,amount) AS (
SELECT '143EA571-3772-42DF-8E8F-6C638D8405B0','2017-06-26','2017-07-21',16000 UNION ALL
SELECT '2095DF0B-B5F0-48EC-A1C0-2A8E5EBAAD22','2017-02-09','2017-03-22',240000 UNION ALL
SELECT '3DC52EEC-9656-4BFE-8B09-CE25C8A402BE','2017-05-11','2017-06-13',192000 UNION ALL
SELECT '6E894637-B5F6-4DBB-BB68-5F1AF51C8913','2017-04-20','2017-05-10',120000 UNION ALL
SELECT '6F69296E-3DD5-44E8-8FF3-23455BB9BBA0','2017-07-24','2017-08-04',80000 UNION ALL
SELECT 'A2919D17-1876-4761-A5FA-CA3CC95E6744','2017-02-23','2017-04-19',320000 UNION ALL
SELECT 'A74985B1-3D8C-486B-9427-A0F0966D89B9','2017-01-12','2017-01-31',112000 UNION ALL
SELECT 'BC6BFFF7-58E3-47AA-B4BD-BF521DF9717C','2017-06-14','2017-07-07',56000 UNION ALL
SELECT 'DFB2C4AA-EE19-4BD6-9FB6-0AA34303B683','2017-01-12','2017-02-08',14000
),
...
aID sDate fDate amount LJamount Com_rate
----------- ---------- ---------- --------------------- --------------------- ---------------------
1 2017-01-12 2017-01-24 79300.00 79300.00 0.0689
2 2017-01-25 2017-02-24 149557.1428 228857.1428 0.199
3 2017-02-25 2017-03-24 308571.4286 537428.5714 0.4673
4 2017-03-25 2017-04-24 177142.8572 714571.4286 0.6213
5 2017-04-25 2017-05-24 170487.3949 885058.8235 0.7696
6 2017-05-25 2017-06-24 138607.8432 1023666.6667 0.8901
7 2017-06-25 2017-07-24 53000.00 1076666.6667 0.9362
8 2017-07-25 2017-08-04 73333.3333 1150000.00 1.00
use Tempdb
go
--> --> 中国风(Roy)生成測試數據
if not object_id(N'Tempdb..#T') is null
drop table #T
Go
Create table #T([SID] int,[sDate] DATE,[fDate] DATE,[aMount] MONEY)
Insert #T
select 1,'2016-01-01','2016-03-28',2000 union all
select 2,'2016-02-02','2016-03-08',1000 union all
select 3,'2016-02-26','2016-04-18',3000 union all
select 4,'2016-03-05','2016-04-03',500 union all
select 5,'2016-04-10','2016-05-30',4000
UNION ALL SELECT 6,'2016-01-01','2016-01-31',31
GO
;WITH CTET
AS
(
SELECT a.SID ,
CASE WHEN b.number = 0 THEN a.sDate
WHEN DAY(sDate) > 24
THEN CONVERT(VARCHAR(8), DATEADD(m, b.number, a.sDate), 120)
+ '25'
ELSE CONVERT(VARCHAR(8), DATEADD(m, b.number - 1, a.sDate), 120)
+ '25'
END AS sDate ,
CASE WHEN DAY(a.fDate) <= 24
AND DAY(a.sDate) > 24
AND CONVERT(VARCHAR(8), DATEADD(m, b.number + 1, a.sDate), 120)
+ '24' > a.fDate
OR CONVERT(VARCHAR(8), DATEADD(m, b.number, a.sDate), 120)
+ '24' > a.fDate THEN a.fDate
WHEN DAY(a.sDate) > 24
AND CONVERT(VARCHAR(8), DATEADD(m, b.number, a.sDate), 120)
+ '24' <= a.fDate
THEN CONVERT(VARCHAR(8), DATEADD(m, b.number + 1, a.sDate), 120)
+ '24'
ELSE CONVERT(VARCHAR(8), DATEADD(m, b.number, a.sDate), 120)
+ '24'
END AS fDate ,
a.aMount ,
a.fDate AS fDate2 ,
a.aMount / (DATEDIFF(dd, a.sDate, a.fDate) + 1) AS DailyPrice
FROM #T AS a
INNER JOIN master.dbo.spt_values AS b ON b.type = 'P'
AND ( CONVERT(VARCHAR(8), DATEADD(m,
b.number,
a.sDate), 120)
+ '24' <= a.fDate
OR CONVERT(VARCHAR(8), DATEADD(m,
b.number - 1,
a.sDate), 120)
+ '25' < a.fDate
AND CONVERT(VARCHAR(8), DATEADD(m,
b.number,
a.sDate), 120)
+ '25' > a.fDate
AND DAY(sDate) <= 25
)
)
SELECT SID ,
sDate ,
fDate ,
aMount,
DailyPrice ,
CASE WHEN fDate=fDate2 THEN aMount-ISNULL(SUM((DATEDIFF(dd, sDate, fDate) + 1 ) * DailyPrice)OVER(PARTITION BY SID ORDER BY sDate ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0)
ELSE (DATEDIFF(dd, sDate, fDate) + 1 ) * DailyPrice END AS lJaMount
,( DATEDIFF(dd, sDate, fDate) + 1 ) * DailyPrice * 100 / aMount AS Com_rate
FROM CTET
ORDER BY SID,sDate;
/*
SID sDate fDate aMount DailyPrice lJaMount Com_rate
1 2016-01-01 2016-01-24 2000.00 22.7272 545.4528 27.2726
1 2016-01-25 2016-02-24 2000.00 22.7272 704.5432 35.2271
1 2016-02-25 2016-03-24 2000.00 22.7272 659.0888 32.9544
1 2016-03-25 2016-03-28 2000.00 22.7272 90.9152 4.5454
2 2016-02-02 2016-02-24 1000.00 27.7777 638.8871 63.8887
2 2016-02-25 2016-03-08 1000.00 27.7777 361.1129 36.111
3 2016-02-26 2016-03-24 3000.00 56.6037 1584.9036 52.8301
3 2016-03-25 2016-04-18 3000.00 56.6037 1415.0964 47.1697
4 2016-03-05 2016-03-24 500.00 16.6666 333.332 66.6664
4 2016-03-25 2016-04-03 500.00 16.6666 166.668 33.3332
5 2016-04-10 2016-04-24 4000.00 78.4313 1176.4695 29.4117
5 2016-04-25 2016-05-24 4000.00 78.4313 2352.939 58.8234
5 2016-05-25 2016-05-30 4000.00 78.4313 470.5915 11.7646
6 2016-01-01 2016-01-24 31.00 1.00 24.00 77.4193
6 2016-01-25 2016-01-31 31.00 1.00 7.00 22.5806
*/
WITH
/* 测试数据
table1(SID,sDate,fDate,amount) AS (
SELECT 1,'2016-01-01','2016-03-28',2000 UNION ALL
SELECT 2,'2016-02-02','2016-03-08',1000 UNION ALL
SELECT 3,'2016-02-26','2016-04-18',3000 UNION ALL
SELECT 4,'2016-03-05','2016-04-03',500 UNION ALL
SELECT 5,'2016-04-10','2016-05-30',4000
), */
a(aID,sDate,fDate) AS ( -- 日期区间
SELECT number + 1,
CASE WHEN number = 0
THEN '2016-01-01'
ELSE DATEADD(month,number,'2015-12-25')
END,
CASE WHEN number = 5
THEN '2016-05-30'
ELSE DATEADD(month,number,'2016-01-24')
END
FROM master..spt_values
WHERE type = 'p'
AND number < 6
),
b AS ( -- 切割日期区间
SELECT a.aID,
CASE WHEN a.sDate > t.sDate THEN a.SDate ELSE t.sDate END AS sDate,
CASE WHEN a.fDate < t.fDate THEN a.fDate ELSE t.fDate END AS fDate,
DATEDIFF(day,t.sDate,t.fDate) + 1 AS totalDays,
t.amount AS totalAmount
/* DEBUG
,a.sDate AS a_sDate,
a.fDate AS a_fDate,
t.SID,
t.sDate AS t_sDate,
t.fDate As t_fDate
*/
FROM a
JOIN table1 t
ON a.sDate <= t.fDate
AND t.sDate <= a.fDate
),
c(aID,amount) AS ( -- 分隔 amount
SELECT aID,
CONVERT(money, totalAmount * 1.0 * (DATEDIFF(day,sDate,fDate)+1) / totalDays)
FROM b
),
d(amount) AS ( -- 合计 amount
SELECT sum(amount)
FROM c
),
e(aID,amount) AS ( -- 分段统计 amount
SELECT aID,
SUM(amount)
FROM c
GROUP BY aID
),
f(aID,amount,LJamount) AS ( -- 分段统计 LJamount
SELECT e1.aID,
MAX(e1.amount),
SUM(e2.amount)
FROM e e1
JOIN e e2
ON e2.aID <= e1.aID
GROUP BY e1.aID
)
SELECT a.*,
f.amount,
f.LJamount,
ISNULL(F.LJamount,0) / d.amount AS Com_rate
FROM a
JOIN d
ON 1=1
LEFT JOIN f
ON a.aid = f.aid
aID sDate fDate amount LJamount Com_rate
----------- ---------- ---------- --------------------- --------------------- ---------------------
1 2016-01-01 2016-01-24 545.4545 545.4545 0.0519
2 2016-01-25 2016-02-24 1343.4344 1888.8889 0.1798
3 2016-02-25 2016-03-24 2938.441 4827.3299 0.4597
4 2016-03-25 2016-04-24 2849.1407 7676.4706 0.731
5 2016-04-25 2016-05-24 2352.9412 10029.4118 0.9551
6 2016-05-25 2016-05-30 470.5882 10500.00 1.00
aID sDate fDate totalDays totalAmount a_sDate a_fDate SID t_sDate t_fDate
----------- ---------- ---------- ----------- ----------- ---------- ---------- ----------- ---------- ----------
1 2016-01-01 2016-01-24 88 2000 2016-01-01 2016-01-24 1 2016-01-01 2016-03-28
2 2016-01-25 2016-02-24 88 2000 2016-01-25 2016-02-24 1 2016-01-01 2016-03-28
3 2016-02-25 2016-03-24 88 2000 2016-02-25 2016-03-24 1 2016-01-01 2016-03-28
4 2016-03-25 2016-03-28 88 2000 2016-03-25 2016-04-24 1 2016-01-01 2016-03-28
2 2016-02-02 2016-02-24 36 1000 2016-01-25 2016-02-24 2 2016-02-02 2016-03-08
3 2016-02-25 2016-03-08 36 1000 2016-02-25 2016-03-24 2 2016-02-02 2016-03-08
3 2016-02-26 2016-03-24 53 3000 2016-02-25 2016-03-24 3 2016-02-26 2016-04-18
4 2016-03-25 2016-04-18 53 3000 2016-03-25 2016-04-24 3 2016-02-26 2016-04-18
3 2016-03-05 2016-03-24 30 500 2016-02-25 2016-03-24 4 2016-03-05 2016-04-03
4 2016-03-25 2016-04-03 30 500 2016-03-25 2016-04-24 4 2016-03-05 2016-04-03
4 2016-04-10 2016-04-24 51 4000 2016-03-25 2016-04-24 5 2016-04-10 2016-05-30
5 2016-04-25 2016-05-24 51 4000 2016-04-25 2016-05-24 5 2016-04-10 2016-05-30
6 2016-05-25 2016-05-30 51 4000 2016-05-25 2016-06-24 5 2016-04-10 2016-05-30