New column to calculate percentage - ms-access

Need to add a column with percentage for each "adh_classi" by "stop_code"
ex.
"Stop_code" Count adh_Classi
10013 32 Early
10013 101 Late
10013 317 On-Time
Total for 10013 = 450
Early-> 7.11% (32/450)
Late -> 22.44% (101/450)
I do not have much Access experience

Accomplishing in a query requires an aggregate subquery or DSum() aggregate function to calculate the total for each class.
SELECT Stop_Code, 100 * Count / (SELECT Sum(Count) AS SumCnt FROM tablename AS Q1
WHERE Q1.Stop_Code = tablename.Stop_Code) AS Pct FROM tablename;
or
SELECT tablename.Stop_Code, 100 * Count / SumCnt AS Pct
FROM tablename
INNER JOIN (SELECT Stop_Code, Sum(Count) AS SumCnt FROM tablename
GROUP BY Stop_Code) AS Q1
ON tablename.Stop_Code = Q1.Stop_Code;
or
SELECT Stop_Code, 100 * Count / DSum("Count", "tablename", "Stop_Code=" & [Stop_Code]) AS Pct
FROM tablename
Domain aggregate function causes slower performance in large dataset.
Another approach is to build a report that uses Grouping & Sorting design and aggregate function calc in textbox of group footer: =Sum([Count]) . Expression in detail section would reference footer textbox: =100 * [Count] / [tbxSubTotal].

Related

Sum Distinct Duplicated Values

