在SQL Server中工作,我有一个包含4列的表
随着时间的推移,每个公司的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%
答案 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