随时间推移的最小值和最大值的T-SQL比较

时间:2018-01-24 19:46:33

标签: sql sql-server

在SQL Server中工作,我有一个包含4列的表

  • ACCOUNTID
  • 帐户名
  • SubscriptionAmt
  • DateKey

随着时间的推移,每个公司的SubscriptionAmt按月(DateKey,即201801)列出。

我想写一个包含

的选择语句
AccountId, AccountName, EarliestSubscriptionAmt, LatestSubscriptionAmt, Difference

我知道下面的努力是不正确的。我知道我必须在子查询中进行某种分区,但我不能把它放在它上面

感谢任何帮助

SELECT 
    [Account ID],
    [Account Name],
    b.EarlySub,
    c.LatestSub,
    (c.LatestSub - b.EarlySub / b.EarlySub) * 100 as PercentageChange
FROM 
    SubTable AS
LEFT JOIN
    (SELECT
         [Account ID],
         SubscriptionAmt AS EarlySub
     FROM 
         SubTable
     WHERE 
         DateKey = MIN(DateKey)) AS b ON a.[Account ID] = b.[Account ID]
LEFT JOIN
    (SELECT
         [Account ID],
         SubscriptionAmt AS LatestSub
     FROM 
         SubTable
     WHERE 
         DateKey = MAX(DateKey)) AS c ON a.[Account ID] = c.[Account ID]

示例数据:

AccountId   AccountName   SubscriptionAmt   DateKey  
----------------------------------------------------
    1       Bob's Store        100          201701
    1       Bob's Store        200          201702
    1       Bob's Store        300          201703
    1       Bob's Store        400          201704

期望的结果:

AccountId  AccountName   EarliestSubAmt  LatestSubAmt  PercentageChange
------------------------------------------------------------------------
    1      Bob's Store       100             400           300%

3 个答案:

答案 0 :(得分:1)

完整演示:

DECLARE @TABLE TABLE
(
AccountId VARCHAR(50),
AccountName VARCHAR(50),
SubscriptionAmt INT,
DateKey VARCHAR(50)
)

INSERT INTO @TABLE
VALUES('1','Bob''s Store','100','201701'),('1','Bob''s Store','200','201702'),('1','Bob''s Store','300','201703'),('1','Bob''s Store','400','201704')

;
WITH CTE
AS
(
 SELECT  AccountId,
         AccountName,
         SubscriptionAmt,
         ROW_NUMBER()OVER(PARTITION BY AccountId,AccountName ORDER BY CAST(DateKey+'01' as DATE)) as ForMin,
         ROW_NUMBER()OVER(PARTITION BY AccountId,AccountName ORDER BY CAST(DateKey+'01' as DATE) DESC) as ForMAX                      
        FROM @TABLE
)
SELECT A.AccountId,
       A.AccountName,
       A.SubscriptionAmt as EarliestSubAmt,
       B.SubscriptionAmt as LatestSubAmt,
       CAST(((B.SubscriptionAmt - A.SubscriptionAmt)/A.SubScriptionAmt ) as varchar(50)) + '%' as PercentageChange
FROM CTE as A
INNER JOIN CTE as B
ON A.AccountId = B.AccountId
AND A.AccountName = B.AccountName
WHERE A.ForMin = 1 AND B.ForMAX = 1

答案 1 :(得分:1)

您可以通过首先使用外部申请获取每个帐户ID的最小日期和最大日期,然后使用案例表达式获取最小或最大金额来获取最小和最大金额

select  [AccountId], [AccountName],
        MIN(CASE WHEN DateKey = MinDateKey THEN SubscriptionAmt END) as EarliestSubAmt,
        MAX(CASE WHEN DateKey = MaxDateKey THEN SubscriptionAmt END) as LatestSubAmt

from    SubTable s
outer apply (
        select Min(DateKey) MinDateKey, Max(DateKey) MaxDateKey from SubTable t where s.AccountId = t.AccountId
) t
group by [AccountId], [AccountName]

你可以包装所有这些以获得百分比变化。

select  *,
        ((LatestSubAmt-EarliestSubAmt)/EarliestSubAmt) * 100 as PercentageChange
from    (
            select  [AccountId], [AccountName],
                    MIN(CASE WHEN DateKey = MinDateKey THEN SubscriptionAmt END) as EarliestSubAmt,
                    MAX(CASE WHEN DateKey = MaxDateKey THEN SubscriptionAmt END) as LatestSubAmt
            from    SubTable s
            outer apply (
                    select Min(DateKey) MinDateKey, Max(DateKey) MaxDateKey from SubTable t where s.AccountId = t.AccountId
            ) t
            group by [AccountId], [AccountName]
) s

答案 2 :(得分:1)

请使用以下查询。我已将帐户ID视为每个商店的关键值,并且不会重复。请在实施到任何系统之前进行测试。

--Data Prep
create table #Test (
        AccountId int,
        AccountName varchar(max),
        SubscriptionAmt int,
        DateKey int
        )

insert into #Test
    Select 1,'Bobs Store',100,201701
    union
    select 1,'Bobs Store',200,201702
    union
    select 1,'Bobs Store',300,201703
    union
    select 1,'Bobs Store',400,201704

--Actual code ****************************************************

select *,
    ROW_NUMBER() over(Partition by Accountid order by datekey asc) MinAm,
    ROW_NUMBER() over(Partition by Accountid order by datekey desc) MaxAm into #Final
 from #Test

Select *,
        ((LatestSubAmt-EarliestSubAmt)/EarliestSubAmt)*100 as PercentageChange
From (
  select 
        AccountId,
        AccountName,
        (select SubscriptionAmt from #Final f2 where f1.AccountId=f2.AccountId and f2.MinAm=1) EarliestSubAmt,
        (select SubscriptionAmt from #Final f2 where f1.AccountId=f2.AccountId and f2.MaxAm=1) LatestSubAmt
  from #Final f1
  Where MinAm=1) A

- ********************************************* ***********

如果您不想使用子查询

Select Distinct Accountid,
      AccountName,
      sum(case when minAm=1 then SubscriptionAmt else 0 END) over (Partition by Accountid) EarliestSubAmt ,
      sum(case when maxam=1 then SubscriptionAmt else 0 END) over (Partition by Accountid) LatestSubAmt,
      ((sum(case when maxam=1 then SubscriptionAmt else 0 END) over (Partition by Accountid)-sum(case when minAm=1 then SubscriptionAmt else 0 END) over (Partition by Accountid))
      /sum(case when minAm=1 then SubscriptionAmt else 0 END) over (Partition by Accountid))*100 PercentageChange
FRom (
select *,
    ROW_NUMBER() over(Partition by Accountid order by datekey asc) MinAm,
    ROW_NUMBER() over(Partition by Accountid order by datekey desc) MaxAm 
 from #Test
 )A