【问题标题】:Aggregate derived values with SQL使用 SQL 聚合派生值
【发布时间】:2015-08-23 20:14:30
【问题描述】:

我正在使用 SQL Server 2012。我已尽我所能进行此查询。如您所见,我使用 CTE 导出值,然后在 select 语句中使用导出的值。在这个例子中,当我连接 Quarter +Year = Period

时,这只会发生一次

我可以在 SSRS 报告的数据集中使用此查询来实现我想要的分组,但我想知道如何在 SQL 中执行此操作。当我需要派生数据然后对这些派生执行其他功能时,我一直在苦苦挣扎。 CTE 是一种方式。我在有限程度上使用了临时表,但并不精通它们的用法。这是查询。

USE SampleDW
WITH gifts AS
(
SELECT ClientBriefName,AccountIDKey,AdventID,AccountName,AccountType,FlipProvision,FlipDate,ExpectedFlipDate,GiftCategory,GiftType,
GiftDate,GiftAmount,AssetClass,SecurityType,UserDefinedCode,

 COALESCE(
CASE WHEN MONTH(giftdate)IN(1,2,3) THEN 'Q1' ELSE NULL END,
CASE WHEN MONTH(giftdate)IN(4,5,6) THEN 'Q2' ELSE NULL END,
CASE WHEN MONTH(giftdate)IN(7,8,9) THEN 'Q3' ELSE NULL END,
CASE WHEN MONTH(giftdate)IN(10,11,12) THEN 'Q4' ELSE NULL END
) AS Quarter,
CASE WHEN AccountType IN('CORP','ENDOW','OTHER','990','DCA','PRIV-TAX') THEN 'NO' ELSE 'YES' END AS ISPG,
YEAR(Giftdate) YEAR,
CASE WHEN AccountType IN('CRUT','CGA','CRUTNI','CRAT','PIF','NQI','CRUTMU','LEAD-PCT','LEAD-FIXED','GRANTOR-OWNER','PRE-69')
THEN 'YES' ELSE 'NO' END AS LIFEINCOME
FROM Generic.dbo.PO_GiftDetails
) 
SELECT ClientBriefName,AccountIDKey,AdventID,AccountName,AccountType,FlipProvision,FlipDate,ExpectedFlipDate,GiftCategory,GiftType,
GiftDate,GiftAmount,AssetClass,SecurityType,UserDefinedCode, ISPG, QUARTER,YEAR,gifts.LIFEINCOME, CAST(Quarter AS VARCHAR)+CAST(YEAR AS varchar) AS Period 
FROM gifts

结果集

      ClientBriefName   AccountIDKey    AdventID    AccountName AccountType FlipProvision   FlipDate    ExpectedFlipDate    GiftCategory    GiftType    GiftDate    GiftAmount  AssetClass  SecurityType    UserDefinedCode ISPG    QUARTER YEAR    LIFEINCOME  Period
Client1 103859  Jsmith  John Smith  CRUT    0   NULL    NULL    Standard Unitrusts  New Trusts  00:00.0 82300   e   lcus    1   YES Q4  2012    YES Q42012
Client1 100281  Jsmith  John Smith  CRAT    0   NULL    NULL    Additions to Trusts Additions to Trusts 00:00.0 5000    c   caus    2   YES Q4  2012    YES Q42012
Client2 100281  JaSmith Jane Smith  CRUT    0   NULL    NULL    Additions to Trusts Additions to Trusts 00:00.0 5000    c   caus    2   YES Q4  2012    YES Q42012
Client2 100281  JaSmith Jane Smith  CRAT    0   NULL    NULL    Additions to Trusts Additions to Trusts 00:00.0 2000    c   caus    2   YES Q4  2012    YES Q42012
Client1 103859  Jsmith  John Smith  CRUT    0   NULL    NULL    Standard Unitrusts  New Trusts  00:00.0 82300   e   lcus    1   YES Q1  2012    YES Q12012
Client1 100281  Jsmith  John Smith  CRAT    0   NULL    NULL    Additions to Trusts Additions to Trusts 00:00.0 5000    c   caus    2   YES Q1  2012    YES Q12012
Client2 100281  JaSmith Jane Smith  CRUT    0   NULL    NULL    Additions to Trusts Additions to Trusts 00:00.0 5000    c   caus    2   YES Q1  2012    YES Q12012
Client2 100281  JaSmith Jane Smith  CRAT    0   NULL    NULL    Additions to Trusts Additions to Trusts 00:00.0 2000    c   caus    2   YES Q1  2012    YES Q12012

如果我想实现类似数据透视表的输出怎么办。我以前在 SQL 中使用过数据透视,但我不确定如何以最简单的形式在此查询中使用。所需的输出将按客户对各种礼物类型的总和进行分组,所有总和的总和最后按期间分组

AdventID    Annuity Trusts  Flip Trust  Gift Annuity Pools  Net Income Unitrusts    Grand Total Period
CLIENT1 0   0   1187880.16  800 1188680.16  Q12012
CLIENT2 0   0   25014.6 500 25514.6 Q12012
CLIENT1 0   0   550123  800 550923  Q42012
CLIENT2 0   0   4851061 600 4851661 Q42012

