I'm trying to find the correct sql query based on the case below.
customer_id | unit_id | NAV | DATE |
---|---|---|---|
16 | 1254 | 10 | 2020-05-01 |
17 | 1253 | 20 | 2020-05-02 |
18 | 1253 | 30 | 2020-05-03 |
16 | 1254 | 20 | 2020-05-02 |
16 | 1254 | 30 | 2020-05-03 |
17 | 1253 | 20 | 2020-05-02 |
17 | 1255 | 30 | 2020-05-03 |
16 | 1254 | 20 | 2020-05-04 |
From the table above, the AVERAGE_NAV can be found by moving average since the first date unit purchased. So, if I want to find moving average NAV for spesific data of customer_id and unit_id from table ACCOUNTBALANCE, I use this query below.
SELECT
ACCBAL.CUSTOMER_ID,
ACCBAL.UNITTRUST_ID,
ACCBAL.INVACCT_ID,
ACCBAL.NAV,
AVG(ACCBAL.NAV)
OVER (
ORDER BY ACCBAL.BALANCEDATE
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
),
ACCBAL.CREATED_DATE
FROM WMS_UT_ACCOUNTBAL ACCBAL
WHERE
ACCBAL.CUSTOMER_ID=16 AND
ACCBAL.UNITTRUST_ID=1254
you can see the picture of the query in the link below. query image
The result of the query is shown below.
customer_id | unit_id | NAV | DATE | Average_NAV |
---|---|---|---|---|
16 | 1254 | 10 | 2020-05-01 | 10 |
16 | 1254 | 20 | 2020-05-02 | 15 |
16 | 1254 | 30 | 2020-05-03 | 20 |
16 | 1254 | 20 | 2020-05-04 | 20 |
My question is, What is the query to find the average_NAV with all combined different customer_id and unit_id like this table below here.
customer_id | unit_id | NAV | DATE | average_NAV |
---|---|---|---|---|
16 | 1254 | 10 | 2020-05-01 | 10 |
17 | 1253 | 20 | 2020-05-02 | 20 |
18 | 1253 | 30 | 2020-05-03 | 30 |
16 | 1254 | 20 | 2020-05-02 | 15 |
16 | 1254 | 30 | 2020-05-03 | 20 |
17 | 1253 | 20 | 2020-05-02 | 20 |
17 | 1255 | 30 | 2020-05-03 | 30 |
16 | 1254 | 20 | 2020-05-04 | 20 |
the average_NAV must be based on the query result from the same customer_id and unitrust_id start from the first purchase. you can see that for customer_id=17 and unit_id=1255 has average_NAV=30 same as NAV since it's first purchase with those spesific customer_id and unit_id was 2020-05-03. The main obstacle is how I can use where clause inside the outer SELECT because it's prohibited in oracle sql.
I have used CTE method (WITH) but still not what expected like below.
WITH ACCBAL (CUSTOMER_ID,UNITTRUST_ID,NAV, CREATED_DATE) AS
(SELECT ACCBAL1.CUSTOMER_ID, ACCBAL1.UNITTRUST_ID,
ACCBAL1.NAV, ACCBAL1.CREATED_DATE
FROM WMS_UT_ACCOUNTBAL ACCBAL1),
ACCBAL_AVERAGE_NAV (AVERAGE_NAV) AS
(SELECT AVG(ACCBAL2.NAV) OVER
(ORDER BY ACCBAL2.CREATED_DATE RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM WMS_UT_ACCOUNTBAL ACCBAL2
WHERE ACCBAL2.UNITTRUST_ID=ACCBAL.UNITTRUST_ID
AND ACCBAL2.CUSTOMER_ID=ACCBAL.CUSTOMER_ID)
SELECT * FROM ACCBAL,ACCBAL_AVERAGE_NAV;
The query above is not working because it gives error of invalid identidier in WHERE clause.
Anyone can help me? Truly Appreciated. Thank you
CodePudding user response:
- You can include the
PARTITION BY
clause beforeORDER BY
. - Tested on db<>fiddle
SELECT
ACCBAL.CUSTOMER_ID,
ACCBAL.UNITTRUST_ID,
-- ACCBAL.INVACCT_ID,
ACCBAL.NAV,
ACCBAL.CREATED_DATE,
AVG(ACCBAL.NAV)
OVER (
PARTITION BY ACCBAL.CUSTOMER_ID, ACCBAL.UNITTRUST_ID
ORDER BY ACCBAL.CREATED_DATE
)
FROM WMS_UT_ACCOUNTBAL ACCBAL;