I am trying to teach myself more about SQL at the moment and am currently trying to carry out some simple sales reporting using SUM
, COUNT
, AVG
and GROUP BY
functions within a SQL Server 2008 database. I have managed to get the total, count and average of each group by row.
How do I get the grand total of all the group by rows?
SQL so far:
SELECT
SUM(dbo.tbl_orderitems.mon_orditems_pprice) AS prodTotal,
AVG(dbo.tbl_orderitems.mon_orditems_pprice) AS avgPrice,
count(dbo.tbl_orderitems.uid_orditems_prodid) AS prodQty,
dbo.tbl_orderitems.txt_orditems_pname
FROM
dbo.tbl_orderitems
INNER JOIN
dbo.tbl_orders
ON (dbo.tbl_orderitems.uid_orditems_orderid = dbo.tbl_orders.uid_orders)
WHERE
dbo.tbl_orders.uid_order_webid =
<cfqueryparam cfsqltype="cf_sql_integer" value="#session.webid#">
AND dbo.tbl_orders.txt_order_status =
<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.sale_status#">
GROUP BY
dbo.tbl_orderitems.txt_orditems_pname
Product Qty Gross Avg Westbury Climbing Frame 17 8,023.00 471.94 Sandpoint Deluxe Climbing Frame 34 36,146.00 1,063.12 Roseberry Climbing Frame 9 7,441.00 826.78 Ridgeview Texas Climbing Frame 10 6,990.00 699 Selwood Picnic Table 9 489.92 54.44 I need the Totals of qty column and gross column
Many thanks
Jason
SUM is used with a GROUP BY clause. The aggregate functions summarize the table data. Once the rows are divided into groups, the aggregate functions are applied in order to return just one value per group. It is better to identify each summary row by including the GROUP BY clause in the query resulst.
In order to calculate a subtotal in SQL query, we can use the ROLLUP extension of the GROUP BY statement. The ROLLUP extension allows us to generate hierarchical subtotal rows according to its input columns and it also adds a grand total row to the result set.
The GROUP BY statement is often used with aggregate functions ( COUNT() , MAX() , MIN() , SUM() , AVG() ) to group the result-set by one or more columns.
You are looking for the ROLLUP operator which would add a grand total row at the end of the result set. If you are looking for more complex aggregate totals use ROLLUP or CUBE with the GROUP BY clause, such as the link provided by @MartinSmith or Aggregation WITH ROLLUP
SELECT
SUM(dbo.tbl_orderitems.mon_orditems_pprice) AS prodTotal,
AVG(dbo.tbl_orderitems.mon_orditems_pprice) AS avgPrice,
count(dbo.tbl_orderitems.uid_orditems_prodid) AS prodQty,
dbo.tbl_orderitems.txt_orditems_pname
FROM
dbo.tbl_orderitems
INNER JOIN
dbo.tbl_orders ON (dbo.tbl_orderitems.uid_orditems_orderid = dbo.tbl_orders.uid_orders)
WHERE
dbo.tbl_orders.uid_order_webid = <cfqueryparam cfsqltype="cf_sql_integer" value="#session.webid#">
AND dbo.tbl_orders.txt_order_status = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.sale_status#">
GROUP BY
dbo.tbl_orderitems.txt_orditems_pname
WITH ROLLUP
I know this is an old question, but just for future reference - you can also gain more control over the grouping process by using GROUPING SETS. For example:
SELECT
SUM(dbo.tbl_orderitems.mon_orditems_pprice) AS prodTotal,
AVG(dbo.tbl_orderitems.mon_orditems_pprice) AS avgPrice,
count(dbo.tbl_orderitems.uid_orditems_prodid) AS prodQty,
COALESCE(dbo.tbl_orderitems.txt_orditems_pname, 'TOTAL')
FROM
dbo.tbl_orderitems
INNER JOIN
dbo.tbl_orders
ON (dbo.tbl_orderitems.uid_orditems_orderid = dbo.tbl_orders.uid_orders)
WHERE
dbo.tbl_orders.uid_order_webid =
<cfqueryparam cfsqltype="cf_sql_integer" value="#session.webid#">
AND dbo.tbl_orders.txt_order_status =
<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.sale_status#">
GROUP BY GROUPING SETS (
(dbo.tbl_orderitems.txt_orditems_pname),
()
)
This way the result will have both rows grouped by the txt_orditems_pname, and with no grouping at all. You can specify more grouping sets, ie. a query for average salary in a department and team, with totals for department and the entire company also returned.
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