如果您使用的是 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 |