【问题标题】:Aggregate/Sum function on a subquery子查询上的聚合/求和函数
【发布时间】:2021-09-10 23:04:48
【问题描述】:

我在汇总/汇总查询(子查询?)的输出时遇到问题。这是我的初始代码和输出:

代码:

SET ARITHABORT OFF 
SET ANSI_WARNINGS OFF
SELECT
AsOfDate,
round(ColA/sum(ColB) * (ColC),4) As 'Monthly_Return'
from xyz.abc
WHERE
AsOfDate BETWEEN '2021-05-25' AND '2021-05-26'
and ColD like '123%'
GROUP BY AsOfDate, ColA,ColB,ColC



|   AsOfDate |MarketV(ColA)|MarketV(ColB)|Return(ColC)|(ColD)|
|------------|-------------|-------------|------------|------|
| 2021-05-25 |   8891171.14|   8891171.14| -0.81166911|   123|
| 2021-05-25 |  14219713.92|  14219713.92|  2.12135625|   123|
| 2021-05-25 |   3102248.42|   3102248.42|  0.36907554|   123|
| 2021-05-26 |   8819004.25|   8819004.25|  0.88822511|   123|
| 2021-05-26 |  14521364.71|  14521364.71|  1.84104756|   123|
| 2021-05-26 |   3113698.06|   3113698.06|  0.44211577|   123|

|The sum of ColB for 2021-05-25 is 26,213,133.48|


|The sum of ColB for 2021-05-25 is 26,454,067.02|

我想要按日期分组的 ColAi/ColB * ColCi 的总和。

|For 2021-05-25                              |  Return |
|--------------------------------------------|---------|
|8891171.14 / 26,213,133.48 * -0.81166911   =|-0.275308|
|14219713.92 / 26,213,133.48 * 2.12135625   =|1.150762 |
|3102248.42 / 26,213,133.48 * 0.36907554    =|0.043679 |

|For 2021-05-26                              |  Return |
|--------------------------------------------|---------|
|8819004.25 / 26,454,067.02 * 0.88822511    =|0.296108 |
|14521364.71 / 26,454,067.02 * 1.84104756   =|1.0106016|
|3113698.06 / 26,454,067.02 * 0.44211577    =|0.0520379|

我当前的代码显示以下输出:

AsOfDate Monthly_Return
2021-05-25 -0.275308
2021-05-25 1.150762
2021-05-25 0.043679
2021-05-26 0.296108
2021-05-26 1.0106016
2021-05-26 0.0520379

我真正想要的是:

AsOfDate Monthly_Return
2021-05-25 0.9191
2021-05-26 1.3587

【问题讨论】:

  • 提示:GROUP BY AsOfDateGROUP BY AsOfDate, ColumnA
  • sum(ColumnB) 在您心中代表什么?请提供示例数据和所需的输出。
  • sum(ColumnB) 是按日期在 columnB 中所有值的总和
  • 您使用的是什么 DBMS? SQL 请求应始终使用相关 DBMS 进行标记。 As 'Monthly_Return' 根据实例的 SQL 标准是无效的,因为单引号是为字符串文字保留的,而不是为名称保留的。 AsOfDate BETWEEN '2021-05-25' AND '2021-05-26' 在某些 DBMS 中可能会失败,因为您在这里使用的是字符串文字而不是日期文字。
  • 那么Monthly_ReturnSUM(ColumnB) [过滤后的] 查询结果还是整个表的一部分?

标签: sql sql-server aggregate-functions


【解决方案1】:

如果查询确实为您提供了您所追求的子结果,那么您所要做的就是将查询放入子查询中并再次聚合:

SELECT
  asofdate,
  SUM(monthly_return)
FROM ( <your query here> ) subquery
GROUP BY asofdate
ORDER BY asofdate;

由于您很少按您选择的所有列进行分组,因此我向您展示了一些示例数据和结果,以便您仔细检查:

有了这些数据

AsOfDate ColumnA ColumnB ColumnC ColumnD
2021-05-25 12 2 3 123
2021-05-25 12 2 3 123
2021-05-25 12 2 3 123
2021-05-25 12 1 3 123
2021-05-25 12 1 3 123
2021-05-25 12 1 3 123

