PostgreSQL View Error Handling - postgresql

The code given below is a part of a view that I have created. But sometimes it may throw an error saying:
division by zero
The reason for this error is that sum(bills.past_arrear) part may be 0 for some months.
SELECT (SELECT revenue_driver.driver_id
FROM ccdb.revenue_driver
WHERE revenue_driver.driver_desc::text = 'Arrear Collection Efficiency'::text) AS driver_id
,bills.org_unit_id::integer AS section_id
,date_part('Month'::text, bills.due_date) AS mnth
,date_part('Year'::text, bills.due_date) AS yr
,ROUND(SUM(COALESCE(bills.arrear_collected,0::numeric))/sum(bills.past_arrear)*100::numeric, 2) AS per_efficiency
,now() AS creation_dt
FROM ccdb.bills
WHERE bills.due_date::date >= date_trunc('Month'::text,'now'::text::date::timestamp with time zone)::date
AND bills.due_date::date <= 'now'::text::date
AND (bills.bill_type_group_code::text = ANY (ARRAY['EB'::character varying::text, 'Energy'::character varying::text]))
GROUP BY bills.org_unit_id, date_part('Year'::text, bills.due_date), date_part('Month'::text, bills.due_date);
What I want is if ROUND(SUM(COALESCE(bills.arrear_collected,0::numeric))/sum(bills.past_arrear)*100::numeric, 2) throws division by zero error I want to replace the value with 0.
I have not idea how do handle this error. Kindly someone help me on this.

You need to use a CASE WHEN in your select statement like below :-
CASE
WHEN sum(bills.past_arrear) = 0
THEN 0
ELSE ROUND(SUM(COALESCE(bills.arrear_collected, 0::NUMERIC)) / sum(bills.past_arrear) * 10 ‌​0::NUMERIC, 2)
END AS per_efficiency

Related

mismatched input 'as'. Expecting: ',', <expression>

