Search code examples
sqlsql-serverstringinner-joinaggregate-functions

How to GROUP BY total amount for all items in order in one row


I need to calculate total amount for all items in the order, I used STRING_AGG() but the output divided the amounts in multiple rows.

This is the SELECT statement :

    SELECT b.order_id as 'Order Id',
       string_agg(e.testname,CHAR(13)) as 'Test',
       string_agg(d.PRICE,CHAR(13))  as 'Price',
       string_agg(d.test_vat,CHAR(13))  as '15% Vat',
       sum(convert(float,d.TOTAL_AMOUNT)) as 'Total'
     
  FROM patients a , lab_orders b ,customers c , order_details d , labtests e  
  where a.patient_no = b.patient_no 
  and b.custid = c.custid
  and b.order_id = d.order_id 
  and d.testid = e.testid
  and b.ORDER_ID=2000000272
  
  group by   b.order_id , d.TOTAL_AMOUNT

The output :

Order Id    Test                                 Price       15% Vat        Total
2000000272  (TSH) Free T3 (FT3) Free T4 (FT4)   90 90 90    13.5 13.5 13.5  310.5
2000000272  SGPT(ALT) SGOT (AST)                40 40       6 6             92
2000000272  Patient Time (PT)                   60          9               69

Why the total divided to 3 rows because of GROUP BY how to fix this and show the total for all items 310.5+92+69 = 471.5 in one row only.


Solution

  • Just remove the total amount from the group by clause:

    group by b.order_id --, d.total_amount
    

    This guarantees just one row per order_id, while, on the other hand, having total_amount in the group by clause breaks into a new row for every different value of tuple (order_id, total_amount).

    Side notes:

    • use standard joins! old-school, implicit joins are legacy syntax, that should not be used in new code

    • don't use single quotes for identifiers; use square brackets, or better yet, identifiers that do not require quoting

    • don't store numbers as strings

    So:

    select lo.order_id
        string_agg(lt.testname, char(13))    as Test,
        string_agg(od.price, char(13))       as Price,
        string_agg(od.test_vat, char(13))    as [15% Vat],
        sum(convert(float, od.total_amount)) as Total
    from patients p, 
    inner join lab_orders lo    on p.patient_no = lo.patient_no 
    inner join locustomers c    on lo.custid = c.custid
    inner join order_details od on lo.order_id = od.order_id 
    inner join labtests lt      on od.testid = lt.testid
    where lo.order_id = 2000000272
    group by lo.order_id