Average over Group By SQL - 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.

Related

Compare the same table and fetch the satisfied results

I am trying to achieve the below requirement and need some help.
I created the below query,
SELECT * from
(
select b.extl_acct_nmbr, b.TRAN_DATE, b.tran_time,
case when (a.amount > b.amount) then b.amount
end as amount
,b.ivst_grup, b.grup_prod, b.pensionpymt
from ##pps a
join #pps b
on a.extl_acct_nmbr = b.extl_acct_nmbr
where a.pensionpymt <=2 and b.pensionpymt <=2) rslt
where rstl.amount is not null
Output I am getting,
Requirement is to get
The lowest amount row having same account number. (Completed and getting in the output)
In case both the amounts are same for same account (get the pensionpymt =1) (not sure how to get)
In case only one pensionpymt there add that too in the result set. (not sure how to get)
could you please help, expected output should be like this,
you can use window function:
select * from (
select * , row_number() over (partition by extl_acct_nmbr order by amount asc,pensionpymt) rn
from ##pps a
join #pps b
on a.extl_acct_nmbr = b.extl_acct_nmbr
) t
where rn = 1

GROUPING multiple LIKE string

Data:
2015478 warning occurred at 20201403021545
2020179 error occurred at 20201303021545
2025480 timeout occurred at 20201203021545
2025481 timeout occurred at 20201103021545
2020482 error occurred at 20201473021545
2020157 timeout occurred at 20201403781545
2020154 warning occurred at 20201407851545
2027845 warning occurred at 20201403458745
In above data, there are 3 kinds of strings I am interested in warning, error and timeout
Can we have a single query where it will group by string and give the count of occurrences as below
Output:
timeout 3
warning 3
error 2
I know I can write separate queries to find count individually. But interested in a single query
Thanks
You can use filtered aggregation for that:
select count(*) filter (where the_column like '%timeout%') as timeout_count,
count(*) filter (where the_column like '%error%') as error_count,
count(*) filter (where the_column like '%warning%') as warning_count
from the_table;
This returns the counts in three columns rather then three rows as your indicated.
If you do need this in separate rows, you can use regexp_replace() to cleanup the string, then group by that:
select regexp_replace(the_column, '(.*)(warning|error|timeout)(.*)', '\2') as what,
count(*)
from the_table
group by what;
Please use below query, without hard coding the values using STRPOS
select val, count(1) from
(select substring(column_name ,position(' ' in (column_name))+1,
length(column_name) - position(reverse(' ') in reverse(column_name)) -
position(' ' in (column_name))) as val from matching) qry
group by val; -- Provide the proper column name
Demo:
If you want this on separate rows you can also use a lateral join:
select which, count(*)
from t cross join lateral
(values (case when col like '%error%' then 'error' end),
(case when col like '%warning%' then 'warning' end),
(case when col like '%timeout%' then 'timeout' end)
) v(which)
where which is not null
group by which;
On the other hand, if you simply want the second word -- but don't want to hardcode the values -- then you can use:
select split_part(col, ' ', 2) as which, count(*)
from t
group by which;
Here is a db<>fiddle.

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.

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;

SELECT with not equal condition

How to i display the invoicenumber only if the extended price is not equal to subtotal?
Following query is fail to run and error group function is not allowed here
SELECT a.INVOICENUMBER,SUM(a.EXTENDEDPRICE),SUM(a.SUBTOTAL)
FROM CUSTOMERORDERHISTORYVIEW a
WHERE EXISTS
(SELECT a1.INVOICENUMBER FROM CUSTOMERORDERHISTORYVIEW a1 WHERE
a.INVOICENUMBER=a1.INVOICENUMBER AND SUM(a1.EXTENDEDPRICE) <> SUM(a1.SUBTOTAL))
GROUP BY a.INVOICENUMBER;
You are looking for the having clause:
SELECT a.INVOICENUMBER, SUM(a.EXTENDEDPRICE), SUM(a.SUBTOTAL)
FROM CUSTOMERORDERHISTORYVIEW a
GROUP BY a.INVOICENUMBER;
HAVING SUM(a.EXTENDEDPRICE) <> SUM(a.SUBTOTAL);