I have a scenario where I have to use CASE and SUM in an CDS VIEW SQL statement and I cannot add net_val to the group by statement. Is there a way to use CASE and SUM together
case when sum( net_val ) < 0 then 'DEBIT'
when sum( net_val ) > 0 then 'CREDIT'
end as DEBIT_CREDIT_STATUS
Related
I have a multiple ctes. In my select statement I must filter values base on the conditions. This is my query.
SELECT roadName
,sum(roadLength) AS sumRoadLength
,avg(elevationDifference) AS eglAvgDepth
,avg(elevationDifference) AS pglAvgDepth
,
FROM cte3
GROUP BY roadName
ORDER BY roadName
Under "elevationDifference" there are lots of values ranging from -10 to +20 which are spread through "roadName". What i want to accomplished is that "eglAvgDepth" will return if all "elevationDifference" values are <0 and take the average. Same case with pglAvgDepth where values are >0.
I tried to add where statement but works only in eglAvgDepth
WHERE elevationDifference < 0
GROUP BY roadName
ORDER BY roadName
Just add a conditional expression:
avg(case when elevationDifference < 0 then elevationDifference end) as eglAvgDepth,
avg(case when elevationDifference > 0 then elevationDifference end) as pglAvgDepth,
EDIT:
You have phrased this that you want the value based on whether all the values are positive or negative. If so:
(case when max(elevationDifference) < 0 then avg(elevationDifference) end) as eglAvgDepth,
(case when max(elevationDifference) > 0 then avg(elevationDifference) end) as pglAvgDepth,
I'm not a frequent SQL user so be patient:) What I'm trying to do is create multiple summary columns using SQL proc; I know the below is incorrect as I can't use where statement like this but how do I rearrange this?
proc sql ;
create table totals as
select
Account_number,
sum(charge) as total_payments,
sum(charge) as total_cash (where transactioncode in ('CASH')),
sum(charge) as total_intt (where transactioncode in ('INTT')),
calculated total_payments/12 as avg_monthly_payments,
calculated total_cash/12 as avg_cash_payments,
calculated total_intt/12 as avg_INTT_payments
from tabe_1
group by Account_number
; quit ;
You can use CASE...WHEN statement, something like this
create table totals as
select
Account_number,
sum(charge) as total_payments,
sum(CASE WHEN transactioncode ='CASH' THEN charge ELSE 0 END) as total_cash,
sum(CASE WHEN transactioncode ='INTT' THEN charge ELSE 0 END) as total_intt,
sum(charge)/12 as avg_monthly_payments,
sum(CASE WHEN transactioncode ='CASH' THEN charge ELSE 0 END)/12 avg_cash_payments,
sum(CASE WHEN transactioncode ='INIT' THEN charge ELSE 0 END)/12 as avg_INTT_payments
from tabe_1
group by Account_number
Reference from How to sum time using mysql
I want to SUM Field LogsFormatted.Late Every month with query :
SELECT
SUM(CASE
WHEN MONTH (LogsFormatted.DateIn) = 1
THEN SEC_TO_TIME( SUM( TIME_TO_SEC(LogsFormatted.Late)))
ELSE 0 END
) AS '1'
FROM
HrAttLogsFormatted AS LogsFormatted
But the result is
1111 - Invalid use of group function
Where is the problem with the query? resulting in an error output.. Thank you in advance
[EDIT-SOLVED] It's Solved with simply apply
Change format SUM at the beginning of the query
SEC_TO_TIME(SUM(
CASE WHEN MONTH(LogsFormatted.DateIn) = 1 THEN
TIME_TO_SEC(LogsFormatted.Late) END)
) AS '1'
You don't need to call the sum() so many times. You can also move the case condition to the WHERE clause:
SELECT SUM(TIME_TO_SEC(lf.Late))
FROM HrAttLogsFormatted lf
WHERE MONTH(lf.DateIn) = 1 ;
If you want conditional aggregation, then do:
SELECT SUM(CASE WHEN MONTH(lf.DateIn) = 1 THEN TIME_TO_SEC(lf.Late) END)
FROM HrAttLogsFormatted lf;
How to combine these two queries into single query
1. select sum(amount) as received from voucher where amount>0
2. select sum(amount) as repaid from voucher where amount<0
You may use conditional aggregation
select sum( case when amount > 0 then amount else 0 end ) as received,
sum( case when amount < 0 then amount else 0 end ) as repaid
FROM t
You may use FILTER in Postgres 9.4 +
select sum( amount ) filter (where amount > 0 ) as received,
sum( amount ) filter (where amount < 0 ) as repaid
FROM t
Try this.,
select case when amount>0 then sum(amount) end as 'received',
case when amount<0 then sum(amount) end as 'repaid' from voucher
How can i shorten the following select statement?
create or replace view V_AMV_PLG_QUOTES_50_MS as
select
sum(NVL(ASK_SIZE,0)) as ASK_VOLUME,
CASE WHEN
sum(CASE WHEN NVL(ASK_SIZE,0)=0 THEN CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END ELSE ASK_SIZE END)=0 THEN 1
ELSE sum(CASE WHEN NVL(ASK_SIZE,0)=0 THEN CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END ELSE ASK_SIZE END) END as ASK_PRICE,
EXCHANGE_SK as EXCHANGE_SK,
PRODUCT_SK as PRODUCT_SK,
BUSINESS_DATE as BUSINESS_DATE
from
S_AMV_PLG_QUOTE_AGG quotes
where NVL(BASE_CURR_ASK_PRICE ,0) > 0
group by
EXCHANGE_SK,
PRODUCT_SK,
BUSINESS_DATE
Notice the very long calculation appears twice.. Can i insert it into a variable somehow? And just use the CASE operator on the Variable? (Notice we have a sum function there..)
You can't use create and use a variable within a view. If you just want to avoid repeating the nested case statement, you could move it (and the NVL) into an in-line view:
select
sum(MY_ASK_SIZE) as ASK_VOLUME,
CASE WHEN sum(MY_ASK_PRICE)=0 THEN 1
ELSE sum(MY_ASK_PRICE)
END as ASK_PRICE,
EXCHANGE_SK as EXCHANGE_SK,
PRODUCT_SK as PRODUCT_SK,
BUSINESS_DATE as BUSINESS_DATE
from (
select
EXCHANGE_SK, PRODUCT_SK, BUSINESS_DATE,
NVL(ASK_SIZE,0) as MY_ASK_SIZE,
CASE WHEN NVL(ASK_SIZE,0)=0 THEN
CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END
ELSE ASK_SIZE
END AS MY_ASK_PRICE
from S_AMV_PLG_QUOTE_AGG quotes
where NVL(BASE_CURR_ASK_PRICE ,0) > 0
)
group by
EXCHANGE_SK,
PRODUCT_SK,
BUSINESS_DATE;
The NVL and case are performed once, and aliased as MY_ASK_SIZE and MY_ASK_PRICE respectively; and those aliases are then used in the outer query, including within the sum.
If you want to avoid repeating the SUM too, move that into the in-line view as well, along with the group-by clause:
select
ASK_VOLUME as ASK_VOLUME,
CASE WHEN ASK_PRICE=0 THEN 1
ELSE ASK_PRICE
END as ASK_PRICE,
EXCHANGE_SK as EXCHANGE_SK,
PRODUCT_SK as PRODUCT_SK,
BUSINESS_DATE as BUSINESS_DATE
from (
select
EXCHANGE_SK, PRODUCT_SK, BUSINESS_DATE,
SUM(NVL(ASK_SIZE,0)) as ASK_VOLUME,
SUM(CASE WHEN NVL(ASK_SIZE,0)=0 THEN
CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END
ELSE ASK_SIZE
END) AS ASK_PRICE
from S_AMV_PLG_QUOTE_AGG quotes
where NVL(BASE_CURR_ASK_PRICE ,0) > 0
group by
EXCHANGE_SK,
PRODUCT_SK,
BUSINESS_DATE
);
Most of your column aliases are redundant but I've stuck with your pattern.
This is largely cosmetic though; Oracle's optimiser is likely to be clever enough to only perform the actual calculation once anyway, so I wouldn't expect to see much (or any) performance difference.
I used creation of a simple ifZeroReturnOne function:
CREATE OR REPLACE FUNCTION ifZeroReturnOne (expr IN NUMBER)
RETURN NUMBER
IS retval NUMBER;
BEGIN
SELECT CASE WHEN expr=0 THEN 1
ELSE expr END
INTO retval
FROM DUAL;
RETURN (retval);
END;
Than I used in the query:
select sum(NVL(ASK_SIZE,0)) as ASK_VOLUME,
ifZeroReturnOne (sum(CASE WHEN NVL(ASK_SIZE,0)=0 THEN CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END ELSE ASK_SIZE END) as ASK_PRICE,
EXCHANGE_SK as EXCHANGE_SK,
etc...............
Let me know if you have better suggestions