如何根据日期字段获取字段的总和

时间:2018-03-20 22:04:10

标签: sql sql-server

对不起,如果标题没有做到这个问题正义,但请推荐一个新标题,如果你有一个更好的。

我需要完成的是我需要根据RecDates之间的范围获取QtyOnHand(对于给定的AffectedDate)/ sum(IssQty)。因此,如果AffectedDate ='2015-2',那么我想要将RecDate在'2014-2'和'2015-1'之间的所有IssQty相加。我希望每个AffectedDate行都有这种类型的公式。因此它可以即时计算,这意味着它将始终采用AffectedDates年和月和-12,然​​后根据RecDate将IssQty加在一起。这里有些例子。

ItemKey RecDate IssQty  AffectedDate    QtyOnHand
20406   2014-1   751.898       2014-1           842.132
20406   2014-2   744.102       2014-2           539.03
20406   2014-5   493.847       2014-5           486.183
20406   2014-7   494.834      2014-7            1314.209
20406   2014-8   494.217       2014-8           819.992
20406   2014-9   741.017       2014-9          1401.975
20406   2014-10  889.714       2014-10         512.261
20406   2014-12  740.647       2014-12        640.19
20406   2015-2   496.068       2015-2         144.122
20406   2015-3   496.068       2015-3         530.054
20406   2015-5   370.941       2015-5        159.113
20406   2015-7   989.668       2015-7        492.19
20406   2015-8   792.228       2015-8        890.662
20406   2015-9   744.102       2015-9        1028.56
  1. AffectedDate ='2015-3'所以请在'2014-03'和'2015-02'的RecDate之间获取该AffectedDate [530.054] / Sum(IssQty)的QtyOnHand

  2. AffectedDate ='2015-5'所以请在'2014-05'和'2015-04'的RecDate之间获取该AffectedDate [159.113] / Sum(IssQty)的QtyOnHand

  3. 这些是我希望这个公式如何工作的例子。

2 个答案:

答案 0 :(得分:1)

好的,让我们首先从基础开始。就像Bertrand先生说2014-1不是约会对象一样,它看起来就像你在说" 2014减去1" (2013年)。我认为它真正意味着代表的是2014年的第一个月,但是,如果您想存储日期,请将它们存储为date。你会注意到CONVERT(date,'2014-1)会失败。

我不打算将这些值转换为日期,但我有必要在我的示例数据中执行此操作;也许那会帮助你。

CREATE TABLE #Sample (ItemKey int,
                      RecDate date, --The source data is not a date
                      IssQty decimal(10,3),
                      AffectedDate date, --The sourse data is not a date
                      QtyOnHand decimal(10,3));
INSERT INTO #Sample
SELECT ItemKey,
       CONVERT(date,CASE LEN(RecDate) WHEN 6 THEN STUFF(RecDate,5,1,'0') + '01'
                                      WHEN 7 THEN REPLACE(RecDate,'-','') + '01' END),
       IssQty,
       CONVERT(date,CASE LEN(AffectedDate) WHEN 6 THEN STUFF(AffectedDate,5,1,'0') + '01'
                                           WHEN 7 THEN REPLACE(AffectedDate,'-','') + '01' END),
       QtyOnHand
FROM (VALUES (20406,'2014-1',751.898,'2014-1',842.132  ),
             (20406,'2014-2',744.102,'2014-2',539.03   ),
             (20406,'2014-5',493.847,'2014-5',486.183  ),
             (20406,'2014-7',494.834,'2014-7',1314.209 ),
             (20406,'2014-8',494.217,'2014-8',819.992  ),
             (20406,'2014-9',741.017,'2014-9',1401.975 ),
             (20406,'2014-10',889.714,'2014-10',512.261),
             (20406,'2014-12',740.647,'2014-12',640.19 ),
             (20406,'2015-2',496.068,'2015-2',144.122  ),
             (20406,'2015-3',496.068,'2015-3',530.054  ),
             (20406,'2015-5',370.941,'2015-5',159.113  ),
             (20406,'2015-7',989.668,'2015-7',492.19   ),
             (20406,'2015-8',792.228,'2015-8',890.662  ),
             (20406,'2015-9',744.102,'2015-9',1028.56  )) V(ItemKey, RecDate, IssQty, AffectedDate, QtyOnHand);

接下来,我们在这里错过了几个月,这是一个问题,因为您想要过去12个月的数据。因此,我们需要填写这些内容。我将使用日历表(您需要谷歌这一点,在这里我的名为DimDate)。

然后,因为我们有每行的记录,我们可以使用ROWS BETWEEN导致:

WITH MaxMin AS(
    SELECT ItemKey, MIN(AffectedDate) AS MinDate, MAX(AffectedDate) AS MaxDate
    FROM #Sample
    GROUP BY ItemKey),
WithNewColumn AS(
    SELECT MM.ItemKey,
           S.RecDate,
           S.IssQty,
           DD.[Date] AS AffectedDate,
           S.QtyOnHand,
           S.QtyOnHand / SUM(S.IssQty) OVER (PARTITION By MM.ItemKey ORDER BY DD.[Date]
                                             ROWS BETWEEN 13 PRECEDING AND 1 PRECEDING) AS YourNewColumn
    FROM MaxMin MM
         JOIN DimDate DD ON DD.[Date] BETWEEN MM.MinDate AND MM.MaxDate AND DD.[Calendar Day] = 1
         LEFT JOIN #Sample S ON MM.ItemKey = S.ItemKey
                            AND DD.[Date] = S.AffectedDate)
SELECT *
FROM WithNewColumn
WHERE RecDate IS NOT NULL --eliminate the NULLs (if you want to). if not, this isn't needed, nor the CTE above
ORDER BY ItemKey, AffectedDate;

答案 1 :(得分:0)

如果您的日期没有空白,则只能使用一个sum窗口功能解决您的问题。所以你需要自我加入。以下是使用apply

的一个选项
select 
    *, a.QtyOnHand / c.total
from 
    myTable a
    outer apply (
        select
            total = sum(IssQty)
        from
            myTable b
        where
            b.RecDate between dateadd(mm, -12, a.AffectedDate) and dateadd(mm, -1, a.AffectedDate)
    ) c