sql work out growth in query - sql

I'm trying to work out the percentage of growth between 2 years but it is returning growth as 0.
SELECT my.finmonth,
my.trnyear,
my.drawofficenum,
my1.ytdty,
ly1.ytdly,
CASE
WHEN my1.ytdty <> 0 THEN ( my1.ytdty - ly1.ytdly ) / ly1.ytdly * 100
ELSE 0
END AS Growth2012
FROM salestymonth my
LEFT JOIN salestyytd my1
ON my.finmonth = my1.finmonth
AND my.trnyear = my1.trnyear
AND my.drawofficenum = my1.drawofficenum
LEFT JOIN saleslyytd ly1
ON my.finmonth = ly1.finmonth
AND my.trnyear = ly1.trnyear
AND my.drawofficenum = ly1.drawofficenum
WHERE my.finmonth = '1'
ORDER BY ytdty DESC

Try 1.00*(my1.YTDTY - ly1.YTDLY) / ly1.YTDLY. If your column types are integers, you won't get non-integer results from dividing unless you force the numerator to be a decimal or float.

Related

What can I do to update my query to avoid a Division by zero error?

I'm trying to update my query to pull a list of stores if it is marked as "third party" and integrated_images_via_api is set to "true".
When returning these results, I would like to use the divide function to pull averages but i keep running into a division by zero error.
Looks like something went wrong with your query.
net.snowflake.client.jdbc.SnowflakeSQLException: Division by zero
With
menu_data as (
SELECT DISTINCT
dht.date_stamp,
dm.BUSINESS_ID,
ps.provider_type,
dht.MENU_ID,
dht.ACTIVE_STORES_LINKED_TO_MENU,
dht.HAS_HEADER_IMAGE,
dht.HAS_LOGO_IMAGE,
dht.PHOTOS_TOTAL,
dht.NUM_ITEM_IDS,
dht.ITEMS_WITH_DESCRIPTIONS,
dht.PHOTOS_TOTAL*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_photos,
dht.NUM_ITEM_IDS*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_items,
dht.ITEMS_WITH_DESCRIPTIONS*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_desc,
dht.HAS_HEADER_IMAGE*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_headers,
dht.HAS_logo_IMAGE*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_logos,
case when dht.has_header_image AND dht.has_logo_image AND dht.photos_total/dht.NUM_ITEM_IDS >=0.1 --NS, >10% Photos
then 1
else 0 end as NS_Sat
FROM
PRODDB.PUBLIC.DIMENSION_MENU_HEALTH_TRACKING dht
Left Join PRODDB.PUBLIC.DIMENSION_MENU dm ON dm.MENU_ID = dht.MENU_ID
LEFT JOIN DOORDASH_MERCHANT.PUBLIC.MAINDB_STORE_POINT_OF_SALE_INFO ps on ps.store_id=dm.store_id
LEFT JOIN PRODDB.STATIC.POS_PROVIDER_CLASSIFICATION pc on pc.PROVIDER_TYPE=ps.PROVIDER_TYPE
LEFT JOIN PRODDB.STATIC.MENU_DETAILS pm on pm.PROVIDER_ID=pc.PROVIDER_TYPE
WHERE
1 = 1
AND dht.DATE_STAMP = (SELECT max(date_stamp) from PRODDB.PUBLIC.DIMENSION_MENU_HEALTH_TRACKING)
AND dht.ACTIVE_MENU
AND dht.NUM_ITEM_IDS >0
AND --dm.BUSINESS_ID in ('1026','57396','859','1037567','400712','554309')
pc.DIRECT_OR_3PT= 'Third Party'
AND pm.INTEGRATED_IMAGES_VIA_API= 'TRUE'
)
--Main Query
SELECT
md.DATE_STAMP,
business_id,
sum(ACTIVE_STORES_LINKED_TO_MENU) as total_store_menus,
sum(case when md.NS_SAT = 1 then ACTIVE_STORES_LINKED_TO_MENU else NULL end) as NS_store_menus,
total_store_menus - NS_store_menus as ns_opp,
round(NS_Store_menus / total_store_menus, 4) as NS_Perc,
sum(sum_photos) as total_photos,
sum(sum_items) as total_items,
sum(sum_desc) as total_descriptions,
sum(sum_headers) as total_headers,
round(total_photos / total_items,4) as item_perc,
round(total_descriptions / total_items,4) as desc_perc,
total_items - total_photos as item_opp,
round(total_headers / total_store_menus,4) as perc_headers
from menu_data md
where ns_perc >= 0.95
group by 1,2
order by 1,2 DESC

