【问题标题】:Table with 3 columns, too difficult for me有 3 列的表格,对我来说太难了
【发布时间】:2013-12-11 01:30:26
【问题描述】:

我是一个非常新的 SQL 用户,我有一个包含 3 列的大型数据库:公司名称、日期和下个月的公司股票回报。如何有效地将月度数据转化为年度数据?我已经尝试在接下来的 12 个月中每个月加入,这样我就可以将 12 列相乘,但这太低效了。所有日期均为该月的最后一天。任何帮助将不胜感激!

表格如下所示:

Company Name              date          return
apple               11/30/2012            1.05
apple               12/31/2012             .97
apple                1/31/2013            1.01
apple                2/28/2013            1.04
ford                11/30/2012            1.05
ford                12/31/2012             .97
ford                 1/31/2013            1.01
BP                   6/30/2012             .95

我希望回报是未来 12 个月的回报相乘。这能有效地完成吗?

【问题讨论】:

  • 您需要提供有关您的表结构和一些示例数据的更多信息才能得到答案
  • 另外,接下来 12 个月相乘是什么意思...
  • Barry 和 MWT0 已经解决了这个问题,但我只有一份 1 个月的股票回报清单。我想要年度回报。因此,我尝试制作可以相乘的 12 列。这不是一个有效的方法。

标签: sql performance join


【解决方案1】:

这样的东西应该可以工作

SELECT 
      CompanyName, 
      YEAR(date), 
      EXP(SUM(LOG(return))) As AnnualReturn
FROM  yourTable
GROUP BY CompanyName, YEAR(date)
ORDER BY CompanyName, YEAR(date)

YEAR(..) 函数之类的细节因具体 DBMS 产品而异,但这是基本方法。

【讨论】:

  • 谢谢巴里!一个简单但有效的模板正是我所需要的。
【解决方案2】:

如果您使用的是 ORACLE,那么您可以使用以下方法:

SQL Fiddle

没有PRODUCT 聚合函数,但你可以写一个custom aggregation function...

Oracle 11g R2 架构设置

CREATE TYPE ProductAggregationType as OBJECT
(
  product NUMBER,
  STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT ProductAggregationType) 
    RETURN NUMBER,
  MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ProductAggregationType, 
    value IN NUMBER) RETURN NUMBER,
  MEMBER FUNCTION ODCIAggregateTerminate(self IN ProductAggregationType, 
    RETURNValue OUT NUMBER, flags IN NUMBER) RETURN NUMBER,
  MEMBER FUNCTION ODCIAggregateMerge(self IN OUT ProductAggregationType, 
    ctx2 IN ProductAggregationType) RETURN NUMBER
);
/

CREATE OR REPLACE type body ProductAggregationType is 
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT ProductAggregationType) 
RETURN NUMBER IS
BEGIN
  sctx := ProductAggregationType(1);
  RETURN ODCIConst.Success;
END;

MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ProductAggregationType, value IN NUMBER) RETURN NUMBER is
BEGIN
  self.product := self.product * value;
  RETURN ODCIConst.Success;
END;

MEMBER FUNCTION ODCIAggregateTerminate(self IN ProductAggregationType, 
    returnValue OUT NUMBER, flags IN NUMBER) RETURN NUMBER is
BEGIN
  returnValue := self.product;
  RETURN ODCIConst.Success;
END;

MEMBER FUNCTION ODCIAggregateMerge(self IN OUT ProductAggregationType, ctx2 IN ProductAggregationType) RETURN NUMBER is
BEGIN
  self.product := self.product * ctx2.product;
  RETURN ODCIConst.Success;
END;
END;
/

CREATE FUNCTION PRODUCT (input NUMBER) RETURN NUMBER 
PARALLEL_ENABLE AGGREGATE USING ProductAggregationType;
/

CREATE TABLE data ( names, dates, "return" ) AS
          SELECT 'A', TO_DATE( '31-01-2021', 'DD-MM-YYYY' ), 1.05 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '28-02-2021', 'DD-MM-YYYY' ), 0.97 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-03-2021', 'DD-MM-YYYY' ), 1.01 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '30-04-2021', 'DD-MM-YYYY' ), 1.04 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-05-2021', 'DD-MM-YYYY' ), 1.05 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '30-06-2021', 'DD-MM-YYYY' ), 0.97 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-07-2021', 'DD-MM-YYYY' ), 1.01 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-08-2021', 'DD-MM-YYYY' ), 1.02 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '30-09-2021', 'DD-MM-YYYY' ), 1.03 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-10-2021', 'DD-MM-YYYY' ), 0.90 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '30-11-2021', 'DD-MM-YYYY' ), 1.00 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-12-2021', 'DD-MM-YYYY' ), 1.12 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-01-2022', 'DD-MM-YYYY' ), 0.90 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '28-02-2022', 'DD-MM-YYYY' ), 1.10 FROM DUAL
UNION ALL SELECT 'A', TO_DATE( '31-03-2022', 'DD-MM-YYYY' ), 1.00 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-01-2021', 'DD-MM-YYYY' ), 1.02 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '28-02-2021', 'DD-MM-YYYY' ), 0.98 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-03-2021', 'DD-MM-YYYY' ), 1.03 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '30-04-2021', 'DD-MM-YYYY' ), 1.01 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-05-2021', 'DD-MM-YYYY' ), 1.02 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '30-06-2021', 'DD-MM-YYYY' ), 0.96 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-07-2021', 'DD-MM-YYYY' ), 1.05 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-08-2021', 'DD-MM-YYYY' ), 1.01 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '30-09-2021', 'DD-MM-YYYY' ), 1.02 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-10-2021', 'DD-MM-YYYY' ), 0.97 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '30-11-2021', 'DD-MM-YYYY' ), 1.02 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-12-2021', 'DD-MM-YYYY' ), 1.08 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-01-2022', 'DD-MM-YYYY' ), 0.95 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '28-02-2022', 'DD-MM-YYYY' ), 1.05 FROM DUAL
UNION ALL SELECT 'B', TO_DATE( '31-03-2022', 'DD-MM-YYYY' ), 1.00 FROM DUAL
/

查询 1

SELECT names,
       EXTRACT( YEAR FROM dates ) AS year,
       PRODUCT( "return" ) AS total_return
FROM   data
GROUP BY names, EXTRACT( YEAR FROM Dates )
ORDER BY year

Results

| NAMES | YEAR |   TOTAL_RETURN |
|-------|------|----------------|
|     A | 2021 | 1.165456536894 |
|     B | 2021 | 1.176962855452 |
|     A | 2022 |           0.99 |
|     B | 2022 |         0.9975 |

查询 2

或者您可以使用power of logarithms 来计算产品:

SELECT names,
       EXTRACT( YEAR FROM dates ) AS year,
       EXP(SUM(LN( "return" ))) AS total_return
FROM   data
GROUP BY names, EXTRACT( YEAR FROM Dates )
ORDER BY year

Results

| NAMES | YEAR |   TOTAL_RETURN |
|-------|------|----------------|
|     A | 2021 | 1.165456536894 |
|     B | 2021 | 1.176962855452 |
|     A | 2022 |           0.99 |
|     B | 2022 |         0.9975 |

【讨论】:

  • 我使用您的查询 1 对空值和产品功能进行了一些调整。非常感谢您抽出宝贵的时间,这非常有帮助!
  • 很高兴为您提供帮助 - 如果它回答了您的问题,那么请接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-03
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多