I am trying to add a Sum to a data item with a case statement. I am trying to create the results in cognos from the SQL query below.
Select
,SUM(CASE WHEN reas_desc = 'misapplied funds' THEN 1 ELSE 0 END) AS Misapplied
,SUM(CASE WHEN reas_desc = 'lump sum payment' THEN 1 ELSE 0 END) AS Lumps
,SUM(CASE WHEN proc_desc = 'title/registration' THEN 1 ELSE 0 END) AS "Title/Reg"
I want the end product to have 3 columns titled "Misapplied", "lumps", and "title/Reg"with the total of those items. The SQL code works perfectly but I need to build in cognos for others to view and use.
You define your first data item like this:
CASE WHEN reas_desc = 'misapplied funds' THEN 1 ELSE 0 END
From that you should be able to figure out the rest.
Apparently more detail is needed:
Data item 1:
Expression: CASE WHEN reas_desc = 'misapplied funds' THEN 1 ELSE 0 END
Name: Misapplied
Detail Aggregation: Total
Data item 2:
Expression: CASE WHEN reas_desc = 'lump sum payment' THEN 1 ELSE 0 END
Name: Lumps
Detail Aggregation: Total
Data item 3:
Expression: CASE WHEN proc_desc = 'title/registration' THEN 1 ELSE 0 END
Name: Title/Reg
Detail Aggregation: Total
Related
I have a table that looks like below. In my query I'm sum:ing the order item value for each order item type, but I'm not sure how to summarize the providerfee per order id when the providerfee appears on multiple rows. Sum(providerfee) would give me 60 instead of 30.
Raw table (sample):
order id
order item type
order item value
providerfee
1
Product
300
30
1
Shipping
40
30
1
Invoicefee
30
30
Aggregated table if I would query above example table with the query I'm using now:
noOfOrders
productAmount
ShippingAmount
InvoiceAmount
providerfee
1
300
40
30
60
What value I wish to get in the providerfee column in my aggregated table instead:
noOfOrders
productAmount
ShippingAmount
InvoiceAmount
providerfee
1
300
40
30
30
Does anyone now best practice of fetching the right sum per order id from the providerfee-column? I think it won't make any sense to publish the actual query I'm writing but basically what I'm doing to fetch the amounts for order item types is:
with amounts as (
select
case when orderItemType= 'Product' then orderItemValue else 0 end as productAmount
,case when orderItemType = 'Shipping' then orderItemvalue else 0 end as shippingAmount
case when orderItemType = 'Fee' then orderItemvalue else 0 end as InvoicefeeAmount
,providerfee
from exampleTable
)
select
sum(amounts.productAmount) as productAmount
,sum(amounts.shippingAmount) as shippingAmount
,sum(amounts.invoicefeeAmount) as invoicefeeAmount
,sum(amounts.providerfee) as providerfeeAmount <---- This one gives me too high values since I'm summing every rows and providerfee appears on every row
from amounts
Here's a picture of how my actual table look like. Providerfee is supposed to be 638 just like invoiceAmount
One thing I also tried was a logic with row number function. But this gave me a result where three providerfees where missing. Instead of 638 I got 551. Can't see why since I counted in the raw table and got it to 638 myself. Not sure if I'm missing something logical with row number function that can have an impact on the SUM. Should I try another function to be able to pull out only one providerfee-row per order id?
with amounts as (
select
row_number() over (partition by orderId order by orderItemTimestamp DESC) as rn
,case when orderItemType= 'Product' then orderItemValue else 0 end as productAmount
,case when orderItemType = 'Shipping' then orderItemvalue else 0 end as shippingAmount
,case when orderItemType = 'Fee' then orderItemvalue else 0 end as InvoicefeeAmount
,providerfee
from exampleTable
)
select
sum(amounts.productAmount) as productAmount
,sum(amounts.shippingAmount) as shippingAmount
,sum(amounts.invoicefeeAmount) as invoicefeeAmount
,sum(amounts.providerfee) as providerfeeAmount <---- This one gives me too high values since I'm summing every rows and providerfee appears on every row
,sum(case when (amounts.providerfee is not null and amounts.rn = 1) then amounts.providerfee else 0 end) as providerfee2
from amounts
Grand total can be done using conditional aggregation. (Note that I here expect every Orderto have exactly one Invoicefee.)
select COUNT(distinct OrderId) as noOfOrders,
SUM(case when orderItemType = 'Product' then orderItemValue else 0 end) as productAmount,
SUM(case when orderItemType = 'Shipping' then orderItemvalue else 0 end) as shippingAmount,
SUM(case when orderItemType = 'Fee' then orderItemvalue else 0 end) as InvoicefeeAmount,
SUM(case when orderItemType = 'Fee' then providerfee else 0 end) as providerfee
from amounts
You can also add a GROUP BY, to get aggregation per order:
select OrderId,
SUM(case when orderItemType = 'Product' then orderItemValue else 0 end) as productAmount,
SUM(case when orderItemType = 'Shipping' then orderItemvalue else 0 end) as shippingAmount,
SUM(case when orderItemType = 'Fee' then orderItemvalue else 0 end) as InvoicefeeAmount,
SUM(case when orderItemType = 'Fee' then providerfee else 0 end) as providerfee
from amounts
group by OrderId
I am getting a divide by zero error in my script.
Can anyone please help.
I am trying to divide two records and one of them has zero in it. I dont want to lose the row, please advise.
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Paid in 24hrs",
COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
You can introduce a second case to check the result of the sum:
case
when sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) > 0
then COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end)
else 0 /* a default value that makes sense to you */
end as "Achieved"
Looking at your code I could assume you are using MSSQL and therefore you could use nullif which returns null if two arguments are equal. So for example your code could look like :
COUNT([MONTH_OF_SUSPENSION])/nullif(sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end),0) as "Achieved"
What it does is if the value of the sum operator is equal 0 then the divisor is turn from zero into null and that will result in the entire equation to become null.
use another case statement to check the result of your sum
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Paid in 24hrs",
case
when sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) = 0 then 'whatever you want in this case'
else COUNT([MONTH_OF_SUSPENSION])/sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
although this is pretty nasty looking, so you could tidy it up a bit with a sub-select:
select
year,
month,
request,
PaidIn24hrs,
case
when PaidIn24hrs = 0 then 'whatever you want in this case'
else request/PaidIn24hrs
end as "Achieved"
from
(
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "PaidIn24hrs"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
)
I am trying to choose between two rows of data in order to get a total count of type.
Table - Evaluations
EvaluationID (link to minEval_ID and max_EvalID)
EstablishedDelays
Table - Outcome
min_EvalID
max_EvalID
EligTypeRecalc
This is what my current query is:
SELECT "NewEligType"=
COUNT (*),
SUM (CASE WHEN a.EligTypeRecalc IN (1,4,5,7) Then 1 Else 0 END) 'Established Condition',
SUM (CASE WHEN a.EligTypeRecalc=6 Then 1 Else 0 END) 'Established Delay & At-Risk',
SUM (CASE WHEN a.EligTypeRecalc=2 and b.EstablishedDelays=1 Then 1 Else 0 END) 'Established Delay only: One Delay',
SUM (CASE WHEN a.EligTypeRecalc=2 and b.EstablishedDelays=2 Then 1 Else 0 END) 'Established Delay only: Two Delays',
SUM (CASE WHEN a.EligTypeRecalc=2 and b.EstablishedDelays>=3 Then 1 Else 0 END) 'Established Delay only: Three+ Delays',
SUM (CASE WHEN a.EligTypeRecalc=8 Then 1 Else 0 END) 'Clinical Judgement'
from Outcome a
join Evaluations b
on a.max_EvalID=b.evaluationid and a.min_evalID=b.evaluationID
where a.EligTypeRecalc<>3
The problem I'm encountering is picking the correct Eval_ID to choose the correct number of delays and not count the other. The EstablishedDelays associated with max_EvalID is correct unless the EligTypeRecalc is 0, then it should count the delays associated with min_EvalID.
So far I've come up with this basic logic but I'm having a mind block on how to get it to the next step:
CASE WHEN EligTypeRecalc=max_EvalID
THEN EstablishedDelays=max_EvalID
ELSE EstablishedDelays=min_EvalID
Bonus points: I only have Read access to the database.
**What's the proper query syntax to use to select the row associated and exclude the other?
Thanks for your advice!
You might try wrapping your summary of the Evaluations table into a CTE and then join that to the Outcome table.
Here is the code I used, its a little long:
WITH min_eval AS
(
SELECT
a.DataMatch,
a.max_EvalID,
a.EligTypeRecalc,
b.evaluationid,
b.EstablishedDelays
FROM Outcomes a
JOIN Evaluations b
ON a.min_EvalID=b.evaluationid
WHERE a.EligTypeRecalc<>3
),
max_eval AS
(
SELECT
a.DataMatch,
a.max_EvalID,
a.EligTypeRecalc,
b.evaluationid,
b.EstablishedDelays
FROM Outcomes a
JOIN Evaluations b
ON a.max_EvalID=b.evaluationid
WHERE a.EligTypeRecalc<>3
)
SELECT "NewEligType"=
COUNT (*),
SUM (CASE WHEN a.EligTypeRecalc IN (1,4,5,7) THEN 1 ELSE 0 END) 'Established Condition',
SUM (CASE WHEN a.EligTypeRecalc=6 THEN 1 ELSE 0 END) 'Established Delay & At-Risk',
SUM (CASE WHEN (a.EligTypeRecalc=2 AND a.EstablishedDelays=1) OR (a.EligTypeRecalc=2 AND a.EstablishedDelays=0 AND b.EligTypeRecalc=2 AND b.EstablishedDelays=1) THEN 1 ELSE 0 END) 'Established Delay only: One Delay',
SUM (CASE WHEN (a.EligTypeRecalc=2 AND a.EstablishedDelays=2) OR (a.EligTypeRecalc=2 AND a.EstablishedDelays=0 AND b.EligTypeRecalc=2 AND b.EstablishedDelays=2) THEN 1 ELSE 0 END) 'Established Delay only: Two Delays',
SUM (CASE WHEN (a.EligTypeRecalc=2 AND a.EstablishedDelays>=3) OR (a.EligTypeRecalc=2 AND a.EstablishedDelays=0 AND b.EligTypeRecalc=2 AND b.EstablishedDelays>=3) THEN 1 ELSE 0 END) 'Established Delay only: Three+ Delays',
SUM (CASE WHEN a.EligTypeRecalc=8 THEN 1 ELSE 0 END) 'Clinical Judgement'
FROM max_eval a
JOIN min_eval b
ON a.DataMatch=b.DataMatch
I'm trying to run a case on an aggregate sum but can't seem to get this working...essentially I want to return 1 if the sum of the column is > 0...
SELECT Shop.Brands, Shop.Brand, Shop.T3, Shop.ShopName, Shop.Period
CASE WHEN sum(PLData.Actuals) > 0 THEN 1 ELSE 0 END as Actuals,
CASE when sum(PLData.Budgets) > 0 THEN 1 ELSE 0 END as Budget,
CASE when sum(pldata.ForecastLedger) > 0 THEN 1 ELSE 0 END as Forecast
FROM SunFinance.dbo.Shop Shop LEFT OUTER JOIN SunFinance.dbo.PLData PLData ON Shop.T3 = PLData.Shop
WHERE Shop.BusinessType In ('CORPORATE','RETAIL','WHOLESALE')
AND PLData.Account Like '488%')
GROUP by shop.brand, shop.brands, shop.t3, shop.shopname, Shop.Period
Where am I going wrong?
If your DBMS doesn't let you use aggregates in case expressions, you can try to do the aggregation first in an inline view, then do your CASE expressions.
WITH RESULTS AS (
SELECT Shop.Brands
, Shop.Brand
, Shop.T3
, Shop.ShopName
, Shop.Period
, sum(PLData.Actuals) as Actuals
, sum(PLData.Budgets) as Budget,
, sum(pldata.ForecastLedger) as Forecast
FROM SunFinance.dbo.Shop Shop
LEFT OUTER JOIN SunFinance.dbo.PLData PLData
ON Shop.T3 = PLData.Shop
WHERE Shop.BusinessType In ('CORPORATE','RETAIL','WHOLESALE')
AND PLData.Account Like '488%'
GROUP by shop.brand, shop.brands, shop.t3, shop.shopname, Shop.Period
)
SELECT brands, brand, t3, shopname, period,
case when actuals > 0 then 1 else 0 end as actuals,
case when budget > 0 then 1 else 0 end as budget,
case when forecast > 0 then 1 else 0 end as forecast
FROM results
This query returns one row with columns Ready, Processing, Complete, Failed and Error with totals for each. Is there a way to rewrite this query so that columns that have a total of zero are not returned?
I'm using this to populate the mschart control and I don't wan't labels on the chart if there are 0 instances of that category.
SELECT
SUM(CASE WHEN Status = 'R' THEN 1 ELSE 0 END) AS Ready,
SUM(CASE WHEN Status = 'P' THEN 1 ELSE 0 END) AS Processing,
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) AS Complete,
SUM(CASE WHEN Status = 'F' THEN 1 ELSE 0 END) AS Failed,
SUM(CASE WHEN Status = 'E' THEN 1 ELSE 0 END) AS Error
FROM MailDefinition
No, because the shape of the query (the fields it contains) has to be known. Only the data can change, and that is what you should be looking for. You can dynamically remove or hide labels based on 0 or null data in a column.
What I would do is take what you have, throw it into an unpivot, then remove all of the 0 records.
select
Type,
Sum
from
(
SELECT
SUM(CASE WHEN Status = 'R' THEN 1 ELSE 0 END) AS Ready,
SUM(CASE WHEN Status = 'P' THEN 1 ELSE 0 END) AS Processing,
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) AS Complete,
SUM(CASE WHEN Status = 'F' THEN 1 ELSE 0 END) AS Failed,
SUM(CASE WHEN Status = 'E' THEN 1 ELSE 0 END) AS Error
FROM MailDefinition
) a
unpivot
(
Sum for Type in ([Ready],[Processing],[Complete],[Failed],[Error])
) u
where Sum>0
That does, of course, entail changing your chart some.