SQL Partition data within and outside of a Common

2019-08-11 07:21发布

问题:

I am using SQL Server 2012 I have the following sample result set. The columns with the Tot Prefix are derived from the columns to the left.

What I am trying to do is partition data for a given date, and a given AssetStyle. Based on this criteria I want to sum profit and sum ACB. I then want to divide the results of these two sums for a total return number. The sample data is below.

ValuationDate   CustodianaccountNum AssetStyle  AssetClass  Profit  ACB NetReturn   TotProfit   TotACB  TotReturn
3/31/2007   1111    All Cap US All Cap  2552.55337  1069804.43  0.002386    719511.4487 7859959.87  0.091541364
3/31/2007   2222    All Cap US All Cap  1085.121285 1547961.89  0.000701    719511.4487 7859959.87  0.091541364
3/31/2007   3333    All Cap US All Cap  715873.774  3298000 0.217063    719511.4487 7859959.87  0.091541364
3/31/2007   4444    All Cap US All Cap  0   1944193.55  0   719511.4487 7859959.87  0.091541364
4/30/2007   1111    All Cap US All Cap  1374.387675 554859.78   0.002477    404343.9809 5803741.618 0.069669535
4/30/2007   2222    All Cap US All Cap  8041.548001 1038959.69  0.00774 404343.9809 5803741.618 0.069669535
4/30/2007   3333    All Cap US All Cap  -714.739726 554922.1475 -0.001288   404343.9809 5803741.618 0.069669535
4/30/2007   4444    All Cap US All Cap  395642.785  3655000 0.108247    404343.9809 5803741.618 0.069669535
3/31/2008   1111    Alt. Investment Strategies  Alternative Investments -6701.16054 1445773.579 -0.004635   -46461.95138    2709953.979 -0.017144923
3/31/2008   2222    Alt. Investment Strategies  Alternative Investments -2859.33957 37854.99999 -0.075534   -46461.95138    2709953.979 -0.017144923
3/31/2008   3333    Alt. Investment Strategies  Alternative Investments 0   247481.1    0   -46461.95138    2709953.979 -0.017144923
3/31/2008   4444    Alt. Investment Strategies  Alternative Investments -36901.45127    978844.3    -0.037699   -46461.95138    2709953.979 -0.017144923

I am attempting to get this result based on the following query.

WITH DATA AS
(
SELECT 
  ValuationDate, 
  CustodianaccountNum,
  AssetStyle, 
  AssetClass, 
  Profit, 
  ACB, 
  NetReturn, 
  SUM(Profit) OVER  (PARTITION by  AssetStyle, ValuationDate) AS TotProfit,
  SUM(ACB) OVER  (PARTITION by  AssetStyle, ValuationDate) AS TotACB
FROM 
  [PWM_Performance].[dbo].[BucketPerformance2]
)
SELECT 
  *, 
  SUM(TotProfit/TotACB) OVER  (PARTITION by  AssetStyle, ValuationDate) AS TotReturn
FROM data
  WHERE Totacb > 1
  ORDER BY AssetStyle, ValuationDate

I am getting the expected result for TotProfit and totACB, but I am not getting the correct result for TotReturn. The sample data shows the correct result but I am getting different values that aren't the sum of the data subsets I have indicated in my partition statement.

I am using a CTE because I don't think I can derive a calculation from the two preceding derived sums of profit and ACB.

回答1:

WITH DATA AS
(
SELECT 
  ValuationDate, 
  CustodianaccountNum,
  AssetStyle, 
  AssetClass, 
  Profit, 
  ACB, 
  NetReturn, 
  SUM(Profit) OVER (PARTITION BY  AssetStyle, ValuationDate) AS TotProfit,
  SUM(ACB) OVER (PARTITION BY  AssetStyle, ValuationDate) AS TotACB
FROM PWM_Performance.dbo.BucketPerformance2
)
SELECT 
  *, 
  TotProfit / TotACB AS TotReturn
FROM data
WHERE TotACB > 1
ORDER BY AssetStyle, ValuationDate

You already had the right numerator and denominator in hand. The partitions in style and date each have four rows all having the same values. So when you summed over identical partitions a second time it was simply adding the same ratio over and over: division was all you needed in order to finish the calculation. And had you not been filtering on TotACB you could have eliminated the CTE.

The other answer works in terms of the algebra but it's doing extra work. Instead of just directly spitting out 1/2, as an example, it has to work out (1+1+1+1) / (2+2+2+2). Performance might eventually be a factor and there is definitely some potential for differences in the result given the nature of floating point.



回答2:

I think you're looking for:

SUM(TotProfit) OVER  (PARTITION by  AssetStyle, ValuationDate) / 
    SUM(TotACB) OVER  (PARTITION by  AssetStyle, ValuationDate)

That is, sum your numerator and denominator independently, then divide those sums.