SQL Sum with calculated column - sql

hello I have an SQL query that selects a SUM value in the first column and I want the second column to be ( first_column / another_field )
select sum(a.amount), (sum(a.amount) / d.total_loading_weight * 1000) as MarginPerTon
from tra_affair a join tra_Delivery d on a.delivery=d.delivery_id
where a.delivery='394179' and a.is_margin='1'
I am getting the "not a single-group group function" error

The problem is: d.total_loading_weight. I'm not sure what you want, but something like:
select sum(a.amount),
(sum(a.amount) / sum(d.total_loading_weight * 1000)) as MarginPerTon
from tra_affair a join
tra_Delivery d
on a.delivery = d.delivery_id
where a.delivery = '394179' and a.is_margin = '1';
You can also use min() or max() instead of sum() if the values are always the same.

Related

Average over Group By SQL

I have the command:
SELECT
number_of_pairs,
COUNT(*) --/(SUM(COUNT)) AS Percentage
FROM result
WHERE number_of_pairs!= 'NULL'
GROUP BY 1;
Which results in :
But my objective is not to know the count of each group but the percentage of each group count with respect the total.
I have tried:
COUNT(*)/(SUM(COUNT)) AS Percentage
But doesn't return anything.
I would like to get 379/(379+371)=0.505 in the first row and 371/(379+371)=... in the second
SQLite version : 3.11.0
You can use SUM() window function to get the total:
SELECT
number_of_pairs,
1.0 * COUNT(*) / SUM(COUNT(*)) OVER() AS Percentage
FROM result
WHERE number_of_pairs <> 'NULL'
GROUP BY number_of_pairs;
Unless you actually have 'NULL' as a string literal in column number_of_pairs, you must change the condition to:
number_of_pairs IS NOT NULL
For older versions of SQLite that do not support window functions:
SELECT
r.number_of_pairs,
1.0 * COUNT(*) / MAX(t.counter) AS Percentage
FROM result r
CROSS JOIN (SELECT COUNT(*) counter FROM result WHERE number_of_pairs <> 'NULL') t
WHERE r.number_of_pairs <> 'NULL'
GROUP BY r.number_of_pairs;
See a simplified demo.

Convert and sum variable a, grouping by variable b

I would like to convert the variable ar66 from nvarchar to numeric and sum it for the variable ar5.
I create the following code, but it does not work:
select top(10) ar5, (
select
case
when isnumeric(q1.ar66) = 1 then
cast(q1.ar66 AS numeric)
else
NULL
end
AS 'ar66_numeric'
from rmb_loan q1)
from rmb_loan q2
group by q2.ar5
Do you have any suggestion to solve the problem?
Does this do what you want?
select top (10) ar5, sum(try_convert(numeric(38, 6), q1.ar66))
from rmb_loan q2
group by q2.ar5;
When using select top you should normally have an order by clause.

Reference an ALIAS in a SUM funciton - SQL Server

