tags:

views:

92

answers:

2

In a follow-up to a previous question, let's say I have 3 tables, A, B, and C. Table A has an ID which is used as a foreign key on tables B and C, each of which has some value as an attribute. For each ID in table A, I want to get the difference in value between tables B and C, which can be done as follows:

CREATE VIEW T1 AS
    SELECT B.A_ID AS ID, SUM(B.VALUE) AS VAL
    FROM B
    GROUP BY B.A_ID;
CREATE VIEW T2 AS
    SELECT C.A_ID AS ID, SUM(C.VALUE) AS VAL
    FROM C
    GROUP BY C.A_ID;
SELECT T1.ID, T1.VAL, T2.VAL FROM T1, T2 WHERE T1.ID = T2.ID;

The problem is, what if table B has some values for a particular ID, but table C does not, or vice versa. In that case, my select statement will not return that row. Is there a way for me to create a single view, which essentially looks like the following:

CREATE VIEW T3 AS
    SELECT B.A_ID AS ID, SUM(B.VALUE) AS VAL1, SUB(C.VAL) AS VAL2
    FROM B, C
    WHERE B.A_ID = C.A_ID
    GROUP BY B.A_ID;

An example of the creation script for such a view would be appreciated.

+1  A: 

You can use this

CREATE VIEW myView AS
SELECT test_a.id, name, IFNULL( (
  SELECT SUM( value ) 
  FROM test_b
  WHERE test_b.a_id = test_a.id
  GROUP BY test_b.a_id ) , 0
) - IFNULL( (
  SELECT SUM( value ) 
  FROM test_c
  WHERE test_c.a_id = test_a.id
  GROUP BY test_c.a_id ) , 0
)
FROM test_a

But this will result in negative numbers if c has a higher sum than b. If you want the absolute difference than use this:

CREATE VIEW myView AS
SELECT test_a.id, name, ABS( IFNULL( (
  SELECT SUM( value ) 
  FROM test_b
  WHERE test_b.a_id = test_a.id
  GROUP BY test_b.a_id ) , 0 ) - IFNULL( (
SELECT SUM( value ) 
  FROM test_c
  WHERE test_c.a_id = test_a.id
  GROUP BY test_c.a_id ) , 0
  )
)
FROM test_a
Justin Giboney
Considering that both tables B and C have potentially thousands of rows, for hundreds of rows in A, what would the performance of this query be? (I would use the first option, as I need to know if the difference is positive or negative.) Also, is there a way to do this as a view?
Elie
to create a view just addCREATE VIEW viewName AS in front of the query...as far as performance I don't know... you'll have to try it... I just set up three tables with a few rows each.Another issue to consider is if there is an ID in table a that is not in either b or c... my queries will return 0. If you don't want this, there are ways around it.
Justin Giboney
A: 
SELECT ID, MAX(VAL1), MAX(VAL2) FROM 
((SELECT B.A_ID AS ID, SUM(B.VALUE) AS VAL1, 0 as VAL2
FROM B GROUP BY B.A_ID) as T1
UNION
(SELECT C.A_ID AS ID, 0 VAL1, SUM(C.VALUE) AS VAL2
FROM C GROUP BY C.A_ID) as T2) as Foo
GROUP BY FOO.ID

Its a bit hacky. Plus, you can't create a view that has a union.

Jonathan