Reference an ALIAS in a SUM funciton - SQL Server - sql

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;

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.

SQL Sum with calculated column

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.

SUM and GROUP BY a substring in Splice (NoSql)

I am trying to to run a query like the one below. The goal is to get the total activity count for every user_key but because the user_key has a complex structure and I need only the part after the '|' symbol I had to use a substring function. However, when I'm trying to run the query, I get the
error:
SQL Error [42Y36]: Column reference 'USER_KEY' is invalid, or is part of an invalid expression. For a SELECT list with a GROUP BY, the columns and expressions being selected may only contain valid grouping expressions and valid aggregate expressions.
The substring function works OK outside this query. Any workarounds for this problem? Using Splice Machine (NoSql)
SELECT
substr(user_key, instr(user_key,'|') + 1) AS new_user_key,
SUM(
CAST(
activity_count AS INTEGER
)
) AS Total
FROM
schema_name.table_name
GROUP BY
substr(user_key, instr(user_key,'|') + 1)
Your GROUP BY column needs to match the SELECT
SELECT
substr(user_key, instr(user_key,'|') + 1) AS new_user_key,
SUM(
CAST(
activity_count AS INTEGER
)
) AS Total
FROM
schema_name.table_name
GROUP BY
substr(user_key, instr(user_key,'|') + 1) AS new_user_key
I found the answer myself. I used a table subquery:
SELECT new_table.new_user_key, sum(new_table.total)
from
(
SELECT
substr(user_key, instr(user_key,'|') + 1) AS new_user_key,
CAST(activity_count AS INTEGER) AS Total
FROM schema_name.table_name
)
as new_table
GROUP BY
new_table.new_user_key
Let's hope someone will find this post useful and will save some time to him or her.

subquery Count() - Column must appear in the GROUP BY clause

I just wanted to know, why a subquery returned more than one value, so I made this query:
SELECT id,
(SELECT Count(tags[i])
FROM generate_subscripts(tags, 1) AS i
WHERE tags[i]='oneway') as oneway_string
FROM planet_osm_ways
WHERE 'oneway' = ANY(tags)
HAVING
(SELECT Count(tags[i])
FROM generate_subscripts(tags, 1) AS i
WHERE tags[i]='oneway') > 1
which should find all occurences of 'oneway' in tags array and count them.
[42803] ERROR: column "planet_osm_ways.id" must appear in the GROUP BY clause
or be used in an aggregate function Position: 8
You should change HAVING to WHERE as there are no groups on which you could apply HAVING filter, instead you want to use WHERE filter which applies to each row.
SELECT id,
(SELECT Count(tags[i])
FROM generate_subscripts(tags, 1) AS i
WHERE tags[i]='oneway') as oneway_string
FROM planet_osm_ways
WHERE 'oneway' = ANY(tags)
AND
(SELECT Count(tags[i])
FROM generate_subscripts(tags, 1) AS i
WHERE tags[i]='oneway') > 1

Using created column in select statement twice

I have a big problem with this query in SQL.
select distinct
b.*,
case
when b.Cash > b2.Cash
then ((b.Cash - b2.Cash) / b.Cash) * 100
end as Increased,
('Cash Increased by' + convert(VARCHAR(20), Increased))) as
Case
from
Accounting b
join
(…
In select statement I created column Increased. Then I want to created another column Case with the following value Cash Increased by… (value from Increased column).
My question is how can I do it in one select statement?
You have two options
Use this query as a subquery and do the concatenation in the outer query
You have to copy-paste the CASE..WHEN into the concatenations
Subquery
SELECT
*
, ('Cash Increased by' + convert(VARCHAR(20), Increased))) AS CASE
FROM (
SELECT DISTINCT
b.*
, CASE
WHEN b.Cash > b2.Cash THEN ((b.Cash - b2.Cash) / b.Cash) * 100
END AS Increased
FROM
Accounting b JOIN (...)
) SubQuery
Copy the CASE part
SELECT DISTINCT
b.*
, CASE
WHEN b.Cash > b2.Cash THEN ((b.Cash - b2.Cash) / b.Cash) * 100
END AS Increased
, (
'Cash Increased by' + CONVERT(VARCHAR(20),
CASE
WHEN b.Cash > b2.Cash THEN ((b.Cash - b2.Cash) / b.Cash) * 100
END)
) AS CASE
FROM
Accounting b JOIN (...)
NOTE
Do not forget to escape (or change) the alias for the concatenation. The CASE is a reserved word in most DMBS!
NOTE 2 Next time please mention the DBMS you are using!