I am trying to average values of some specific rows but sum volumes of all of them.
I have 2 tables, one called exchanges
and another one called valid_country
.
exchanges
+-----------+----------+--------------+----------+--------+
| id | ref | country | value | volume |
+-----------+----------+--------------+----------+--------+
| 1 | 1029 | DE | 1 000 | 100 |
+-----------+----------+--------------+----------+--------+
| 2 | 1029 | US | 2 000 | 250 |
+-----------+----------+--------------+----------+--------+
| 3 | 1029 | FR | 3 500 | 300 |
+-----------+----------+--------------+----------+--------+
| 4 | 1053 | UK | 1 200 | 110 |
+-----------+----------+--------------+----------+--------+
| 5 | 1029 | RU | 900 | 70 |
+-----------+----------+--------------+----------+--------+
This table contains many references (ref) which have different countries, themselves with different values and volumes.
valid_country
+--------------+--------------+
| ref | country |
+--------------+--------------+
| 1029 | US |
+--------------+--------------+
| 1029 | RU |
+--------------+--------------+
| 1053 | UK |
+--------------+--------------+
This table lists all the 'good' countries for which values can be averaged.
+----------+------------+-------------+
| ref | AVG(value) | SUM(volume) |
+----------+------------+-------------+
| 1029 | 1 450 | 720 |
+----------+------------+-------------+
| 1053 | 1 200 | 110 |
+----------+------------+-------------+
Firstly ref are GROUP BY
.
Ref 1029 shall AVERAGE
values of only US and RU (because of table valid_country) but SUM
volumes of all countries.
Same thing for Ref 1053 but since there's only one row it is easy.
Here is a little Fiddle. The SQL request is false since it averages all countries and not only the good one.
SUM()and AVG()SUM(some_expression) calculates a total for the expression, while AVG(some_expression) returns the average value. The DISTINCT keyword is applicable to both functions, returning only those unique values for the aggregated column or expression. In the event no matching rows are found, NULL is returned.
SELECT SUM(column_name) FROM table_name; If you need to arrange the data into groups, then you can use the GROUP BY clause. The AVG function finds the arithmetic mean for a group of records in a SQL table. An average, or arithmetic mean, is the sum of a group of numbers divided by the count for that group.
SUM() and COUNT() functions SUM of values of a field or column of a SQL table, generated using SQL SUM() function can be stored in a variable or temporary column referred as alias. The same approach can be used with SQL COUNT() function too.
You can use a LEFT JOIN
and the CASE
statement to ignore some values in the AVG
(SQLFiddle):
SELECT e.ref,
AVG(CASE WHEN vc.country IS NOT NULL THEN e.value END) AS average,
SUM(e.volume) AS volume
FROM exchanges e
LEFT JOIN valid_country vc ON ( vc.country = e.country )
GROUP BY e.ref
CASE
returns NULL
if not matched, and AVG
ignores those values:
| ref | average | volume |
|------|---------|--------|
| 1029 | 1450 | 720 |
| 1053 | 1200 | 110 |
I think the comparison to valid_country
needs to use both ref
and country
:
SELECT e.ref,
AVG(CASE WHEN vc.country IS NOT NULL THEN e.value END) AS average,
SUM(e.volume) AS volume
FROM exchanges e LEFT JOIN
valid_country vc
ON vc.country = e.country AND vc.ref = e.ref
GROUP BY e.ref;
This doesn't matter for your sample data but it might be important for the larger problem.
This query makes use of a subquery to deliver the correct results:
SELECT e1.ref,subq.avg,SUM(volume)
FROM exchanges e1,
(SELECT e2.ref, AVG(value) as avg
FROM exchanges e2, valid_country vc
WHERE e2.country = vc.country
GROUP BY e2.ref) as subq
WHERE e1.ref = subq.ref
GROUP BY ref
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With