So, I have two tables like such:
main_table: property_table:
+----------------------------+ +-------------------------+
| event| property_id | value | | property_id | name |
+----------------------------+ +-------------------------+
| 1 | 1 | 100 | | 1 | property1 |
| 2 | 1 | 200 | | 2 | property2 |
| 3 | 2 | 50 | | 3 | property3 |
| 4 | 3 | 10 | +-------------+-----------+
| 5 | 3 | 30 |
And using the following query:
SELECT pt.name, SUM(value) as subtotal
FROM main_table as mt
LEFT JOIN property_table as pt
ON mt.property_id = pt.property_id
GROUP BY pt.name;
I obtain the following table:
+-------------------------+
| name | subtotal |
---------------------------
| property1 | 300 |
| property2 | 50 |
| property3 | 40 |
Now I would like to add a row to this table which will calculate the total among all properties. But here is the catch, some properties are to be added and some subtracted . So for the sake of argument lets say it is total = property1 - property2 + property3 .
+-------------------------+
| name | subtotal |
---------------------------
| property1 | 300 |
| property2 | 50 |
| property3 | 40 |
| total | 290 |
I now "GROUP BY" can be used with "WITH ROLLUP", but this would exclusively add all the values. I guess you could technically allow negative numbers into the table and solve everything with "WITH ROLLUP", but this seems prone to user error. Is it over the top to avoid the negative integers?
You could use a subquery based on a union all one select for values and one for total
select name, subtotal
from (
SELECT pt.name, SUM(value) as subtotal , 0 ord
FROM main_table as mt
LEFT JOIN property_table as pt ON mt.property_id = pt.property_id
GROUP BY pt.name
union all
SELECT 'Total', SUM(value) , 1
FROM main_table as mt
LEFT JOIN property_table as pt ON mt.property_id = pt.property_id
group by 1
) t
order by ord, name
At the end I found that a case could be implemented inside the SUM when using GROUP BY WITH ROLLUP:
SELECT pt.name,
SUM(
CASE
WHEN pt.name = 'property2' THEN -mt.value
ELSE mt.value
END
) as subtotal
FROM main_table as mt
LEFT JOIN property_table as pt
ON mt.property_id = pt.property_id
GROUP BY pt.name WITH ROLLUP;
But it the actual implementation I choose to add a column called action:
property_table:
+-------------------------+---------+
| property_id | name | action |
+-------------------------+---------+
| 1 | property1 | '+' |
| 2 | property2 | '-' |
| 3 | property3 | '+' |
+-------------+-----------+---------+
And replace the CASE with an IF:
SELECT pt.name,
SUM(IF(pt.action='-', -mt.value, mt.value) as subtotal
FROM main_table as mt
LEFT JOIN property_table as pt
ON mt.property_id = pt.property_id
GROUP BY pt.name WITH ROLLUP;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.