ERROR [HY000] ERROR: Aggregate function calls may not be nested */ - sql

I cannot get the below line to work when adding to my query, any thoughts?
stddev(stat) bias
with c as (
SELECT A.ENGINE_ASOF_CALENDAR_DATE, A.LEVEL_1_CODE CURR, CNTR_TO_ACTIVE_RISK, A.PRICE, a.ACTIVE_WEIGHT_PCT,
lag(a.PRICE, 1) over(partition by a.LEVEL_1_CODE order by a.ENGINE_ASOF_CALENDAR_DATE) price_lag,
lag(CNTR_TO_ACTIVE_RISK, 1) over(partition by a.LEVEL_1_CODE order by a.ENGINE_ASOF_CALENDAR_DATE) risk_lag,
price_lag/a.PRICE - 1 rtn,
a.ACTIVE_WEIGHT_PCT * rtn wgt_rtn
FROM DBS_APPL_RISK_DATAMART.USR_OWNR_RISK_DATAMART.VWC_FOREIGNEXCHANGE_FUND_EXPOSURE A
WHERE A.PORTFOLIO_CODE = 'Sunsuper Active - SUKHH3_Active'
)
SELECT c.*,
sum(wgt_rtn) over(partition by c.ENGINE_ASOF_CALENDAR_DATE)sum_rtn,
sum(risk_lag) over(partition by c.ENGINE_ASOF_CALENDAR_DATE)sum_risk_lag,
sum_risk_lag/sqrt(260) over(partition by c.ENGINE_ASOF_CALENDAR_DATE)sum_lag_risk2,
sum_rtn/nullif(sum_lag_risk2,0) stat,
stddev(stat) bias
FROM c
order by c.ENGINE_ASOF_CALENDAR_DATE desc

You are using column aliases in expressions in the same select where they are defined. You are also mixing aggregation functions in a select that has no group by.
Perhaps this will fix your problem:
WITH . . .
SELECT c.*, sum_rtn / nullif(sum_lag_risk2, 0) as stat,
stddev(sum_rtn / nullif(sum_lag_risk2, 0)) over () as bias
FROM (SELECT c.*,
sum(wgt_rtn) over (partition by c.ENGINE_ASOF_CALENDAR_DATE) as sum_rtn,
sum(risk_lag) over (partition by c.ENGINE_ASOF_CALENDAR_DATE) as sum_risk_lag,
sum_risk_lag/sqrt(260) over (partition by c.ENGINE_ASOF_CALENDAR_DATE) as sum_lag_risk2
FROM c
) c
ORDER BY c.ENGINE_ASOF_CALENDAR_DATE desc
I'm not sure what the standard deviation should be partitioned by. This is over all the data.

Related

postgresql cumsum by condition

I have the table
I need to calculate cumsum group by id for every row with type="end".
Can anyone see the problem?
Output result
This is a little tricky. One method is to assign a grouping by reverse counting the ends. Then use dense_rank():
select t.*,
dense_rank() over (order by grp desc) as result
from (select t.*,
count(*) filter (where type = 'end') over (order by created desc) as grp
from t
) t;
You can also do this without a subquery:
select t.*,
(count(*) filter (where type = 'end') over () -
count(*) filter (where type = 'end') over (order by created desc) -
1
)
from t;

How to use conditions with a RANK statement

The following piece of code does its job : it gives me the top 10 results for each category.
SELECT *
FROM (
SELECT *, RANK() OVER (PARTITION BY "pera_id" ORDER BY "surface" DESC) AS rnk
FROM "testBadaBing"
) AS x
WHERE rnk <= 10
Now I'd like to add conditions so that the number of results may vary based on a criteria. Example : if "note" = 1, then I want to retain 1 result, else make it 3.
I tried something along the lines which you can see below using the CASE WHEN statement but as you might expect it doesn't work. Error returned :
1 - near "CASE": syntax error
SELECT *
CASE WHEN "note" = 1 THEN
SELECT *
FROM (
SELECT *, RANK() OVER (PARTITION BY "pera_id" ORDER BY "surface" DESC) AS rnk
FROM "testBadaBing"
) AS x
WHERE rnk <= 1
ELSE
SELECT *
FROM (
SELECT *, RANK() OVER (PARTITION BY "pera_id" ORDER BY "surface" DESC) AS rnk
FROM "testBadaBing"
) AS x
WHERE rnk <= 3
END
Do you have any ideas how to make this work? My knowledge of SQL is pretty limited. The code has to be SQLite/SpatiaLite compatible as I'm working in the QGIS environment. Thanks.
You can use boolean logic in the WHERE clause of the outer query:
SELECT *
FROM (
SELECT t.*,
RANK() OVER (PARTITION BY "pera_id" ORDER BY "surface" DESC) AS rnk
FROM "testBadaBing" t
) AS x
WHERE ("note" = 1 and rnk = 1) OR rnk <= 3

Is it possible to rank a dataset by the result of another window function in T-SQL?

