SQL获得两个累计总和的平衡点

时间:2019-05-03 09:34:14

标签: sql sql-server cumulative-sum balance

下面我提供了一个代码,该代码在一定程度上完成了这个有趣的任务,但是由于我的SQL知识限制,该代码可能设计不佳。主要问题是,查询在执行时会给出 random (更确切地说是3种不同)的结果。我的猜测是,嵌套查询中的行按“随机”选择的列进行排序,这就是为什么最终结果不同(平衡点取决于顺序)的原因。

内部带有SELECT的{​​{1}}创建一个r日期列表和两个累积和,例如:

GROUP

尝试在附件中添加示例数据(由于注释下方而删除)。

在第二个嵌套的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

1 个答案:

答案 0 :(得分:0)

建议ROW_NUMBER()本身并不能帮助克服问题。我必须将任务分为两个步骤:拳头,我必须设置一个变量@bDate来存储2个内部嵌套的SELECT的结果,然后在单独的{{1 }}步骤。

SELECT