My query in PRESTO returns this error
Query failed (#20220506_153121_03035_vycq3): line 6:41: mismatched
input 'as'. Expecting: ',',
I don't know why, anybody could find the issue?
select
droh.created_by as deliverymen_email,
count(distinct o.order_number) as deliveries,
sum(case when o.last_status = 10 then 1 else 0 end) quantity_canceled,
cast(sum(quantity_canceled as decimal))/cast(count(deliveries as decimal)) as
delivery_cancellation_fee
from sensitive_raw_courier_api.deliveryman_route_order_history droh
left join raw_courier_api."order" o
on droh.order_number = o.order_number and droh.state = 'DM_PICKED_UP'
where 1=1
and o.created_date >= {{date_begin}}
and droh.created_at >= {{date_end}}
and o.customer_email = {{costumer_email}}
group by 1
order by 2 desc
There is an error with the position of 2 brackets.
We count(~) first and then cast( count(~) ) the result.
cast(sum(quantity_canceled as decimal))/cast(count(deliveries as decimal)) as
should be
cast(sum(quantity_canceled) as decimal)/cast(count(deliveries) as decimal) as
Without the context and further information, it's not sure if this is your only issue in this query, but you can't "mix" a cast with a sum or a count like you do. You need to do the cast first and then sum or count the values (or vice versa). So as example this syntax in your query is incorrect:
CAST(SUM(quantity_canceled AS DECIMAL))
It should be this one instead:
SUM(CAST(quantity_canceled AS DECIMAL))
Or this one:
CAST(SUM(quantity_canceled) AS DECIMAL)
You must fix all occurences of this mistake and then check if the query is correct or contains further problems.
A last note: Doing a division could always end in a division by zero exception if you don't prevent this. So you should take care of this.

NULLIF how to set it properly in this query

I am using the following query to get some tablespaces usage at a glance:
db2 "select substr(tbsp_name,1,30) as Tablespace_Name, tbsp_type as Type, substr(tbsp_state,1,20) as Status, (tbsp_total_size_kb / 1024 ) as Size_Meg, smallint((float(tbsp_free_size_kb)/ float(tbsp_total_size_kb))*100) as Percent_Free_Space, int((tbsp_free_size_kb) / 1024 )as Meg_Free_Space from sysibmadm.tbsp_utilization where smallint((float(tbsp_free_size_kb)/ float(tbsp_total_size_kb))*100) < 20 order by Percent_Free_Space"
however, I'm stuck with the following error:
SQL0801N Division by zero was attempted. SQLSTATE=22012
I understand you can fix this error with a NULLIF however I can't find the correct way to set in in the query, thanks for the help.
( using "DB2 v9.7.0.11", "s150922", "IP23937", and Fix Pack
"11")
Maybe you should use case:
CASE WHEN tbsp_total_size_kb=0 THEN NULL ELSE (tbsp_total_size_kb / 1024 ) END as Size_Meg
if tbsp_total_size_kb can be null IFNULL like this:
CASE WHEN IFNULL(tbsp_total_size_kb,0)=0 THEN NULL ELSE (tbsp_total_size_kb / 1024 ) END as Size_Meg
Try this:
smallint(float(tbsp_free_size_kb) / float(nullif(tbsp_total_size_kb,
0)) * 100)

PostgreSQL: return message after count = 0

I have maybe easy question, but I'm completely stucked.
I have script
SELECT COALESCE(COUNT(id), 0) as MyFiels from table
It works fine and when I have zero value it shows 0.
But I want that instead of 0, I can see one line = "NO RESULTS" for example.
I tried:
SELECT COALESCE(to_char(COUNT(id), 'NO RESULT')) as MyFiels from table
And PostgreSQL shows error message:
ERROR: "E" is not supported
SQL state: 0A000
Where I'm incorrect? Any ideas?
I see what is the error, you are trying to use coalesce to convert 0 to string, and coalesce convert null to something. You need use a CASE
SELECT CASE WHEN COUNT(*) = 0 THEN 'NO RESULT'
ELSE CAST(COUNT(*) as TEXT)
END as field
FROM Table

SQL query for two possible values?

I am using SSMS 2008 R2 and am trying to figure out the SQL select statement to select all records where two or more of the values are found.
These are the four possible values I am looking for. If two or more of these values (SubstanceAbuse, BehaviorEmotion, SexualAbuse, DomesticViolence) are met, I want to set a new field to 1. How do I do this?
case when qav.[test_setup_details_caption] in ('Substance Abuse / Drug Use','Caregiver monitor youth for drug alcohol use') then 1 else 0 end SubstanceAbuse,
case when qav.[test_setup_details_caption] in ('Physical Aggression','Firesetting','Gang Involvement','Runaway Behavior') then 1 else 0 end BehaviorEmotion,
case when qav.[test_setup_details_caption] = 'Problem Sexual Behavior' then 1 else 0 end SexualAbuse,
case when qav.[test_setup_details_caption] LIKE '%Domestic%' then 1 else 0 end DomesticViolence,
My suggestion would be to take the above statement and make it a virtual table in a new SELECT statement. Then you can do a SUM on the ones (since they are calculated already) in your WHERE statement and display only
where (Sub + Beh + Sex + Dom) > 1
It would look something like this (pseudo-code):
SELECT t.*
FROM (SELECT sub case, Beh case, etc.
FROM yourtable) t
WHERE (t.sub + t.Beh + t.Sex + t.Dom) > 1
It seems like all you need is this WHERE clause:
WHERE SubstanceAbuse + BehaviorEmotion + SexualAbuse + DomesticViolence > 1
update myTable set myField = 1 where 2 <= (select SubstanceAbuse + BehaviorEmotion + SexualAbuse + DomesticViolence from ...)
Of course, this is just a template for your query, but you get the idea. If the answer is still unclear then I kindly ask you to give me more details.
Best regards,
Lajos Arpad.

Assign case statement result to variable

When I try to run the following statement, I get this error:
"A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations."
DECLARE #OFR DECIMAL(18,2)
;
SELECT #OFR =
CASE SUM(ofr.Quantity)
WHEN 0 THEN 0
ELSE SUM(ofr.Gross) / SUM(ofr.Quantity)
END
FROM DistributionCosts ofr
;
SELECT #OFR
I just want to stick the result of that case statement into a variable and I'm getting stuck here.
Any ideas?
Thanks.
Are you sure this is where your error is? I just ran the statement below and it worked:
DECLARE #OFR DECIMAL(18,2)
;
with DistributionCosts as
(
select 1 as quantity, 5 as gross
union
select 5 , 20
)
SELECT #OFR =
CASE SUM(ofr.Quantity)
WHEN 0 THEN 0
ELSE SUM(ofr.Gross) / SUM(ofr.Quantity)
END
FROM DistributionCosts ofr
;
SELECT #OFR
If I select a column in addition to setting a variable I do get your error... If you are selecting another column you will need to either stop selecting that column or assign that column to a local variable as well.