Background:
I am trying to calculate the profit margin inside of the query and I am running into errors. When I try to use the select statement in the SUM function, I trigger an error:
Cannot perform an aggregate function on an expression containing an
aggregate or a subquery.
I understand that this is caused by having a SELECT query inside of the SUM function. From there, I tried to reference the alias of the COGS column. I recieve an error when I do that as well:
Invalid column name 'COGS'.
After messing around with the query some more, I figured it might be due to fact that I'm trying all of this inside of a SUM function and so I removed that and ran the query. It returned a few errors:
Column 'tbl_invoice.subTotal' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Column 'tbl_invoice.tradeinAmount' is invalid in the select list because it is not contained in either an aggregate function or the
GROUP BY clause.
Column 'tbl_invoice.subTotal' is invalid in the select list because it is not contained in either an aggregate function or the
GROUP BY clause.
Column 'tbl_invoice.tradeinAmount' is invalid in the select list because it is not contained in either an aggregate function or the
GROUP BY clause.
Column 'tbl_invoice.subTotal' is invalid in the select list because it is not contained in either an aggregate function or the
GROUP BY clause.
Column 'tbl_invoice.tradeinAmount' is invalid in the select list because it is not contained in either an aggregate function or the
GROUP BY clause.
Is there another way to use or reference the value I need in the SUM function?
Query:
--Main query
SELECT
custID,
COUNT(custID) AS InvoiceNum,
--This is the column that has an alias
(SELECT cogs FROM #tempMarketing where #tempMarketing.custID = tbl_invoice.custID) as COGS,
--This is where I am trying to calculate the profit margin
SUM(((((subTotal + (-1 * tradeinAmount) - (SELECT cogs FROM #tempMarketing where #tempMarketing.custID = tbl_invoice.custID)))
/ (NULLIF(subTotal + (-1 * tradeinAmount),0))) *100)) as Profitmargin,
FROM tbl_invoice
group by custID
order by InvoiceNum desc;
SELECT
a.custID,
COUNT(a.custID) AS InvoiceNum, case when a.custid=b.custid then b.cogs else 0 end
as COGS,
SUM(((((subTotal + (-1 * tradeinAmount) - case when a.custid=b.custid then b.cogs else 0 end))
/ (NULLIF(subTotal + (-1 * tradeinAmount),0))) *100)) as Profitmargin,
FROM tbl_invoice a
left join #tempMarketing b on a.custID =b.custid
group by a.custID,
case when a.custid=b.custid then b.cogs else null end
order by InvoiceNum desc;
You can try the following query, I have created a common table expression for cogs column:
WITH cte_base AS(
SELECT cogs FROM #tempMarketing where #tempMarketing.custID = tbl_invoice.custID
)
SELECT
custID,
COUNT(custID) AS InvoiceNum,
--This is the column that has an alias
cte_base.cogs as COGS,
--This is where I am trying to calculate the profit margin
SUM(((((subTotal + (-1 * tradeinAmount) - (cte_base.cogs)))
/ (NULLIF(subTotal + (-1 * tradeinAmount),0))) *100)) as Profitmargin,
FROM tbl_invoice
group by custID
order by InvoiceNum desc;

SQL SUM question

Hi I have a question about SUM in sql,
I have a query that looks like this
SELECT
SUM ( table_one.field + table_two.field ) as total_field
SUM ( total_field + table_one.anotherfield )
FROM
table_one
JOIN
table_two ON table_one.id = table_two.id
WHERE
table_one = 1
But this doesn't work ( dont mind possible typing errors in JOIN statement, only the second SUM is the probly the query works perfecly without that SUM)
Is there another way to do it, as I need the total_field within my application. I can ofcource add those numbers within the application but I prefer to do it in sql.
You cannot use the column alias in an aggregate to reference the value, just SUM again;
SELECT
SUM ( table_one.field + table_two.field ) as total_field, --your missing a , also
SUM ( table_one.field + table_two.field + table_one.anotherfield )
FROM
table_one
JOIN
table_two ON table_one.id = table_two.id
WHERE
table_one = 1
SUM is an aggregate function. This means you can aggregate data from a field over several tuples and sum it up into a single tuple.
What you want to do is this:
SELECT
table_one.field + table_two.field,
table_one.field + table_two.field + table_one.anotherfield
or maybe this:
SELECT
SUM(table_one.field) + SUM(table_two.field),
SUM(table_one.field) + SUM(table_two.field) + SUM(table_one.anotherfield)
Try replacing "total_field" with "table_one.field + table_two.field" in second SUM().
The name "total_field" is an alias and as such cannot be used in an aggregate functions
The easiest and quickest way is to simply replace the code for total_field in the second calculation.
SELECT
SUM ( ISNULL(table_one.field,0) + ISNULL(table_two.field,0) ) as total_field
SUM ( ISNULL(table_one.field,0) + ISNULL(table_two.field,0) + IsNUll(table_one.anotherfield,0) )
from
table_one
As your code doesn't cater for a null value in the fields you may get warnings when sum the values. I would suggest using IsNull as above and if there is a null value just treat it as 0.
You could use a subquery like this:
SELECT
total_field,
total_field + sum_anotherfield
FROM (
SELECT
SUM(table_one.field + table_two.field) AS total_field,
SUM(table_one.anotherfield) AS sum_anotherfield
FROM
table_one
JOIN
table_two ON table_one.id = table_two.id
WHERE
table_one.somefield = 1
) x

Using Min/Max with conditional operator

I am trying to run a query to find max and min values, and then use a conditional operator. However, when I try to run the following query, it gives me the error - "misuse of aggregate: min()".
My query is:
SELECT a.prim_id, min(b.new_len*36) as min_new_len, max(b.new_len*36) as max_new_len
FROM tb_first a, tb_second b
WHERE a.sec_id = b.sec_id AND min_new_len > 1900 AND max_new_len < 75000
GROUP BY a.prim_id
ORDER BY avg(b.new_len*36);
Any suggestions?
You need to use the HAVING clause to filter by expressions containing aggregates.
If you are using MySQL you can use the column aliases in that clause for other RDBMSs you can't.
SELECT a.prim_id,
min(b.new_len * 36) as min_new_len,
max(b.new_len * 36) as max_new_len
FROM tb_first a
JOIN tb_second b
ON a.sec_id = b.sec_id /*<-- Use explicit JOIN syntax...*/
GROUP BY a.prim_id
HAVING min(b.new_len * 36) > 1900
AND max(b.new_len * 36) < 75000
ORDER BY avg(b.new_len * 36);
In many RDBMSs you can also put the query into an inline view and select from that to use the column aliases instead of repeating the formulae. In that case you do use WHERE as below.
SELECT prim_id,
min_new_len,
max_new_len
from (SELECT a.prim_id,
min(b.new_len * 36) as min_new_len,
max(b.new_len * 36) as max_new_len,
avg(b.new_len * 36) as avg_new_len
FROM tb_first a
JOIN tb_second b
ON a.sec_id = b.sec_id
GROUP BY a.prim_id) derived
WHERE min_new_len > 1900
AND max_new_len < 75000
ORDER BY avg_new_len;
WHERE clauses filter the individual 'input' records prior to aggregation.
HAVING clauses filter the resulting 'output' records after the aggregation.
Giving the answer posted by Martin.