How to sum the value of another sum from same select statement

I am trying sum the value of another sum in the same select statement and then I want to check the sum value in case statement. When I do it, it is working instead it is just gets individual value.
I have to sum Billable_Trades and then I have to give some rate if the billable_trades is above some numbers for that, I need to know the total of the billable_trade.
select t.Business_Unit_Description, -- case when Product_Type_Description = 'Fee Based' then 'Fee Based' else '' end as revenue_type,
billable_trades,
isnull(c.comm_adjustments, 0) as commission_adjustments,
rate,
billable_trades*rate as charges,
0.3 as commission_rate,
isnull(c.comm_adjustments, 0)*0.3 as credit,
(billable_trades*rate)- isnull(c.comm_adjustments, 0)*0.3 as total
from
(
select Business_Unit_Description,
sum(billable_trades) as billable_trades,
CASE WHEN SUM(billable_trades) > 0 and SUM(billable_trades) <= 150000 THEN 0.85667 ELSE 0.47104 END as rate
from cte_combined
group by Business_Unit_Description
) t
left outer join cte_comm_adj c on c.Business_Unit_Description = t.Business_Unit_Description
order by t.Business_Unit_Description
There is obviously more to the query than is shown - as you are using a derived table to reference a CTE and also outer joining to another CTE.
I would move the calculation of rate out of the derived table:
Select t.Business_Unit_Description -- case when Product_Type_Description = 'Fee Based' then 'Fee Based' else '' end as revenue_type,
, t.sum_billable_trades
, commission_adjustments = isnull(c.comm_adjustments, 0)
, r.rate
, charges = t.sum_billable_trades * r.rate
, commission_rate = 0.3
, credit = isnull(c.comm_adjustments, 0) * 0.3
, total = (t.sum_billable_trades * r.rate) - isnull(c.comm_adjustments, 0) * 0.3
From (Select Business_Unit_Description
, sum_billable_trades = sum(billable_trades)
From cte_combined
Group By Business_Unit_Description) t
Cross Apply (Values (iif(t.sum_billable_trades > 0 And t.sum_billable_trades <= 150000, 0.85667, 0.47104))) As r(rate)
Left Outer Join cte_comm_adj c On c.Business_Unit_Description = t.Business_Unit_Description
Order By t.Business_Unit_Description;
I also wouldn't use the same name for the sum just to make it clearer.

Out of range integer: infinity

