SQL, querying sum of positive results, absolute value - sql

I have the following query which returns a total dollar amount.
select sum(cast(dollars as dec)) from financials
This includes positive and negative values.
I would like 2 separate things:
How can I just query the positive dollar amounts? ie. I have 3 records, 10 , -5 , 10. result would be 20.
I want an absolute value as a sum. ie. I have 3 records, 10, -5, 10. the result would be 25.
thanks.

FOR 1) Use conditional SUM()
SELECT SUM( CASE WHEN dollars > 0 then dollars ELSE 0 END) as positive_sum,
SUM( CASE WHEN dollars < 0 then dollars ELSE 0 END) as negative_sum
FROM financials
FOR 2) use ABS()
SELECT SUM( ABS( dollars ) )
FROM financials

Please try below queries. Thanks.
1) select sum(cast(dollars as dec))
from financials
where dollars > 0;
2) select sum(cast(abs(dollars) as dec))
from financials;

You have two queries.solutions are as follows
1.
select sum(dollars) from financials
2.
select sum((case when dollars>0 then dollars end))+sum((case when dollars<0 then -1*dollars end)) from financials

Related

How can I show the percentage of increase or decrease of visits to a page with respect to the previous year in SQL

how are you doing? I need a query in SQL that when entering the current year shows me a percentage of increase or decrease in visits to my page with respect to the previous year, if it can be better by months.
I currently have this query that shows me the number of visits per month on my page, I need to fill the Percentage column with a new query:
SELECT
FORMAT([DateTime], 'MMMM') AS [Month],
COUNT(*) AS [CounterOfVisitors],
'' AS [Percentage]
FROM
[BasicCore.VisitorCounter]
WHERE
YEAR([DateTime]) = 2023
GROUP BY
MONTH([DateTime]), FORMAT([DateTime], 'MMMM')
This is the output:
Thank you so much
You can first scan both 2022 and 2023 data,and then use conditional CASE inside sum function to see year over year comparison.
See the following code as example.
SELECT
FORMAT([DateTime], 'MMMM') AS [Month],
SUM(CASE WHEN YEAR([DateTime])=2023 THEN 1 ELSE 0 END) AS [CounterOfVisitors],
(SUM(CASE WHEN YEAR([DateTime])=2023 THEN 1 ELSE 0 END) * 1.0 / SUM( CASE WHEN YEAR([DateTime])=2022 THEN 1 ELSE 0 END) - 1.0) AS [Percentage]
FROM
[BasicCore.VisitorCounter]
WHERE
YEAR([DateTime]) in (2022,2023)
GROUP BY
MONTH([DateTime]), FORMAT([DateTime], 'MMMM')

Calculate rate based on condition using postgresql

I want to find the rate of negative and zero profits from a column. I tried to do it using aggregate and subquery but it doesn't seem to work as both method return 0 values.
The code is as follows
SELECT
COUNT(CASE WHEN profit < 0 THEN 1
END) AS negative_profits,
COUNT(CASE WHEN profit < 0 THEN 1
END) / COUNT(profit),
COUNT(CASE WHEN profit = 0 THEN 1
END) AS zero_profits,
COUNT(CASE WHEN profit = 0 THEN 1
END) / COUNT(profit)
FROM sales;
SELECT (SELECT COUNT(*)
FROM sales
WHERE profit <= 0)/COUNT(profit) AS n_negative_profit
FROM sales;
Both query return 0 in values
enter image description here
Avoid integer division, which truncates (like Adrian pointed out).
Also, simplify with an aggregate FILTER expression:
SELECT count(*) FILTER (WHERE profit <= 0)::float8
/ count(profit) AS n_negative_profit
FROM sales;
If profit is defined NOT NULL, or to divide by the total count either way, optimize further:
SELECT count(*) FILTER (WHERE profit <= 0)::float8
/ count(*) AS n_negative_profit
FROM sales;
See:
Aggregate columns with additional (distinct) filters
Because you are doing integer division per docs Math operators/functions.
numeric_type / numeric_type → numeric_type
Division (for integral types, division truncates the result towards zero)
So:
select 2/5;
0
You need to make one of the numbers float or numeric:
select 2/5::numeric;
0.40000000000000000000
and to make it cleaner round:
select round(2/5::numeric, 2);
0.40

