Re: aggregate / group by question - Mailing list pgsql-sql

From T E Schmitz
Subject Re: aggregate / group by question
Date
Msg-id 421DADC3.20208@numerixtechnology.de
Whole thread Raw
In response to Re: aggregate / group by question  (Keith Worthington <KeithW@NarrowPathInc.com>)
List pgsql-sql
Hello Keith,
Thank you for your help.

Keith Worthington wrote:
> T E Schmitz wrote:
>> Tables:
>>
>> TRANSAKTION
>> -----------
>> KIND ('R' or 'S' for refund or sale)
>> TRANSAKTION_PK
>> PAYMENT_METHOD (cheque, cash, CC)
>>
>> ITEM
>> ----
>> TRANSAKTION_FK
>> ITEM_PK
>> RETAIL_PRICE
>> DISCOUNT
>>
>> Desired result set:
>>
>> PAYMENT_METHOD | category | SUBTOTAL
>> ------------------------------------
>> Cash           | sales    | 103,55
>> Cash           | discounts|  -0,53
>> Cash           | refunds  | -20,99
>> CC             | sales    | 203,55
>> CC             | discounts|  -5,53
>> CC             | refunds  | -25,99
>>
>> where
>> sales amount is the sum of RETAIL_PRICE
>> discount amount is the sum of DISCOUNT
>> refunds is the sum of (RETAIL_PRICE-DISCOUNT)
>>
>>
> Your comment implies that the amount of retail sales is the sum of all 
> amounts regardless of whether or not discount IS NULL.  So perhaps 

correct

> losing the 'IS NULL' from you retail_price case may fix your statement.  

no

> This may be a bit heavy handed AND I am still a novice 

that makes two of us ;-)

It worked after a couple of minor changes!
I didn't realize that the select_list can be "made up" from a sub-select.

> SELECT merged_data.payment_method,
>       merged_data.category,
>       merged_data.subtotal
>  FROM (
> --       Get the refunds.  (kind = 'R')
>         SELECT transaktion.payment_method,
          SELECT transaktion.payment_method as payment_method,

>                'refunds' AS category,
>                -1 * sum( item.retail_price - COALESCE(item.discount) ) 
> AS subtotal
>           FROM transaktion
>           LEFT OUTER JOIN item
>             ON ( transaktion.transaktion_pk = item.transaktion_fk )
>          WHERE transaktion.kind = 'R'
>          GROUP BY transaktion.payment_method
>         UNION ALL
> --       Get the sales.  (kind = 'S')
>         SELECT transaktion.payment_method,
>                'sales' AS category,
>                sum( item.retail_price - COALESCE(item.discount, 0) ) AS 
> subtotal
           sum( item.retail_price ) AS subtotal


>           FROM transaktion
>           LEFT OUTER JOIN item
>             ON ( transaktion.transaktion_pk = item.transaktion_fk )
>          WHERE transaktion.kind = 'S'
>          GROUP BY transaktion.payment_method
>         UNION ALL
> --         Get the discounts.  (kind = 'S' AND discount IS NOT NULL)
>         SELECT transaktion.payment_method,
>                'discounts' AS category,
>                -1 * sum( COALESCE(item.discount, 0) ) AS subtotal
>           FROM transaktion
>           LEFT OUTER JOIN item
>             ON ( transaktion.transaktion_pk = item.transaktion_fk )
>          WHERE transaktion.kind = 'S'
>            AND transaktion.discount IS NOT NULL
>          GROUP BY transaktion.payment_method
>       ) AS merged_data
> ORDER BY merged_data.payment_method,
>          merged_data.category;

---------------------------------------------

In the meantime I had come up with a solution, too - I compared the two 
queries with EXPLAIN ANALYZE and my one takes about 4x longer. I haven't 
got much data in the test DB yet but the over time the amount of 
TRANSAKTIONs, which are never deleted, will be huge:

Here's my version (to reduce complexity I had omitted some details such 
as TRANSAKTION.THE_TIME" and ITEM.QUANTITY

select distinct  METHOD,

case
when KIND ='R' then 'REFUND'
when KIND ='S' and DISCOUNT is  null then 'SALES'
when KIND ='S' and DISCOUNT is not  null  then 'DISCOUNT'
end as CATEGORY,

(select
sum(
case
when TRANSAKTION.KIND ='R' then 
(-(S.RETAIL_PRICE-coalesce(S.DISCOUNT,0))*S.QUANTITY)
when TRANSAKTION.KIND ='S' and ITEM.DISCOUNT is  null then 
(S.RETAIL_PRICE*S.QUANTITY)
when TRANSAKTION.KIND ='S' and ITEM.DISCOUNT is not  null  then 
(-S.DISCOUNT*S.QUANTITY)
end
)
from ITEM S
inner join TRANSAKTION  T  on T.TRANSAKTION_PK =S.TRANSAKTION_FK
where
T.THE_TIME >= '1999-01-08' and T.THE_TIME < '2005-02-19' -- this Z-Report
and T.METHOD = TRANSAKTION.METHOD
and T.KIND=TRANSAKTION.KIND
)
as SUBTOTAL

from ITEM
inner join TRANSAKTION  on TRANSAKTION_PK =TRANSAKTION_FK
where THE_TIME >= '1999-01-08' and THE_TIME < '2005-02-19'
group by METHOD,KIND,DISCOUNT,QUANTITY
order by METHOD, CATEGORY

-- 


Regards/Gruß,

Tarlika Elisabeth Schmitz


pgsql-sql by date:

Previous
From: KÖPFERL Robert
Date:
Subject: Re: Junk queries with variables?
Next
From: Sean Davis
Date:
Subject: Re: Software for database-visualisation