Getting ORA-01476: divisor is equal to zero error - sql

I need to get the total volume for two quarters as the query is showing in CASE statements. The third CASE statement is meant to divide the total of the volume for each quarter by the total MK_VOL.
Now the issue is that the MK_VOL for each day is one value, so essentially I need to get the MAX of each day and then SUM for the whole quarter to get the MKT_SHARE (which is SUM of VOL divided by SUM of the MK_VOL). To reiterate, for MK_VOL, it's not just a case of getting the total for the whole quarter but the MAX of each day and then the total.
As you can see the MK_VOL is the same for 02-APR.
Now my third case statement is trying to do that and I get an error. This is what I need help with please or a better solution.
I have tried doing a sub query but that didn't work either.
Data Set below
DATE Client VOL MK_VOL
----------- -------- ----- -------
01-APR AB 2 45
02-APR AC 3 46
02-APR AG1 26 46
02-APR AG2 48 46
03-APR AD 4 47
06-SEP AF 5 48
07-SEP AF 8 50
Query Below
SELECT CLIENT
, SUM(CASE WHEN DATE BETWEEN '01-JUL-19' AND '30-SEP-19' THEN VOLUME END) AS Q3_VOLUME
, SUM(CASE WHEN DATE BETWEEN '01-APR-19' AND '30-JUN-19' THEN VOLUME END) AS Q2_VOLUME
, SUM(CASE WHEN DATE BETWEEN '01-JUL-19' AND '30-SEP-19' THEN VOLUME END) AS Q3_VOLUME
/ sum(DISTINCT CASE WHEN DATE BETWEEN '01-JUL-19' AND '30-SEP-19' THEN MKT_VOL END) AS MKT_SHARE
FROM TB1
WHERE TRADE_DATE BETWEEN '01-APR-19' AND '30-SEP-19'
GROUP BY CLIENT
The expected result should be total VOL / SUM (MAX(MK_VOL) for each client.

First, your problem here is not only you could not calculate values as you wanted them to be, you had a "ORA-01476: divisor is equal to zero error" error which means you had a zero value in your divisor. You have to fix it or at least you have to avoid it like i demonstrate below.
SELECT CLIENT
SUM(Q3_VOLUME)/SUM(CASE WHEN MKT_SHARE!=0 THEN MKT_SHARE END) V1,
SUM(Q2_VOLUME)/SUM(CASE WHEN MKT_SHARE!=0 THEN MKT_SHARE END) V2
FROM (
SELECT CLIENT,
DATE
SUM(CASE WHEN DATE BETWEEN '01-JUL-19' AND '30-SEP-19' THEN VOLUME END) AS Q3_VOLUME,
SUM(CASE WHEN DATE BETWEEN '01-APR-19' AND '30-JUN-19' THEN VOLUME END) AS Q2_VOLUME,
MAX(DISTINCT CASE WHEN DATE BETWEEN '01-JUL-19' AND '30-SEP-19' THEN MKT_VOL END) AS MKT_SHARE
FROM TB1
WHERE TRADE_DATE BETWEEN '01-APR-19' AND '30-SEP-19'
GROUP BY CLIENT,DATE
)
GROUP BY CLIENT

I guess you need max of mktvoulumes for each quarter to evaluate the ratio quarter wise. Is this what you want as below?
Select
CLIENT
, SUM(CASE WHEN DATE BETWEEN
'01-JUL-19' AND '30-SEP-19' THEN
VOLUME END) )
/(
MAX(CASE WHEN DATE BETWEEN
'01-JUL-19' AND '30-SEP-19' THEN
MKT_VOLUME END) ) AS Q1
, SUM(CASE WHEN DATE BETWEEN
'01-APR-19' AND '30-JUN-19' THEN
VOLUME END)
/
(
MAX(DISTINCT CASE WHEN DATE
BETWEEN
'01-JUL-19' AND '30-SEP-19' THEN
MKT_VOLUME END) ) AS Q2
From Table group by client

Related

How can I fetch total of Qty of Buy and Sale in month of July in single sql query

I want to find total buy and sell in single row for the specific month.
Below is the table
Month() function will help to group the month values.
SELECT
YEAR(TrDate) SaleYear,
MONTH(TrDate) SaleMonth,
SUM(CASE WHEN trType = 'B' THEN Qty END)) as TotalBuy,
SUM(CASE WHEN trType = 'S' THEN Qty END)) as TotalSale
FROM TableName
GROUP BY YEAR(TrDate), MONTH(TrDate)