Is there any way to rank a dataset by the result of another window function?
For example, I have a query like this one below:
select distinct
country,
cast(sum(Sessions) over (partition by country) as float) / cast(sum(sessions) over() as float) as sess_prcnt
from
GoogleAnalytics.dbo.SiteVisitsLog
order by
sess_prcnt desc
What I want to do is to rank the countries by the sess_prcnt column.
Adding a line like rank() over(order by sess_prcnt) or using CTE gives errors.
Thank you in advance!
You say using a CTE gives errors - what sort of errors do they cause? e.g., any issue with doing something like
; WITH A AS
(select distinct
country,
cast(sum(Sessions) over (partition by country) as float) / cast(sum(sessions) over() as float) as sess_prcnt
from
GoogleAnalytics.dbo.SiteVisitsLog
)
SELECT *, rank() OVER (order by sess_prct DESC) AS rnk
FROM A
order by
sess_prcnt desc
or similar using it as part of the FROM clause
SELECT *, rank() OVER (order by sess_prct DESC) AS rnk
FROM
(select distinct
country,
cast(sum(Sessions) over (partition by country) as float) / cast(sum(sessions) over() as float) as sess_prcnt
from
GoogleAnalytics.dbo.SiteVisitsLog
) A
order by
sess_prcnt desc
You probably also want to ensure you use the appropriate ranking function for your task - ROW_NUMBER, RANK, or DENSE_RANK

ROW_NUMBER and Grouping of data

I have a data that looks like this:
What I want is to have a row number that is group by GroupCode,Group Description,SubGroup and subgroup class and I want to retain the ordering by account code that will look like this:
What's the proper way of seting a row number at the same time grouping them?
You are looking for dense_rank():
select dense_rank() over (order by GroupCode, GroupDescription, SubGroup)
. . .
However, this doesn't guarantee the ordering by accountCode. That will require more work. First, determine the minimum account code for each grouping, then use dense_rank() on that:
select t.*, dense_rank() over (order by minac)
from (select t.*,
min(accountCode) over (partition by GroupCode, GroupDescription, SubGroup) as minac
from t
) t
You're looking for the DENSE_RANK window function:
SELECT
rn = DENSE_RANK() OVER(ORDER BY GroupCode, GroupDescription, SubgroupClass),
*
FROM tbl
ORDER BY rn, AccountCode
I Guess you need this
;WITH cte
AS (SELECT groupcode,
groupdescription,
subgroup,
subgroupclass,
Min(accountcode) AS accountcode
FROM your_table
GROUP BY groupcode,
groupdescription,
subgroup,
subgroupclass),
ordr
AS (SELECT Row_number()OVER(ORDER BY accountcode) AS RN,
*
FROM cte)
SELECT C.rn,
A.*
FROM your_table A
INNER JOIN cte C
ON A.groupcode = C.groupcode
AND A.groupdescription = C.groupdescription
AND A.subgroup = C.subgroup
AND A.subgroupclass = C.subgroupclass

Windowed functions can only appear in the SELECT or ORDER BY clauses

Can anyone explain why can't we use windowed functions in group by clause and why it's allowed only in SELECT and ORDER BY
I was trying to group the records based on row_number() and a column in SQL Server as like this:
SELECT Invoice
from table1
group by row_number() over(order by Invoice),Invoice
I am getting an error
Windowed functions can only appear in the SELECT or ORDER BY
I can select this row_number() in SELECT clause but I want to know why can't we use it group by?
Windowed functions are defined in the ANSI spec to logically execute after the processing of GROUP BY, HAVING, WHERE.
To be more specific they are allowed at steps 5.1 and 6 in the Logical Query Processing flow chart here .
I suppose they could have defined it another way and allowed GROUP BY, WHERE, HAVING to use window functions with the window being the logical result set at the start of that phase but suppose they had and we were allowed to construct queries such as
SELECT a,
b,
NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect
FROM YourTable
WHERE NTILE(2) OVER (PARTITION BY a ORDER BY b) > 1
GROUP BY a,
b,
NTILE(2) OVER (PARTITION BY a ORDER BY b)
HAVING NTILE(2) OVER (PARTITION BY a ORDER BY b) = 1
With four different logical windows in play good luck working out what the result of this would be! Also what if in the HAVING you actually wanted to filter by the expression from the GROUP BY level above rather than with the window of rows being the result after the GROUP BY?
The CTE version is more verbose but also more explicit and easier to follow.
WITH T1 AS
(
SELECT a,
b,
NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForWhere
FROM YourTable
), T2 AS
(
SELECT a,
b,
NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForGroupBy
FROM T1
WHERE NtileForWhere > 1
), T3 AS
(
SELECT a,
b,
NtileForGroupBy,
NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForHaving
FROM T2
GROUP BY a,b, NtileForGroupBy
)
SELECT a,
b,
NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect
FROM T3
WHERE NtileForHaving = 1
As these are all defined in the SELECT statement and are aliased it is easily achievable to disambiguate results from different levels e.g. simply by switching WHERE NtileForHaving = 1 to NtileForGroupBy = 1
You can work around that by placing the window function in a subquery:
select invoice
, rn
from (
select Invoice
, row_number() over(order by Invoice) as rn
from Table1
) as SubQueryAlias
group by
invoice
, rn