Overflow error when using the sum function?

I'm writing a query to calculate how much more the average customer has transacted and spent since signing up with my company. However, it returns the error message "Overflow occurred during numeric data type conversion".
The problem is definitely this bit, as when I comment it out the query runs successfully:
SUM(SALES_GROWTH_PERCENT)
Google tells me it's likely that I'm trying to fit a number with too many decimal places into a field that's too short for it. However, I've tried changing how many decimal places the case statements are using with no luck.
Edit: for context, here are the details of the fields being used, from syscat.columns:
This is the query in question. Can anyone see where I'm going wrong please? Any advice would be appreciated!
SELECT SUM(TRANS_GROWTH_PERCENT)/COUNT(CUSTOMER_ID) AS AVG_TRANS_GROWTH_PERCENT,
SUM(SALES_GROWTH_PERCENT)/COUNT(CUSTOMER_ID) AS AVG_SALES_GROWTH_PERCENT
FROM
(
SELECT CUSTOMER_ID,
CASE WHEN POST_SIGNUP_TRANS <=0
THEN 0
WHEN POST_SIGNUP_TRANS >0
THEN CAST((CAST(POST_SIGNUP_TRANS AS DECIMAL (10,5)) - CAST(PRE_SIGNUP_TRANS AS DECIMAL (10,5))) / CAST(PRE_SIGNUP_TRANS AS DECIMAL (10,5)) * 100 AS DECIMAL (10,1))
ELSE NULL
END AS TRANS_GROWTH_PERCENT,
CASE WHEN POST_SIGNUP_SALES <=0
THEN 0
WHEN POST_SIGNUP_SALES >0
THEN CAST((CAST(POST_SIGNUP_SALES AS DECIMAL (10,5)) - CAST(PRE_SIGNUP_SALES AS DECIMAL (10,5))) / CAST(PRE_SIGNUP_SALES AS DECIMAL (10,5)) * 100 AS DECIMAL (10,1))
ELSE NULL
END AS SALES_GROWTH_PERCENT
FROM
(
SELECT CUSTOMER_ID,
SUM(PRE_SIGNUP_TRANS) AS PRE_SIGNUP_TRANS, SUM(PRE_SIGNUP_SALES) AS PRE_SIGNUP_SALES,
SUM(POST_SIGNUP_TRANS) AS POST_SIGNUP_TRANS, SUM(POST_SIGNUP_SALES) AS POST_SIGNUP_SALES
FROM
(
SELECT CUSTOMER_ID,
CASE WHEN TRANSACTION_DATE >= ANALYSIS_START_DATE THEN 1 ELSE 0 END AS ANALYSIS_FLAG,
CASE WHEN TRANSACTION_DATE < SIGNUP_DATE THEN 1 ELSE 0 END AS PRE_SIGNUP_TRANS,
CASE WHEN TRANSACTION_DATE < SIGNUP_DATE THEN SALES ELSE 0 END AS PRE_SIGNUP_SALES,
CASE WHEN TRANSACTION_DATE >= SIGNUP_DATE THEN 1 ELSE 0 END AS POST_SIGNUP_TRANS,
CASE WHEN TRANSACTION_DATE >= SIGNUP_DATE THEN SALES ELSE 0 END AS POST_SIGNUP_SALES
FROM TRANSACTIONS_TABLE
)
WHERE ANALYSIS_FLAG = 1
GROUP BY CUSTOMER_ID
)
WHERE PRE_SIGNUP_TRANS >0
AND PRE_SIGNUP_SALES >0
)
;

How can I count total number of sales per month using a condition in SQL?