SQL case operation

Im fairly new with sql, and been trying to solve a problem where you have a table information about orders. In this case, Im trying to use the case operation to get a monthly report on orders, so I should have a column which states the year,another one which states the month, and then I should have columns for days 1-20,21-22,23-24 and above 25. Im trying to use the case operation to get the amount of orders that happened on those days.
I tried the following query :
SELECT
DATEPART(YEAR,date) AS year,DATEPART(MONTH,date) AS month,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 1 AND 20 THEN order ELSE 0 END) AS D1_D20,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 21 AND 22 THEN order ELSE 0 END) AS D21_D22,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 23 AND 24 THEN order ELSE 0 END) AS D23_D24,
COUNT(CASE WHEN DATEPART(DAY,date) > 25 THEN order ELSE 0 END) AS D25_END
FROM ORDERS
GROUP BY DATEPART(YEAR,date),DATEPART(MONTH,date)
Obviously the problem with that query is that, now I just get the total number of orders for each of the days, I know I should count the orders, but dont know the syntax. Help would be greatly appreciated!
Use SUM():
SELECT
DATEPART(YEAR, date) AS year, DATEPART(MONTH, date) AS month,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 1 AND 20 THEN 1 ELSE 0 END) AS D1_D20,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 21 AND 22 THEN 1 ELSE 0 END) AS D21_D22,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 23 AND 24 THEN 1 ELSE 0 END) AS D23_D24,
SUM(CASE WHEN DATEPART(DAY,date) > 25 THEN 1 ELSE 0 END) AS D25_END
FROM ORDERS
GROUP BY DATEPART(YEAR, date), DATEPART(MONTH, date);
I would recommend using the functions DAY(), YEAR(), and MONTH() because they are simpler to type.
By the way, you can use COUNT() if you remove the ELSE clause. Your particular problem is that COUNT(0) = COUNT(1) because COUNT() counts non-NULL values. I prefer SUM() because it is more intuitive in this respect.

nest queries and pass their results as alias to SUM

So, I'm running two queries that returns me the X amount of items per month through a year.
the 1st query gives me the following result
the 'no column name' would be the months, so I have no data in august, november and december.
The second query, gives me the following
only August and Setpember has data.
What I'm trying to figure out is how can I sum both tables to get the 100% value, then define each % (corretivas x preventivas).
In my research, I assume I have to nest the queries, but I just can't reach the logic to get me near the wanted result.
this is my queries so far
select month(workOrderDate), COUNT(*) as preventivas from WorkOrder WHERE
workOrderDescription = 'preventiva'
AND YEAR(workOrderDate) = 2018
AND lastUpdateData IS NOT NULL
AND WorkType = '02'
group BY MONTH(workOrderDate)
ORDER BY MONTH(workOrderDate)
select MONTH(workOrderDate), COUNT(*) AS corretivas from WorkOrder WHERE
YEAR(workOrderDate) = 2018
AND workOrderDescription = 'CORRETIVA'
AND lastUpdateData IS NOT NULL
GROUP BY MONTH(workOrderDate)
ORDER BY MONTH(workOrderDate)
The expected result would be
and so on
Would anybody helpe me with this?
You want conditional aggregation :
SELECT MONTH(wo.workOrderDate), COUNT(*) AS total,
(SUM(CASE WHEN wo.WorkType = '02' AND wo.orkOrderDescription = 'preventiva' THEN 1 ELSE 0 END) * 1.0 / COUNT(*)) * 100 AS preventiva,
(SUM(CASE WHEN wo.orkOrderDescription = 'CORRETIVA' THEN 1 ELSE 0 END) * 1.0 / COUNT(*)) * 100 AS CORRETIVA
FROM WorkOrder wo
WHERE YEAR(wo.workOrderDate) = 2018 AND wo.lastUpdateData IS NOT NULL
GROUP BY MONTH(wo.workOrderDate);

Condition SUM in SQL