您的查询将得到

AsOfDate Monthly_Return
2021-05-25 6
2021-05-25 12

最终的聚合使得这个

AsOfDate SUM(Monthly_Return)
2021-05-25 18

演示:https://dbfiddle.uk/?rdbms=postgres_13&fiddle=3e2907d96baa1c73e29f223c0cf7edc2

更新

根据您的最后一次编辑,您只需要:

SELECT asofdate, SUM(columna * columnc) * 1.0 / SUM(columnb)
FROM xyz.abc
WHERE asofdate BETWEEN '2021-05-25' AND '2021-05-26'
AND columnd LIKE '123%'
GROUP BY asofdate
ORDER BY asofdate;

演示:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=a2b40e9cb83a22c8cc5831b16e61ffca

在 SQL Server 中可能需要与 1.0 相乘,否则可能会在此处不适当地应用整数除法(取决于您的数据类型)。

如果您更愿意使用中间结果,这里是您更正的查询:

SELECT
  asofdate,
  ROUND(cola * 1.0 / SUM(colb) OVER (PARTITION BY asofdate) * colc, 4) AS monthly_return
from xyz.abc
WHERE asofdate BETWEEN '2021-05-25' AND '2021-05-26'
AND cold LIKE '123%';

如前所述,您可以在子查询中使用它来获得最终结果。

演示:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=82b3977d5b0591fe0a2b5bc65b3dab34

【讨论】:

  • Monthly_return 是别名
  • @OnTheHunt:是的。那又怎样?
  • 我正在使用 Microsoft SQL Server 管理。这可能是你的建议对我不起作用的原因吗?我想要 ColumnAi / ColumnB 的总和 * ColumnCi 然后最后聚合所有内容
  • Thorsten Kettner,根据您的表格数据,我期望的结果是 24 而不是 18。我们想要 12/9*3=4。当我们将每一行的结果相加时,我们应该得到 24。
  • 12 / 9 * 3?让我们看看,9 是所有 B 值的总和,对吧? 12 是什么?所有 A 值的平均值还是最大值或最小值?与 3 相同,这是 C 值的平均值、最小值或最大值还是什么?定义这个 t 得到公式。顺便说一句,您可能在这里与不合适的数据模型作斗争。也许您想解释表和列的真正含义,因此我们可以提供帮助。 ColumnA 等是无助于理解数据的名称。
【解决方案2】:

用您的新要求和新列名完全重写。 (因为你已经选择了一个答案,所以值得。)

with a as (
  select AsOfDate
  , ColA
  , sum(ColB) over (partition by AsOfDate) as ColB
  , ColC
  from abc
  where AsOfDate BETWEEN '2021-05-25' AND '2021-05-26'
    and ColD like '123%'
)

select AsOfDate
, cast(round(sum(ColA * ColC / ColB), 4) as decimal(6,4)) as 'Monthly_Return'
from a
group by AsOfDate
;

也许下次,在您的问题中包含dbfiddle,以便您的结构和数据可用。此外,在您第一次提出问题时,请附上您想要的结果。

【讨论】:

  • 仅按 AsOfDate 分组不起作用。这是它给出的错误:Msg 8120, Level 16, State 1, Line 63 列 'xyz.abc.ColumnA' 在选择列表中无效,因为它既不包含在聚合函数或 GROUP BY 子句中。消息 8120,级别 16,状态 1,第 63 行列 'xyz.abc.ColumC' 在选择列表中无效,因为它既不包含在聚合函数或 GROUP BY 子句中。
  • 我修改了答案以适应这一点,但这确实是一个猜测,因为您的问题不清楚。 GROUP BY AsOfDate 表示“按日期分组”。你到底是什么意思?
  • 我已经更新了我的问题,显示了我目前得到的输出
  • 您已经发布了输出。更有帮助的是样本输入和期望输出。
  • 当我删除日期范围(BETWEEN...AND...)并且只关注某一天(例如 AsOfDate = 2021-05-25)时,您的建议有效。看起来日期范围导致它总结了日期之间的所有内容,但我希望计算按日期分组
猜你喜欢
  • 2011-09-27
  • 1970-01-01
  • 2013-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多