0

I have the following table:

    Date | Flag|  Val   |  Weight
      1  |  A  |    5   |    2    
      1  |  B  |    5   |    2    
      2  |  A  |    10  |    1     
      3  |  A  |    10  |    1
      3  |  B  |    10  |    1

If I do SUM( val * weight ) / SUM( weight ) grouped by the Flag column, then I will get A: 7.5, B: 6.67. However, this is because the second date has no entry for B. I want to treat this as a zero value. So really I should get A: 7.5, B: 5.

How can I do this is SQL without modifying the table and adding a zero row for B?

qwer
  • 223
  • 4
  • 13

2 Answers2

1

You need to create a frame table. So you have for every date a flag record. Something like

SELECT * FROM (SELECT DISTINCT Date From Table) t1, (SELECT DISTINCT Flag From Table) t2;

Then you can left join with a COALESCE(0) and when you group by you can use count to get the number of records.

Brad Ruderman
  • 2,053
  • 2
  • 15
  • 22
0

Based on Brad answer

You can do something like this:

CREATE TABLE tbValues (`Date` int, `Flag` char, `Val` float, `Weight` float);

INSERT INTO tbValues
    SELECT 1, 'A',  5, 2 UNION
    SELECT 1, 'B',  5, 2 UNION
    SELECT 2, 'A', 10, 1 UNION
    SELECT 3, 'A', 10, 1 UNION
    SELECT 3, 'B', 10, 1 ;

CREATE TABLE tbTemp
as (SELECT * FROM (SELECT DISTINCT Date, Weight From tbValues) t1, (SELECT DISTINCT Flag From tbValues) t2);

And then:

SELECT 
    SUM( IFNULL(V.Val,0) * IFNULL(T.Weight,0) ) / SUM( T.Weight ) 
FROM tbValues V
RIGHT JOIN tbTemp T
    ON V.Date = T.Date
    AND V.Flag = T.Flag
GROUP BY
    T.Flag;

An live example here: SqlFiddle

Community
  • 1
  • 1
Rafael Delboni
  • 817
  • 8
  • 13