I want to calculate con_Amount field & want to put total to D01,D02,....D31 on the condition of Con_PubDate.
if Con_PubDate field Day = 1 then I want to put the total to D01,if Con_PubDate field Day = 2 then I want to put the total to D02,likewise upto Day = 31 then I want to put the total to D31
I try following code in stored procedure but it had an error. Some one please help me to solve this problem.
SELECT Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount
END) AS D31
END) AS D02
END) AS D01
FROM Contributions
GROUP BY Con_Cnt_Code,Con_Dst_Code,Con_Cor_Code
You probably want each conditional sum of a CASE expression as a separate item in your select list, something like this:
SELECT
Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount END) AS D01,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount END) AS D02,
-- and possibly other days as well
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount END) AS D31
FROM Contributions
GROUP BY
Con_Cnt_Code, Con_Dst_Code, Con_Cor_Code;
By default, SUM will ignore NULL values, so you might not need an ELSE condition in your CASE expressions. If you add one, you may default the amount to sum to zero.

SQL Pivoting With rollup (or a row totals)

I have the following query with some g/l accounts and sum totals by month:
Select Month, [41100],[42000],[45100],[42200],[42300],[42400],[45200],
[45205]
from ( Select ACC_0 , (CONVERT(NUMERIC(12,2),(AMTLED_0))) as Amount , MONTH(ACCDAT_0) as Month
from x3v6.CICPROD.GACCENTRYD with(nolock)
where YEAR(ACCDAT_0) = YEAR(GETDATE())
) as s1
PIVOT (SUM(Amount) FOR ACC_0 IN ([41100],[42000],[45100],[42200],[42300],[42400],[45200],
[45205])) as pivot1
Which produces the following result set:
Month 41100 42000 45100 42200 42300 42400 45200 45205
1 3857806.91 19987.61 49876.84 49078.59 2173.63 NULL 375.00 68.52
2 4459775.79 5145.69 64442.41 58102.00 2684.40 NULL 230.00 NULL
3 4311142.03 8594.31 44220.72 33850.08 3116.75 141.00 1917.50 NULL
4 4413788.57 5613.67 58038.20 55359.25 4398.67 NULL 4796.38 132.00
5 4251083.15 4372.07 48488.03 53592.00 2869.86 127.00 110.00 128.00
6 4353075.16 9705.83 53925.37 64104.00 2304.65 2822.78 153.41 NULL
7 4549485.41 10054.92 61607.99 65136.00 1531.66 186.30 265.50 NULL
8 4239075.39 16917.10 43012.02 51591.25 1538.01 1690.91 350.00 NULL
9 4331439.41 39248.15 56368.41 74928.00 1858.82 694.32 160.00 66.00
10 3673909.02 12283.42 38928.66 28608.00 NULL NULL 120.00 NULL
I would like to get a TOTAL tally by each ROW in a column to the right. How would I accomplish this with the PIVOT syntax? I tried using a grouping sets, but it didn't work for me.
Version is SQL Server 2012.
Thanks
One simple way, would be to not use PIVOT, and instead, use the SUM aggregate with CASE expressions.
SELECT Month,
SUM(CASE WHEN ACC_0 = '41100' THEN Amount END) AS [41100],
SUM(CASE WHEN ACC_0 = '42000' THEN Amount END) AS [42000],
SUM(CASE WHEN ACC_0 = '45100' THEN Amount END) AS [45100],
SUM(CASE WHEN ACC_0 = '42200' THEN Amount END) AS [42200],
SUM(CASE WHEN ACC_0 = '42300' THEN Amount END) AS [42300],
SUM(CASE WHEN ACC_0 = '42400' THEN Amount END) AS [42400],
SUM(CASE WHEN ACC_0 = '45200' THEN Amount END) AS [45200],
SUM(CASE WHEN ACC_0 = '45205' THEN Amount END) AS [45205],
SUM(Amount) AS [Total]
FROM (SELECT ACC_0,
(CONVERT(NUMERIC(12,2),(AMTLED_0))) AS Amount,
MONTH(ACCDAT_0) AS Month
FROM x3v6.CICPROD.GACCENTRYD WITH (NOLOCK)
WHERE YEAR(ACCDAT_0) = YEAR(GETDATE())
-- only get the ACC_0 values you need so Total is correct
AND ACC_0 IN ('41100','42000','45100','42200','42300','42400','45200','45205')
) AS s1
GROUP BY Month