I searched the forum but couldn't find a problem like the one I have. I have a table called Journal Table and it has the following data:
A transaction is considered to be sales if the Quantity>0 otherwise it's a loan transaction. Now my question is how can I count the total number of transactions as Sales Per month.
Like:
Month | TotalSales
1 5
2 3
3 7
I tried the following but got the wrong output:
Select DISTINCT Month(date) AS 'Month',
(Select COUNT(TransactionID) from journalTable where Quantity>0)
AS 'Total Sales' from journalTable;
Here is a picture of the output:
The output is wrong as it counts the total of all months and shows it for each month. It should count each month's total and show it.
Just group by and conditionally sum.
select Month(date) as 'Month'
, sum(case when Quantity > 0 then 1 else 0 end) as 'Total Sales'
-- You can even add a count of loans at the same time.
, sum(case when Quantity <= 0 then 1 else 0 end) as 'Total Loans'
from journalTable
group by Month(date);
Something like this
SELECT MONTH(DATE) AS MONTH, COUNT(QUANTITY)CNTT
FROM TRANSACTIONS
WHERE QUANTITY > 0
GROUP BY MONTH(DATE)

SQL Query to sum buckets

I have a table with inovices and a field named Arrers days and I need to count how many items are into 0-30 days also 30-90 and 90-120
Basically what I need is to calcuate the aging of my client portfolio.
so far I have this:
SELECT SUM(CASE WHEN Receivable.Arrers>'0'<'30' THEN 1 ELSE 0) AS 0-30,
SUM(CASE WHEN Receivable.Arrers<'30'>'60' THEN 1 ELSE 0) AS 30-60,
SUM(CASE WHEN Receivable.Arrers<'90'>'120' THEN 1 ELSE 0) AS 90-120
From Receivable
Table Name Receivable
Invoice Arrers
89859 10
89856 3
89853 11
Access SQL does not support CASE WHEN. You can use an IIf expression instead.
SELECT
SUM(IIf(r.Arrers BETWEEN 0 AND 30, 1, 0)) AS [0-30],
SUM(IIf(r.Arrers BETWEEN 31 AND 60, 1, 0)) AS [31-60],
SUM(IIf(r.Arrers BETWEEN 90 AND 120, 1, 0)) AS [90-120]
FROM Receivable AS r;
The example in your question ignores Arrers from 61 to 89, so I did, too. But you can add in another column expression if needed.
If Arrers is text instead of numeric datatype, you can use Val() to cast the text values to numbers ...
SUM(IIf(Val(r.Arrers) BETWEEN 0 AND 30, 1, 0)) AS [0-30]
You can try that one
SELECT
SUM( CASE WHEN Receivable.Arrers BETWEEN 0 AND 30 THEN 1 ELSE 0) AS '0-30',
SUM (CASE WHEN Receivable.Arrers BETWEEN 30 AND 60 THEN 1 ELSE 0) AS '30-60',
SUM (CASE WHEN Receivable.Arrers BETWEEN 90 AND 120 THEN 1 ELSE 0) AS '90-120',
arrers
FROM Receivable
GROUP BY arrers
1 thing need to be checked.
I've put BETWEEN 90 AND 120 as I consider it integer. If they are varchar, you will need to turn them into integers. Val(Receivable.Arrers) will do the trick on access. Please let me know if there is anything unclear
You are on the right track except possibly for the CASE stmt syntax .... try Andy's answer without the Group by
(Dont have enough points to post as a comment)
I'd use something like this:
SELECT subq.ArrersGroup, COUNT(*) 'Count'
FROM
(
SELECT
CASE
WHEN R.Arrers < 30 THEN '0-30'
WHEN R.Arrers < 90 THEN '30-90'
WHEN R.Arrers < 120 THEN '90-120'
ELSE 'Other'
END ArrersGroup
FROM Receivable R
) subq
GROUP BY subq.ArrersGroup
SqlFiddle