简体   繁体   中英

Oracle SQL rows to column with group by and sum

I have a table with the following data.

ID    Name     DiscountGroup Discount DicountCategory
A     XXX      G025          25        MANGMNT
A     XXX      T005           5        HIGH GPA
A     XXX      T010          10        
B     XXXB     G040          40        SOMETXT
B     XXXB     T005           5        HIGH GPA

I want to display the data as

ID    Name     PermanentDiscount Cateogry TempDiscount 
A     XXX      25                MANGMNT  15
B     XXXB     40                SOMETXT   5

ie Permanent and Temporary Discounts in 1 row. All Permanent discount starts with GXXX followed by 3 digits. Similaryly all temporary discount starts with TXXX followed by 3 digits where XXX refers the actual discount. One ID can have multiple temporary discount but only one permanent discount. I tried using

SELECT *
  FROM tableA
PIVOT (
  MAX(Discount) FOR DiscountGroup IN ('')
);

but am not able to figure out the value of in list.

This should work:

WITH sample_data AS 
   ( SELECT 'A' AS id, 'XXX' AS name, 'G025' AS DiscountGroup, 25 AS Discount, 'MANGMNT' AS DiscountCategory FROM DUAL UNION ALL
     SELECT 'A' AS id, 'XXX' AS name, 'T005' AS DiscountGroup, 5 AS Discount, 'HIGH GPA' AS DiscountCategory FROM DUAL UNION ALL
     SELECT 'A' AS id, 'XXX' AS name, 'T010' AS DiscountGroup, 10 AS Discount, NULL AS DiscountCategory FROM DUAL UNION ALL
     SELECT 'B' AS id, 'XXXB' AS name, 'G040' AS DiscountGroup, 40 AS Discount, 'SOMETXT' AS DiscountCategory FROM DUAL UNION ALL
     SELECT 'B' AS id, 'XXXB' AS name, 'T005' AS DiscountGroup, 5 AS Discount, 'HIGH GPA' AS DiscountCategory FROM DUAL
   )
SELECT id,
       name,
       MAX(CASE WHEN DiscountGroup = 'G' THEN Discount ELSE 0 END) AS PermanentDiscount,
       MAX(CASE WHEN DiscountGroup = 'G' THEN Cateogry ELSE NULL END) AS Cateogry,
       SUM(CASE WHEN DiscountGroup = 'T' THEN Discount ELSE 0 END) AS TempDiscount
  FROM ( SELECT id,
                name,
                SUBSTR(DiscountGroup, 1, 1) AS DiscountGroup,
                Discount,
                FIRST_VALUE(DiscountCategory) OVER(PARTITION BY id, name, SUBSTR(DiscountGroup, 1, 1) ORDER BY Discount DESC) AS Cateogry
           FROM sample_data
       )
  GROUP BY id, name
  ORDER BY id, name;

Result:

I NAME PERMANENTDISCOUNT CATEOGRY TEMPDISCOUNT
- ---- ----------------- -------- ------------
A XXX                 25 MANGMNT            15
B XXXB                40 SOMETXT             5

You can add a column with a sum of temporary discounts for each ID/Name, and then filter the rows with permanent discount.

select ID, Name, PermanentDiscount, Cateogry, TempDiscount
from (
    select
        DiscountGroup, ID, Name,
        Discount as PermanentDiscount,
        DicountCategory as Cateogry,
        sum(case when DiscountGroup like 'T%' then Discount else 0 end) over(partition by ID, Name) as TempDiscount
    from table
)
where DiscountGroup like 'G%'
order by ID, Name;

I think It should work for you =>

WITH CTE AS(
SELECT ID,SUM(Discount) TempDiscount
FROM tableA 
WHERE DiscountGroup LIKE 'T%' 
GROUP BY ID )
SELECT a.*,c.TempDiscount FROM
CTE c
INNER JOIN tableA a ON a.ID=c.ID AND a.DiscountGroup LIKE 'G%'

Note: You can check my code here => LINK

i am running this in snowflake.

select id
      ,max(Name)
      ,sum(case when discountgroup like 'G%' then discount else 0 end) Permanentdiscount
      ,max(case when discountgroup like 'G%' then discountcategory end ) category
      ,sum(case when discountgroup like 'T%' then discount else 0 end) Temporarydiscount
from SAMPLE_DATA
      group by id;

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