【问题讨论】:

  • 您对COALESCE+CASEQuarter 声明看起来过分了。为什么不CASE WHEN MONTH(giftdate)IN(1,2,3) THEN 'Q1' WHEN MONTH(giftdate)IN(4,5,6) THEN 'Q2' WHEN MONTH(giftdate)IN(7,8,9) THEN 'Q3' WHEN MONTH(giftdate)IN(10,11,12) THEN 'Q4' ELSE NULL END AS Quarter,
  • 我不需要合并,但我要了解的是,一旦您开始获取数据,如何可靠地暂存数据以进行进一步的推导和转换。过去我使用 select into 然后重新开始使用新表,但这很草率且耗时。
  • lad2025 你的公式不能可靠地将月份放在各自的季度中。
  • 试试这个[Quarter] = 'Q' + CAST(DATEPART(qq, giftdate) AS CHAR(1))
  • “过去我使用 select into 然后重新开始使用新表,但这很草率且耗时。” => 多步骤使用 CTE

标签: sql sql-server-2012 aggregate pivot-table common-table-expression


【解决方案1】:

然后进行聚合,因为您可以在派生表或 CTE 上应用聚合。

下面我假设GiftType 被分解为您帖子中显示的所需结果的指定列。

WITH gifts AS
(
SELECT ClientBriefName, AccountIDKey, AdventID, AccountName, AccountType, 
       FlipProvision, FlipDate, ExpectedFlipDate, GiftCategory, GiftType,
       GiftDate, GiftAmount, AssetClass, SecurityType, UserDefinedCode,

       (CASE WHEN MONTH(GiftDate) IN (1, 2 ,3) THEN 'Q1' ELSE NULL END,
        CASE WHEN MONTH(GiftDate) IN (4, 5, 6) THEN 'Q2' ELSE NULL END,
        CASE WHEN MONTH(GiftDate) IN (7, 8, 9) THEN 'Q3' ELSE NULL END,
        CASE WHEN MONTH(GiftDate) IN (10, 11, 12) THEN 'Q4' ELSE NULL END) AS  Quarter,

       CASE WHEN AccountType IN ('CORP','ENDOW','OTHER','990','DCA','PRIV-TAX') 
            THEN 'NO' 
            ELSE 'YES' END AS ISPG,
       YEAR(Giftdate) AS [YEAR],
       CASE WHEN AccountType IN ('CRUT','CGA','CRUTNI','CRAT','PIF','NQI','CRUTMU',
                                 'LEAD-PCT', 'LEAD-FIXED','GRANTOR-OWNER','PRE-69')
            THEN 'YES' 
            ELSE 'NO' END AS LIFEINCOME
       FROM GenericDW.dbo.PO_GiftDetails
) 

/* ADJUST AGGREGATES AS NEEDED */
SELECT AdventID, Sum(CASE WHEN GiftType = 'Annuity' THEN GiftAmount ELSE 0 END) As Annuity, 
       Sum(CASE WHEN GiftType = 'Trusts' THEN GiftAmount ELSE 0 END) As Trusts, 
       Sum(CASE WHEN GiftType = 'Flip Trust' THEN GiftAmount ELSE 0 END) As [Flip Trust], 
       Sum(CASE WHEN GiftType = 'Gift' THEN GiftAmount ELSE 0 END) As Gift, 
       Sum(CASE WHEN GiftType = 'Annuity Pools' 
                THEN GiftAmount ELSE 0 END) As [Annuity Pools], 
       Sum(CASE WHEN GiftType IN ('Annuity', 'Trusts', 'Flip Trust', 'Gift', 'Annuity Pools')
                THEN GiftAmount ELSE 0) As [Net Income], 
       Sum(CASE WHEN GiftType = 'Unitrusts' THEN GiftAmount ELSE 0 END) As Unitrusts, 
       Sum(GiftAmount) As [Grand Total], 
       CAST([Quarter] + '-' + [Year] AS VARCHAR(100)) As [Period]
FROM gifts
GROUP BY AdventID, CAST([Quarter] + '-' + [Year] AS VARCHAR(100)) 

还有一个可能的支点解决​​方案

With gifts As ( ... )

SELECT AdventID, Sum([Annuity]), Sum([Trusts]), Sum([Flip Trust]), 
       Sum([Gift]), Sum([Annuity Pools]), Sum([Unitrusts]), 
       Sum([Annuity]) + Sum([Trusts]) + Sum([Flip Trust])
           + Sum([Gift]) + Sum([Annuity Pools]) As [Net Income],
       Sum([GiftAmount]) As [Grand Total], 
       CAST([Quarter] + '-' + [Year] AS VARCHAR(100)) As [Period]
FROM gifts
PIVOT (
       Sum([GiftAmount])
       For [GiftType] In
           ([Annuity], [Trusts], [Flip Trust], [Gift], [Annuity Pools], [Unitrusts])
       ) AS pivotTable
GROUP BY AdventID, CAST([Quarter] + '-' + [Year] AS VARCHAR(100)) 

【讨论】:

  • 我的查询有误。我不小心包含了公司信息。您能否将其从 K******DW.dbo.PO_GiftDetails 中删除并将其更改为 GenericDW.dbo?今晚我会测试你的查询。
  • 这里唯一不起作用的是 Period 是一个派生列,但是当我在总计之后添加它时,我收到一个错误,说它不是一个有效的分组依据.. 这是 SQL.. . CAST(Quarter AS VARCHAR)+CAST(YEAR AS varchar) as Period
  • 我通过在组中再次添加 Period 的派生值来使其工作,但是只有 ghe 总计的值其余为 0。
  • 我认为有 0,因为您定义的值略有偏差。但是,可能有 X 种礼物类型,所以我不想在案例陈述中单独列出它们。我宁愿它通过每次出现的gifttype求和,而不管有多少矩阵报告每次有新值时求和
  • @JayC - 我进行了编辑,甚至添加了一个枢轴解决方案。我不知道您数据中的不同礼品类型。请根据需要进行调整。虽然我的枢轴确定已知列,但对于动态枢轴(未知列数),请参阅各种 SO 帖子:123
猜你喜欢
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 2014-04-28
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多