So I'm trying to work through a problem thats a bit hard to explain and I can't expose any of the data I'm working with but what Im trying to get my head around is the error below when running the query below - I've renamed some of the tables / columns for sensitivity issues but the structure should be the same
"Error from Query Engine - Out of range for integer: Infinity"
WITH accounts AS (
SELECT t.user_id
FROM table_a t
WHERE t.type like '%Something%'
),
CTE AS (
SELECT
st.x_user_id,
ad.name as client_name,
sum(case when st.score_type = 'Agility' then st.score_value else 0 end) as score,
st.obs_date,
ROW_NUMBER() OVER (PARTITION BY st.x_user_id,ad.name ORDER BY st.obs_date) AS rn
FROM client_scores st
LEFT JOIN account_details ad on ad.client_id = st.x_user_id
INNER JOIN accounts on st.x_user_id = accounts.user_id
--WHERE st.x_user_id IN (101011115,101012219)
WHERE st.obs_date >= '2020-05-18'
group by 1,2,4
)
SELECT
c1.x_user_id,
c1.client_name,
c1.score,
c1.obs_date,
CAST(COALESCE (((c1.score - c2.score) * 1.0 / c2.score) * 100, 0) AS INT) AS score_diff
FROM CTE c1
LEFT JOIN CTE c2 on c1.x_user_id = c2.x_user_id and c1.client_name = c2.client_name and c1.rn = c2.rn +2
I know the query works for sure because when I get rid of the first CTE and hard code 2 id's into a where clause i commented out it returns the data I want. But I also need it to run based on the 1st CTE which has ~5k unique id's
Here is a sample output if i try with 2 id's:
Based on the above number of row returned per id I would expect it should return 5000 * 3 rows = 150000.
What could be causing the out of range for integer error?
This line is likely your problem:
CAST(COALESCE (((c1.score - c2.score) * 1.0 / c2.score) * 100, 0) AS INT) AS score_diff
When the value of c2.score is 0, 1.0/c2.score will be infinity and will not fit into an integer type that you’re trying to cast it into.
The reason it’s working for the two users in your example is that they don’t have a 0 value for c2.score.
You might be able to fix this by changing to:
CAST(COALESCE (((c1.score - c2.score) * 1.0 / NULLIF(c2.score, 0)) * 100, 0) AS INT) AS score_diff

How to calculate max, min and average in postgresql

I want to separate jobs with color based on conversion of what I did as follow:
select count(ap.id),
(count(ap.id)/cast(SUM(j.views) as float) * 100) as conversion,
j.company_id
from applications ap
right join jobs j
on ap.job_id = j.id
where j.company_id = 61805
group by j.id
if conversion column is greater than 75% of total average of that result, I want to create new alias column and value will be green. if conversion column is between 35% and 75%, column value will be yellow and less than 35%, column value will be red.
Is can be possible do in postgres as above query I've mentioned? Thanks in advance.
Window functions are your friend:
SELECT count,
conversion,
CASE
WHEN conversion > avg_conv * 0.75
THEN 'green'
WHEN conversion < avg_conv * 0.35
THEN 'red'
ELSE 'yellow'
END AS color,
company_id
FROM (SELECT count,
conversion,
avg(conversion) OVER () AS avg_conv,
company_id
FROM (SELECT count(ap.id),
(count(ap.id)/cast(SUM(j.views) as float) * 100) AS conversion,
j.company_id
FROM applications ap
RIGHT JOIN jobs j
ON ap.job_id = j.id
WHERE j.company_id = 61805
GROUP BY j.company_id
) with_avg
) with_color;
(untested)

Why is my output not exactly 2.39?

I need the output with 2 digit like 2.39 but I got the output 2.3980815347721822541966.
That is the problem I don't understand.
Here is my Query.
SELECT M.Description,A.Target,A.Actual,
CASE
WHEN A.Target > 0 THEN A.Actual / CONVERT(DECIMAL(18,2),A.Target)
ELSE 0
END Achievement
FROM (
SELECT * FROM ProcessData PD
WHERE
ProcessYear = 2015 AND ProcessMonth = 1
AND DepotID = 6 AND ModuleID =1
) A
LEFT OUTER JOIN Measure M
ON M.ID = A.MeasureID
You need to format the whole expression rather than just the divisor:
So rather than
THEN A.Actual / CONVERT(DECIMAL(18,2),A.Target)
Change it to:
THEN CONVERT(DECIMAL(18,2), A.Actual / A.Target)
Note that I would expect 2.398 to round to 2.40 (which is what the code I posted will do) - are you sure you want to round down always? If so, look at the ROUND function as well.
THEN CONVERT(DECIMAL(18,2), ROUND(A.Actual / A.Target, 2, 1)