简体   繁体   中英

MySQL How to add a "total" row (with addition and subtraction) to a query result

Problem:

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 .

Expected output:

+-------------------------+
| name         | subtotal |                 
---------------------------
| property1    | 300      |
| property2    |  50      |
| property3    |  40      |
| total        | 290      |

Note:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM