SQL求两次累计和的平衡点
SQL getting balance point of two cumulative sums
下面我提供了一个代码,它在一定程度上完成了这个有趣的任务,但由于我的 SQL 知识限制可能设计不佳。主要问题是,查询在执行时给出 random (更确切地说是 3 个不同的)结果。我的猜测是,嵌套查询中的行按 "randomly" 选定列排序,这就是最终结果不同的原因(平衡点取决于顺序)。
内部 SELECT
和 GROUP
创建一个 r-dates 列表和两个累积和,例如:
rIndex r TotalPerDay CumulativeSum1 CumulativeSum2
1 02.05.2019 92,81 92,81 0
2 03.05.2019 24,81 117,61 0
3 06.05.2019 43,79 161,40 60
4 07.05.2019 78,65 240,05 120
5 09.05.2019 33,99 274,04 180
6 10.05.2019 73,22 347,26 240
7 13.05.2019 19,24 366,50 300
8 14.05.2019 150,77 517,27 360
9 15.05.2019 22,69 539,95 420
10 16.05.2019 4,96 544,91 480
11 17.05.2019 17,45 562,36 540
12 20.05.2019 27,19 589,55 600
13 21.05.2019 12,45 602,00 660
14 22.05.2019 18,08 620,08 720
15 23.05.2019 3,49 623,57 780
16 24.05.2019 10,51 634,09 840
17 27.05.2019 6,19 640,28 900
18 28.05.2019 3,01 643,29 960
19 29.05.2019 2,68 645,97 1020
20 30.05.2019 184,51 830,48 1080
样本数据的尝试在附件中(由于下面的评论而被删除)。
在第二个嵌套 SELECT
中,我找到了一个平衡点,这是一个(第一个)日期,其中 CumulativeSum1 > CumulativeSum2
。然后我必须找到一个带总和的天数索引(因为也有没有数据的天数),这就是最终结果;它是下面查询中最顶层的 SELECT
:
DECLARE @eDate as Date
DECLARE @DayLimit INT
SET @DayLimit = 60 -- let's assume a constant here
SET @eDate = DATEFROMPARTS('2019','05','31')
-- get balance point INDEX over non-empty days
SELECT (SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND SRC3.BalanceDate) as rIndex
FROM
(
SELECT TOP 1 SRC2.rDate -- get first balance point (date)
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY SRC.rDate) as RowNo
,SRC.rDate
,SRC.TotalPerDay -- not required for processing, included just for info and check
,(SELECT (SUM((eTime-ISNULL(rDura,0))/60)) FROM MyTable1 as MT WHERE MT.r <= SRC.rDate AND MT.r < @eDate) as CumulativeSum1
,((SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND SRC.rDate) * @DayLimit) as CumulativeSum2
FROM (
SELECT
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END as rDate,
SUM((eTime-ISNULL(rDura,0))/60) as TotalPerDay
FROM MyTable1
WHERE r < @eDate
GROUP BY -- group by non-empty dates, group all past dates to yesterday
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END
) as SRC
--ORDER BY rDate
) as SRC2 -- compiled list of sums per day
WHERE SRC2.CumulativeSum2 > SRC2.CumulativeSum1; -- balance condition
) as SRC3
对于明显的问题虚心求教:
- 如何确保嵌套查询中的行顺序以获得可靠的结果?
- 我的查询设计是否有明显的错误,如何改进?
此外,我刚刚意识到最上面的查询存在差异,我在其中获得银行工作日的索引,但索引应该超过非空银行工作日...
一些示例数据:
------- CALENDAR TABLE --------------------------------------------------------------------
CREATE TABLE [dbo].[Calendar](
[cDate] [datetime] NOT NULL,
[KindOfDay] [varchar](10) NOT NULL
PRIMARY KEY CLUSTERED
(
[cDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO [dbo].[Calendar] ([cDate],[KindOfDay]) VALUES
('2019-04-20 00:00:00.000', 'SATURDAY'),
('2019-04-21 00:00:00.000', 'SUNDAY'),
('2019-04-22 00:00:00.000', 'HOLIDAY'),
('2019-04-23 00:00:00.000', 'BANKDAY'),
('2019-04-24 00:00:00.000', 'BANKDAY'),
('2019-04-25 00:00:00.000', 'BANKDAY'),
('2019-04-26 00:00:00.000', 'BANKDAY'),
('2019-04-27 00:00:00.000', 'SATURDAY'),
('2019-04-28 00:00:00.000', 'SUNDAY'),
('2019-04-29 00:00:00.000', 'BANKDAY'),
('2019-04-30 00:00:00.000', 'BANKDAY'),
('2019-05-01 00:00:00.000', 'HOLIDAY'),
('2019-05-02 00:00:00.000', 'BANKDAY'),
('2019-05-03 00:00:00.000', 'BANKDAY'),
('2019-05-04 00:00:00.000', 'SATURDAY'),
('2019-05-05 00:00:00.000', 'SUNDAY'),
('2019-05-06 00:00:00.000', 'BANKDAY'),
('2019-05-07 00:00:00.000', 'BANKDAY'),
('2019-05-08 00:00:00.000', 'HOLIDAY'),
('2019-05-09 00:00:00.000', 'BANKDAY'),
('2019-05-10 00:00:00.000', 'BANKDAY'),
('2019-05-11 00:00:00.000', 'SATURDAY'),
('2019-05-12 00:00:00.000', 'SUNDAY'),
('2019-05-13 00:00:00.000', 'BANKDAY'),
('2019-05-14 00:00:00.000', 'BANKDAY'),
('2019-05-15 00:00:00.000', 'BANKDAY'),
('2019-05-16 00:00:00.000', 'BANKDAY'),
('2019-05-17 00:00:00.000', 'BANKDAY'),
('2019-05-18 00:00:00.000', 'SATURDAY'),
('2019-05-19 00:00:00.000', 'SUNDAY'),
('2019-05-20 00:00:00.000', 'BANKDAY'),
('2019-05-21 00:00:00.000', 'BANKDAY'),
('2019-05-22 00:00:00.000', 'BANKDAY'),
('2019-05-23 00:00:00.000', 'BANKDAY'),
('2019-05-24 00:00:00.000', 'BANKDAY'),
('2019-05-25 00:00:00.000', 'SATURDAY'),
('2019-05-26 00:00:00.000', 'SUNDAY'),
('2019-05-27 00:00:00.000', 'BANKDAY'),
('2019-05-28 00:00:00.000', 'BANKDAY'),
('2019-05-29 00:00:00.000', 'BANKDAY'),
('2019-05-30 00:00:00.000', 'BANKDAY'),
('2019-05-31 00:00:00.000', 'BANKDAY'),
('2019-06-01 00:00:00.000', 'SATURDAY'),
('2019-06-02 00:00:00.000', 'SUNDAY'),
('2019-06-03 00:00:00.000', 'BANKDAY'),
('2019-06-04 00:00:00.000', 'BANKDAY'),
('2019-06-05 00:00:00.000', 'BANKDAY'),
('2019-06-06 00:00:00.000', 'BANKDAY'),
('2019-06-07 00:00:00.000', 'BANKDAY'),
('2019-06-08 00:00:00.000', 'SATURDAY'),
('2019-06-09 00:00:00.000', 'SUNDAY'),
('2019-06-10 00:00:00.000', 'BANKDAY'),
('2019-06-11 00:00:00.000', 'BANKDAY'),
('2019-06-12 00:00:00.000', 'BANKDAY'),
('2019-06-13 00:00:00.000', 'BANKDAY'),
('2019-06-14 00:00:00.000', 'BANKDAY'),
('2019-06-15 00:00:00.000', 'SATURDAY'),
('2019-06-16 00:00:00.000', 'SUNDAY'),
('2019-06-17 00:00:00.000', 'BANKDAY'),
('2019-06-18 00:00:00.000', 'BANKDAY'),
('2019-06-19 00:00:00.000', 'BANKDAY'),
('2019-06-20 00:00:00.000', 'BANKDAY')
GO
------- MyTable1 TABLE --------------------------------------------------------------------
CREATE TABLE [dbo].[MyTable1](
[ID] [int] NOT NULL,
[rDate] [date] NOT NULL,
[eTime] [decimal](12,6) NOT NULL,
[rDura] [date] NULL
)
INSERT INTO MyTable1 (ID, rDura, eTime, rDate) VALUES
(17008431,NULL,0.1855,'2019-05-02'),
(17008477,NULL,0.059,'2019-05-02'),
(17008500,NULL,0.329667,'2019-05-02'),
(17090449,NULL,3.3195,'2019-05-02'),
(16888594,NULL,13.830667,'2019-04-26'),
(16888681,NULL,12.6635,'2019-04-26'),
(16888722,NULL,8.154667,'2019-05-07'),
(16888750,NULL,7.83,'2019-05-07'),
(16888766,NULL,5.22,'2019-05-07'),
(16955798,NULL,12.35,'2019-05-07'),
(17108201,NULL,1.669833,'2019-05-07'),
(17110834,NULL,2.596667,'2019-05-02'),
(17111001,NULL,0.814667,'2019-05-06'),
(16893842,NULL,1.053,'2019-05-07'),
(16951779,NULL,2.720833,'2019-05-03'),
(16951821,NULL,4.042333,'2019-05-06'),
(17017058,NULL,0.227333,'2019-05-02'),
(17017060,NULL,1.06,'2019-05-02'),
(17017066,NULL,1.869333,'2019-05-02'),
(17019289,NULL,0.835667,'2019-04-26'),
(17020295,NULL,3.983333,'2019-04-21'),
(17106404,105,3.3545,'2019-04-29'),
(17107843,NULL,2.815167,'2019-05-07'),
(16725584,NULL,0.693,'2019-04-25'),
(17101197,NULL,3.906667,'2019-04-30'),
(17101993,NULL,0.571667,'2019-05-06'),
(17102225,NULL,3.048833,'2019-04-30'),
(17102482,NULL,7.5945,'2019-05-10'),
(16974196,NULL,1.633333,'2019-05-06'),
(17113406,NULL,0.871833,'2019-05-02'),
(17113408,NULL,0.749833,'2019-05-02'),
(17113784,NULL,1.961333,'2019-05-03'),
(17120601,NULL,4.033333,'2019-05-06'),
(17120609,NULL,3.983333,'2019-05-06'),
(17120618,NULL,2.626667,'2019-05-06'),
(17120626,NULL,2.64,'2019-05-06'),
(17120628,NULL,3.684167,'2019-05-06'),
(17121720,NULL,2.235,'2019-04-30'),
(17058455,NULL,5.806667,'2019-04-29'),
(17059476,NULL,2.264833,'2019-05-22'),
(17059478,NULL,182.603667,'2019-05-30'),
(17065386,NULL,5.539667,'2019-05-10'),
(16927091,NULL,1.381,'2019-05-14'),
(16927093,NULL,112.304685,'2019-05-14'),
(16991456,NULL,0.931667,'2019-04-29'),
(17122394,NULL,1.560167,'2019-05-03'),
(17126711,NULL,4.046,'2019-05-03'),
(16935823,NULL,0.359,'2019-04-25'),
(17069727,NULL,1.952833,'2019-05-03'),
(17069870,NULL,1.742333,'2019-05-02'),
(17070555,NULL,5.416667,'2019-05-02'),
(17070557,NULL,3.894167,'2019-05-02'),
(17070851,NULL,2.64,'2019-04-23'),
(17073724,NULL,0.737667,'2019-05-03'),
(17074763,NULL,1.413833,'2019-05-02'),
(17131824,NULL,4.258,'2019-05-10'),
(17132133,NULL,0.257667,'2019-05-14'),
(17132865,NULL,2.769833,'2019-05-17'),
(17138082,NULL,7.866667,'2019-05-31'),
(17139196,NULL,5.860167,'2019-05-03'),
(17139200,NULL,1.479667,'2019-05-03'),
(16983337,NULL,2.951667,'2019-05-02'),
(17028542,NULL,0.680333,'2019-05-13'),
(16823160,NULL,5,'2019-05-06'),
(16823168,NULL,5,'2019-05-06'),
(16823182,NULL,5,'2019-05-06'),
(16823192,NULL,5,'2019-05-06'),
(16906776,NULL,0.8635,'2019-05-02'),
(17082286,NULL,3.333333,'2019-05-09'),
(17083776,NULL,2.317167,'2019-04-25'),
(17083778,NULL,1.447167,'2019-05-02'),
(17084568,NULL,0.2375,'2019-05-02'),
(17154415,NULL,2.64,'2019-05-14'),
(17154425,NULL,2.626667,'2019-05-14'),
(17154453,NULL,0.052,'2019-05-06'),
(17155029,NULL,3.256667,'2019-05-22'),
(17157159,NULL,1.333333,'2019-05-15'),
(16994233,NULL,0.252167,'2019-04-29'),
(17039767,NULL,1.401667,'2019-05-10'),
(17040346,NULL,4.021667,'2019-05-09'),
(17040815,NULL,1.2675,'2019-05-16'),
(17042063,NULL,0.213333,'2019-05-03'),
(17050144,NULL,0.976667,'2019-05-02'),
(17050150,NULL,0.837167,'2019-05-20'),
(17051422,NULL,1.826,'2019-05-07'),
(17142464,NULL,0.464333,'2019-05-06'),
(17145501,NULL,4.745333,'2019-06-06'),
(17145980,NULL,0.195167,'2019-05-07'),
(17145999,NULL,1.330833,'2019-05-07'),
(17146001,NULL,1.503833,'2019-05-06'),
(17146011,NULL,1.22,'2019-05-03'),
(17146017,NULL,0.373,'2019-05-07'),
(17146023,NULL,0.5745,'2019-05-03'),
(17146127,NULL,1.7835,'2019-05-15'),
(17146131,NULL,13.5595,'2019-05-07'),
(17152617,NULL,4.535667,'2019-05-10'),
(17154390,NULL,3.983333,'2019-05-14'),
(17154398,NULL,5.416667,'2019-05-14'),
(17154400,NULL,3.684167,'2019-05-14')
GO
建议 ROW_NUMBER()
没有帮助解决问题。我必须将任务分为两个步骤:首先,我必须设置一个变量 @bDate
来存储 2 个内部嵌套 SELECT
的结果,然后在单独的 [=13] 中找到该日期的索引=]步.
DECLARE @eDate as Date
DECLARE @DayLimit INT
SET @DayLimit = 60 -- let's assume a constant here
SET @eDate = DATEFROMPARTS('2019','05','31')
-- get balance point INDEX over non-empty days
SELECT TOP 1 @bDate = SRC2.rDate -- get first balance point (date)
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY SRC.rDate) as RowNo
,SRC.rDate
,SRC.TotalPerDay -- not required for processing, included just for info and check
,(SELECT (SUM((eTime-ISNULL(rDura,0))/60)) FROM MyTable1 as MT WHERE MT.r <= SRC.rDate AND MT.r < @eDate) as CumulativeSum1
,((SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND SRC.rDate) * @DayLimit) as CumulativeSum2
FROM (
SELECT
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END as rDate,
SUM((eTime-ISNULL(rDura,0))/60) as TotalPerDay
FROM MyTable1
WHERE r < @eDate
GROUP BY -- group by non-empty dates, group all past dates to yesterday
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END
) as SRC
--ORDER BY rDate
) as SRC2 -- compiled list of sums per day
WHERE SRC2.CumulativeSum2 > SRC2.CumulativeSum1; -- balance condition
-- get the index of bank day from Today
SELECT (SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND @bDate);
下面我提供了一个代码,它在一定程度上完成了这个有趣的任务,但由于我的 SQL 知识限制可能设计不佳。主要问题是,查询在执行时给出 random (更确切地说是 3 个不同的)结果。我的猜测是,嵌套查询中的行按 "randomly" 选定列排序,这就是最终结果不同的原因(平衡点取决于顺序)。
内部 SELECT
和 GROUP
创建一个 r-dates 列表和两个累积和,例如:
rIndex r TotalPerDay CumulativeSum1 CumulativeSum2
1 02.05.2019 92,81 92,81 0
2 03.05.2019 24,81 117,61 0
3 06.05.2019 43,79 161,40 60
4 07.05.2019 78,65 240,05 120
5 09.05.2019 33,99 274,04 180
6 10.05.2019 73,22 347,26 240
7 13.05.2019 19,24 366,50 300
8 14.05.2019 150,77 517,27 360
9 15.05.2019 22,69 539,95 420
10 16.05.2019 4,96 544,91 480
11 17.05.2019 17,45 562,36 540
12 20.05.2019 27,19 589,55 600
13 21.05.2019 12,45 602,00 660
14 22.05.2019 18,08 620,08 720
15 23.05.2019 3,49 623,57 780
16 24.05.2019 10,51 634,09 840
17 27.05.2019 6,19 640,28 900
18 28.05.2019 3,01 643,29 960
19 29.05.2019 2,68 645,97 1020
20 30.05.2019 184,51 830,48 1080
样本数据的尝试在附件中(由于下面的评论而被删除)。
在第二个嵌套 SELECT
中,我找到了一个平衡点,这是一个(第一个)日期,其中 CumulativeSum1 > CumulativeSum2
。然后我必须找到一个带总和的天数索引(因为也有没有数据的天数),这就是最终结果;它是下面查询中最顶层的 SELECT
:
DECLARE @eDate as Date
DECLARE @DayLimit INT
SET @DayLimit = 60 -- let's assume a constant here
SET @eDate = DATEFROMPARTS('2019','05','31')
-- get balance point INDEX over non-empty days
SELECT (SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND SRC3.BalanceDate) as rIndex
FROM
(
SELECT TOP 1 SRC2.rDate -- get first balance point (date)
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY SRC.rDate) as RowNo
,SRC.rDate
,SRC.TotalPerDay -- not required for processing, included just for info and check
,(SELECT (SUM((eTime-ISNULL(rDura,0))/60)) FROM MyTable1 as MT WHERE MT.r <= SRC.rDate AND MT.r < @eDate) as CumulativeSum1
,((SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND SRC.rDate) * @DayLimit) as CumulativeSum2
FROM (
SELECT
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END as rDate,
SUM((eTime-ISNULL(rDura,0))/60) as TotalPerDay
FROM MyTable1
WHERE r < @eDate
GROUP BY -- group by non-empty dates, group all past dates to yesterday
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END
) as SRC
--ORDER BY rDate
) as SRC2 -- compiled list of sums per day
WHERE SRC2.CumulativeSum2 > SRC2.CumulativeSum1; -- balance condition
) as SRC3
对于明显的问题虚心求教:
- 如何确保嵌套查询中的行顺序以获得可靠的结果?
- 我的查询设计是否有明显的错误,如何改进?
此外,我刚刚意识到最上面的查询存在差异,我在其中获得银行工作日的索引,但索引应该超过非空银行工作日...
一些示例数据:
------- CALENDAR TABLE --------------------------------------------------------------------
CREATE TABLE [dbo].[Calendar](
[cDate] [datetime] NOT NULL,
[KindOfDay] [varchar](10) NOT NULL
PRIMARY KEY CLUSTERED
(
[cDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO [dbo].[Calendar] ([cDate],[KindOfDay]) VALUES
('2019-04-20 00:00:00.000', 'SATURDAY'),
('2019-04-21 00:00:00.000', 'SUNDAY'),
('2019-04-22 00:00:00.000', 'HOLIDAY'),
('2019-04-23 00:00:00.000', 'BANKDAY'),
('2019-04-24 00:00:00.000', 'BANKDAY'),
('2019-04-25 00:00:00.000', 'BANKDAY'),
('2019-04-26 00:00:00.000', 'BANKDAY'),
('2019-04-27 00:00:00.000', 'SATURDAY'),
('2019-04-28 00:00:00.000', 'SUNDAY'),
('2019-04-29 00:00:00.000', 'BANKDAY'),
('2019-04-30 00:00:00.000', 'BANKDAY'),
('2019-05-01 00:00:00.000', 'HOLIDAY'),
('2019-05-02 00:00:00.000', 'BANKDAY'),
('2019-05-03 00:00:00.000', 'BANKDAY'),
('2019-05-04 00:00:00.000', 'SATURDAY'),
('2019-05-05 00:00:00.000', 'SUNDAY'),
('2019-05-06 00:00:00.000', 'BANKDAY'),
('2019-05-07 00:00:00.000', 'BANKDAY'),
('2019-05-08 00:00:00.000', 'HOLIDAY'),
('2019-05-09 00:00:00.000', 'BANKDAY'),
('2019-05-10 00:00:00.000', 'BANKDAY'),
('2019-05-11 00:00:00.000', 'SATURDAY'),
('2019-05-12 00:00:00.000', 'SUNDAY'),
('2019-05-13 00:00:00.000', 'BANKDAY'),
('2019-05-14 00:00:00.000', 'BANKDAY'),
('2019-05-15 00:00:00.000', 'BANKDAY'),
('2019-05-16 00:00:00.000', 'BANKDAY'),
('2019-05-17 00:00:00.000', 'BANKDAY'),
('2019-05-18 00:00:00.000', 'SATURDAY'),
('2019-05-19 00:00:00.000', 'SUNDAY'),
('2019-05-20 00:00:00.000', 'BANKDAY'),
('2019-05-21 00:00:00.000', 'BANKDAY'),
('2019-05-22 00:00:00.000', 'BANKDAY'),
('2019-05-23 00:00:00.000', 'BANKDAY'),
('2019-05-24 00:00:00.000', 'BANKDAY'),
('2019-05-25 00:00:00.000', 'SATURDAY'),
('2019-05-26 00:00:00.000', 'SUNDAY'),
('2019-05-27 00:00:00.000', 'BANKDAY'),
('2019-05-28 00:00:00.000', 'BANKDAY'),
('2019-05-29 00:00:00.000', 'BANKDAY'),
('2019-05-30 00:00:00.000', 'BANKDAY'),
('2019-05-31 00:00:00.000', 'BANKDAY'),
('2019-06-01 00:00:00.000', 'SATURDAY'),
('2019-06-02 00:00:00.000', 'SUNDAY'),
('2019-06-03 00:00:00.000', 'BANKDAY'),
('2019-06-04 00:00:00.000', 'BANKDAY'),
('2019-06-05 00:00:00.000', 'BANKDAY'),
('2019-06-06 00:00:00.000', 'BANKDAY'),
('2019-06-07 00:00:00.000', 'BANKDAY'),
('2019-06-08 00:00:00.000', 'SATURDAY'),
('2019-06-09 00:00:00.000', 'SUNDAY'),
('2019-06-10 00:00:00.000', 'BANKDAY'),
('2019-06-11 00:00:00.000', 'BANKDAY'),
('2019-06-12 00:00:00.000', 'BANKDAY'),
('2019-06-13 00:00:00.000', 'BANKDAY'),
('2019-06-14 00:00:00.000', 'BANKDAY'),
('2019-06-15 00:00:00.000', 'SATURDAY'),
('2019-06-16 00:00:00.000', 'SUNDAY'),
('2019-06-17 00:00:00.000', 'BANKDAY'),
('2019-06-18 00:00:00.000', 'BANKDAY'),
('2019-06-19 00:00:00.000', 'BANKDAY'),
('2019-06-20 00:00:00.000', 'BANKDAY')
GO
------- MyTable1 TABLE --------------------------------------------------------------------
CREATE TABLE [dbo].[MyTable1](
[ID] [int] NOT NULL,
[rDate] [date] NOT NULL,
[eTime] [decimal](12,6) NOT NULL,
[rDura] [date] NULL
)
INSERT INTO MyTable1 (ID, rDura, eTime, rDate) VALUES
(17008431,NULL,0.1855,'2019-05-02'),
(17008477,NULL,0.059,'2019-05-02'),
(17008500,NULL,0.329667,'2019-05-02'),
(17090449,NULL,3.3195,'2019-05-02'),
(16888594,NULL,13.830667,'2019-04-26'),
(16888681,NULL,12.6635,'2019-04-26'),
(16888722,NULL,8.154667,'2019-05-07'),
(16888750,NULL,7.83,'2019-05-07'),
(16888766,NULL,5.22,'2019-05-07'),
(16955798,NULL,12.35,'2019-05-07'),
(17108201,NULL,1.669833,'2019-05-07'),
(17110834,NULL,2.596667,'2019-05-02'),
(17111001,NULL,0.814667,'2019-05-06'),
(16893842,NULL,1.053,'2019-05-07'),
(16951779,NULL,2.720833,'2019-05-03'),
(16951821,NULL,4.042333,'2019-05-06'),
(17017058,NULL,0.227333,'2019-05-02'),
(17017060,NULL,1.06,'2019-05-02'),
(17017066,NULL,1.869333,'2019-05-02'),
(17019289,NULL,0.835667,'2019-04-26'),
(17020295,NULL,3.983333,'2019-04-21'),
(17106404,105,3.3545,'2019-04-29'),
(17107843,NULL,2.815167,'2019-05-07'),
(16725584,NULL,0.693,'2019-04-25'),
(17101197,NULL,3.906667,'2019-04-30'),
(17101993,NULL,0.571667,'2019-05-06'),
(17102225,NULL,3.048833,'2019-04-30'),
(17102482,NULL,7.5945,'2019-05-10'),
(16974196,NULL,1.633333,'2019-05-06'),
(17113406,NULL,0.871833,'2019-05-02'),
(17113408,NULL,0.749833,'2019-05-02'),
(17113784,NULL,1.961333,'2019-05-03'),
(17120601,NULL,4.033333,'2019-05-06'),
(17120609,NULL,3.983333,'2019-05-06'),
(17120618,NULL,2.626667,'2019-05-06'),
(17120626,NULL,2.64,'2019-05-06'),
(17120628,NULL,3.684167,'2019-05-06'),
(17121720,NULL,2.235,'2019-04-30'),
(17058455,NULL,5.806667,'2019-04-29'),
(17059476,NULL,2.264833,'2019-05-22'),
(17059478,NULL,182.603667,'2019-05-30'),
(17065386,NULL,5.539667,'2019-05-10'),
(16927091,NULL,1.381,'2019-05-14'),
(16927093,NULL,112.304685,'2019-05-14'),
(16991456,NULL,0.931667,'2019-04-29'),
(17122394,NULL,1.560167,'2019-05-03'),
(17126711,NULL,4.046,'2019-05-03'),
(16935823,NULL,0.359,'2019-04-25'),
(17069727,NULL,1.952833,'2019-05-03'),
(17069870,NULL,1.742333,'2019-05-02'),
(17070555,NULL,5.416667,'2019-05-02'),
(17070557,NULL,3.894167,'2019-05-02'),
(17070851,NULL,2.64,'2019-04-23'),
(17073724,NULL,0.737667,'2019-05-03'),
(17074763,NULL,1.413833,'2019-05-02'),
(17131824,NULL,4.258,'2019-05-10'),
(17132133,NULL,0.257667,'2019-05-14'),
(17132865,NULL,2.769833,'2019-05-17'),
(17138082,NULL,7.866667,'2019-05-31'),
(17139196,NULL,5.860167,'2019-05-03'),
(17139200,NULL,1.479667,'2019-05-03'),
(16983337,NULL,2.951667,'2019-05-02'),
(17028542,NULL,0.680333,'2019-05-13'),
(16823160,NULL,5,'2019-05-06'),
(16823168,NULL,5,'2019-05-06'),
(16823182,NULL,5,'2019-05-06'),
(16823192,NULL,5,'2019-05-06'),
(16906776,NULL,0.8635,'2019-05-02'),
(17082286,NULL,3.333333,'2019-05-09'),
(17083776,NULL,2.317167,'2019-04-25'),
(17083778,NULL,1.447167,'2019-05-02'),
(17084568,NULL,0.2375,'2019-05-02'),
(17154415,NULL,2.64,'2019-05-14'),
(17154425,NULL,2.626667,'2019-05-14'),
(17154453,NULL,0.052,'2019-05-06'),
(17155029,NULL,3.256667,'2019-05-22'),
(17157159,NULL,1.333333,'2019-05-15'),
(16994233,NULL,0.252167,'2019-04-29'),
(17039767,NULL,1.401667,'2019-05-10'),
(17040346,NULL,4.021667,'2019-05-09'),
(17040815,NULL,1.2675,'2019-05-16'),
(17042063,NULL,0.213333,'2019-05-03'),
(17050144,NULL,0.976667,'2019-05-02'),
(17050150,NULL,0.837167,'2019-05-20'),
(17051422,NULL,1.826,'2019-05-07'),
(17142464,NULL,0.464333,'2019-05-06'),
(17145501,NULL,4.745333,'2019-06-06'),
(17145980,NULL,0.195167,'2019-05-07'),
(17145999,NULL,1.330833,'2019-05-07'),
(17146001,NULL,1.503833,'2019-05-06'),
(17146011,NULL,1.22,'2019-05-03'),
(17146017,NULL,0.373,'2019-05-07'),
(17146023,NULL,0.5745,'2019-05-03'),
(17146127,NULL,1.7835,'2019-05-15'),
(17146131,NULL,13.5595,'2019-05-07'),
(17152617,NULL,4.535667,'2019-05-10'),
(17154390,NULL,3.983333,'2019-05-14'),
(17154398,NULL,5.416667,'2019-05-14'),
(17154400,NULL,3.684167,'2019-05-14')
GO
建议 ROW_NUMBER()
没有帮助解决问题。我必须将任务分为两个步骤:首先,我必须设置一个变量 @bDate
来存储 2 个内部嵌套 SELECT
的结果,然后在单独的 [=13] 中找到该日期的索引=]步.
DECLARE @eDate as Date
DECLARE @DayLimit INT
SET @DayLimit = 60 -- let's assume a constant here
SET @eDate = DATEFROMPARTS('2019','05','31')
-- get balance point INDEX over non-empty days
SELECT TOP 1 @bDate = SRC2.rDate -- get first balance point (date)
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY SRC.rDate) as RowNo
,SRC.rDate
,SRC.TotalPerDay -- not required for processing, included just for info and check
,(SELECT (SUM((eTime-ISNULL(rDura,0))/60)) FROM MyTable1 as MT WHERE MT.r <= SRC.rDate AND MT.r < @eDate) as CumulativeSum1
,((SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND SRC.rDate) * @DayLimit) as CumulativeSum2
FROM (
SELECT
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END as rDate,
SUM((eTime-ISNULL(rDura,0))/60) as TotalPerDay
FROM MyTable1
WHERE r < @eDate
GROUP BY -- group by non-empty dates, group all past dates to yesterday
CASE
WHEN CAST(r as DATE) < CAST(GETDATE() as date)
THEN DATEADD(dd,-1,CAST(GETDATE() as date))
ELSE CAST(r as date)
END
) as SRC
--ORDER BY rDate
) as SRC2 -- compiled list of sums per day
WHERE SRC2.CumulativeSum2 > SRC2.CumulativeSum1; -- balance condition
-- get the index of bank day from Today
SELECT (SELECT COUNT(cDate) FROM Calendar WHERE KindOfDay = 'BANKDAY' AND cDate BETWEEN GETDATE() AND @bDate);