I have a dataset as below:
customer buy profit
a laptop 350
a mobile 350
b laptop case 50
c laptop 200
c mouse 200
It does not matter how many rows the customer has, the profit is already stated in the row (it's already an accumulative sum). For example, the profit of customer a is 350 and the profit of customer c is 200.
I would like to sum uniquely the profit for all the customers so the desire output should be 350 + 50 + 200 = 600. However, I need to execute this in one line of code (without doing subquery, nested query or write in a separate CTE).
I tried with Partition By but cannot combine MAX and SUM together. I also tried SUM (DISTINCT) but it does not work either
MAX(profit) OVER (PARTITION BY customer)
If anyone could give me a hint on an approach to tackle this, it would be highly appreciated.
You really should use a subquery here:
SELECT SUM(profit) AS total_profit
FROM (SELECT DISTINCT customer, profit FROM yourTable) t;
By the way, your table design should probably change such that you are not storing the redundant profit per customer across many different records.
You can combine SUM() window function with MAX() aggregate function:
SELECT DISTINCT SUM(MAX(profit)) OVER () total
FROM tablename
GROUP BY customer;
See the demo.
Select sum(distinct profit) as sum from Table
You can select max profit of each customer like this:
SELECT customer, MAX(profit) AS max_profit
FROM tablename
GROUP BY customer
Then you can summarise the result in your code or even in the query as nested queries:
SELECT SUM(max_profit) FROM (
SELECT customer, MAX(profit) AS max_profit
FROM tablename
GROUP BY customer
) AS temptable

How to query the percent of totals in a group by query

I have a query that pulls the total number of records grouped by the year and length of characters in the identification number. I want to add a column that calculates the percentage of this total against the total for each record year.
This is the query that I am using, and so far I'm able to pull the year, ID length, and the number of records; however, I'm unable to pull the percentage of the total, grouping by the year:
/* Assess length of McrCertID_112 field for 2020. Count the number and percent of records: */
SELECT
DemoRateYear_101,
length(McrCertId_112),
count(*) AS 'Num_of_Records',
concat((count(*) / (SELECT count(*) FROM upl_db_prod.tblProviderDetails) * 100), '%') AS 'Percentage'
FROM upl_db_prod.tblProviderDetails
GROUP BY length(McrCertId_112), DemoRateYear_101
ORDER BY DemoRateYear_101, length(McrCertId_112);
This is what I want the final table to look like:
DemoRateYear_101 length(McrCertId_112) Num_of_Records Percentage
2017 4 10 47.6190%
2017 5 11 52.3809%
2018 4 8 26.6667%
2018 5 10 33.3333%
2018 7 12 40.0000%
Is there a way I can accomplish this in one query? Thank you for looking!
If window functions are available you can do this:
SELECT
demorateyear_101,
LENGTH(mcrcertid_112),
COUNT(*) AS num_of_records,
COUNT(*) / SUM(COUNT(*) OVER (PARTITION BY demorateyear_101)) * 100 AS percentage
FROM tblproviderdetails
GROUP BY demorateyear_101, LENGTH(mcrcertid_112)
ORDER BY demorateyear_101, LENGTH(mcrcertid_112);
Otherwise a subquery is needed (where clause, if any, must match):
SELECT
demorateyear_101,
LENGTH(mcrcertid_112),
COUNT(*) AS num_of_records,
COUNT(*) / (
SELECT COUNT(*)
FROM tblproviderdetails AS x
WHERE x.demorateyear_101 = tblproviderdetails.demorateyear_101
) * 100 AS percentage
FROM tblproviderdetails
GROUP BY demorateyear_101, LENGTH(mcrcertid_112)
ORDER BY demorateyear_101, LENGTH(mcrcertid_112);

Using created variable in WHERE (MySQL)

I have a table of bank transactions in MySQL that appear as so:
User ID
Date Created
Currency
Amount
USD_amt
1
April 1
USD
1000
1000
1
May 2
GBP
100
141.90
2
April 2
USD
50
50
2
May 5
EUR
200
243.85
The USD_amt is a calculated field from two other tables. I'd like to get the average USD Amount by User ID as well as average amount by user ID by month and then filter on the rows where the monthly average is 10 times the user average
Right now, I am trying the following
SELECT
t.user_id,
t.created_date,
month(t.created_date),
year(t.created_date),
(t.AMOUNT * fx.rate / POWER(10, cd.exponent)) USD_amt,
avg(t.AMOUNT * fx.rate / POWER(10, cd.exponent)) monthly_avg,
avg(t.AMOUNT * fx.rate / POWER(10, cd.exponent)) over (partition by t.user_id) user_avg
from
transactions t
join fx_rates fx
on (fx.ccy = t.currency and fx.base_ccy = 'USD')
join currency_details cd
on cd.currency = t.currency
where
monthly_avg > 10* user_avg
group by
t.user_id,
t.created_date,
month(t.created_date),
year(t.created_date)
Although, it doesn't appear I can use the created variable in the WHERE function.
Any ideas?
You can not use results for the query in the WHERE clause, because WHERE is executed before the results are calculated.
If you want to apply a filter based on the results, you need to use HAVING, which is executed after.
Of course this has performances implications: WHERE allows you to retrieve a subset of results, while HAVING returns all the rows then filters them.
Here's a quick fix on your code that should work
SELECT
t.user_id,
t.created_date,
month(t.created_date),
year(t.created_date),
(t.AMOUNT * fx.rate / POWER(10, cd.exponent)) USD_amt,
avg(t.AMOUNT * fx.rate / POWER(10, cd.exponent)) monthly_avg,
avg(t.AMOUNT * fx.rate / POWER(10, cd.exponent)) over (partition by t.user_id) user_avg
from
transactions t
join fx_rates fx
on (fx.ccy = t.currency and fx.base_ccy = 'USD')
join currency_details cd
on cd.currency = t.currency
group by
t.user_id,
t.created_date,
month(t.created_date),
year(t.created_date)
having
monthly_avg > 10* user_avg

mysql sql avg function does not return correct values?

I've my table with structure like this
Now I want to produce a table that show final average of each student by formula:
Final_avg=0.15x(average of exam= test1,test2 and test3)
+0.25x(exam=midterm)+0.6x(exam=terminal);
I've tried this query but I'm getting incorrect values of fainal_avg
select e.sname AS sn
, AVG( CASE WHEN e.exam IN ('test1','test2','test4') THEN e.average END ) AS t_avg
, e3.average as mid
, e2.average as main
, 0.15*e.average+0.25*e3.average+0.6*e2.average AS f_avg
from $form as e
JOIN $form as e2
ON e2.sname = e.sname AND e2.exam = 'terminal'
JOIN $form as e3
ON e3.sname = e.sname AND e3.exam = 'midterm'
group by e.sname
order by f_avg desc
The final average that I get from the query is inncorect with one that I get by calculating using calculator
This is table for correct and incorrect final average
You are grouping by e.sname, but access e.average in your select clause. As there are several records per sname, it is left to chance which value the DBMS picks from them. You want an aggregation such as AVG(e.sname) instead, in your case: AVG(CASE WHEN e.exam IN ('test1','test2','test4') THEN e.average END).
This mix of self joins and conditional aggregation is kind of clumsy, however. I suggest either to aggregate your test records before joining or not joining at all instead.
Aggregate test records before joining
select
sname, 0.15 * tst.average + 0.25 * mid.average + 0.6 * trm.average as result
from
(
select sname, avg(average) as average
from $form
where exam in ('test1','test2','test4')
group by sname
) tst
join $form trm on trm.sname = tst.sname and exam = 'terminal'
join $form mid on mid.sname = tst.sname and exam = 'midterm';
Mere aggregation, no join
select
sname,
0.15 * avg(case when exam in ('test1','test2','test4') then average end) +
0.25 * avg(case when exam = 'midterm' then average end) +
0.6 * avg(case when exam = 'terminal' then average end) as result
from $form
group by sname;
It returns the average value of given argument, which is field name of a table.
The Distinct option may be used to calculate average of only distinct values from the given set of values.
If we want to find average marks from table student where marks are given in the column s_marks.
For More Click

Filling a field inside a select stamenet - MySQL

I'm trying to do calculations and fill a field inside a select statement. It looks like this:
CREATE VIEW SALES_REPORT AS(
SELECT
INVOICENO,
INVOICEDATE,
CLIENTID,
CONTACT,
INVOICEJOBNO,
ADDCHARGES,
CHARGESINFO,
EMPLOYEEID,
USUALPAY,
VAT,
SUBTOTAL (SELECT(USUALPAY * COUNT(*) AS SUBTOTAL FROM SALES_REPORT)),
TOTAL = (SUBTOTAL * VAT)
FROM SALES_REPORT_JOINS_CONFIG
GROUP BY INVOICENO ORDER BY INVOICEDATE DESC);
Any help would be great, thanks!
TOTAL = (SUBTOTAL * VAT)
should probably be
(SUBTOTAL * VAT) AS TOTAL
right now it's going to return the boolean true/false result of an equality comparison. You're NOT assigning the multiplication results to a 'total' field - you're comparing whatever value is in total to the result of the multiplication.
and this is a flat-out syntax error:
SUBTOTAL (SELECT(USUALPAY * COUNT(*) AS SUBTOTAL FROM SALES_REPORT)),