简体   繁体   中英

MySQL joining tables by creating more columns instead of rows

I am mostly new to SQL and ran across a situation that I can't figure out. Say that I have 2 tables: P and A.

 Person      id    Live       Income
 ---------   --    ----       ------
 Tom          1    House      10
 Sarah        2    Apt        7 
 Sterling     3    Playpen    0
 Chris        4    House      6
 Juanita      5    Apt        12
 ...

 Live2       id   Attribute
 ---------   --   -----
 House        1    Job
 House        2    Car
 House        3    Kids
 Apt          4    Job
 Apt          5    Car
 Playpen      6    Diapers

So if you have a 'House' then you always also have a Job, Car, and Kids. If you have a Playpen then you only have Diapers (and never a Job).

What I am trying to do (without double-counting people) is find the total income for 'House' people (Live='House', the 1st category), then 'Job' people (Attribute='Job', 2nd category), then 'Diaper' people, etc. So Tom is counted as a 'House' person but not a 'Job' person (because he has been previously classified and I don't want to double-count income).

Logically I can think of several ways to approach and based on my research this seems to be a perfect place to use the long form of CASE because I can specify conditions from different columns. BUT, I can't seem to join the tables in a way that I don't end up double counting income by creating too many rows. For example, I'll JOIN them and it will create 3 Tom entries (one each for Job, Car, Kids). IMO either we need multiple 'Attribute' columns (one each for Job, Car, Kids, Diapers) so 'Tom' is still fully described on one row or some way to ignore all the other 'Tom' rows once he has been counted in a classification.

without knowing some additional details im guessing this is what you want... table a is the one with the person in it table b has live2 in it

SELECT
    SUM(CASE WHEN live = 'House' THEN income ELSE 0 END) as house,
    SUM(CASE WHEN live = 'Apt' THEN income ELSE 0 END) as apt,
    SUM(CASE WHEN live = 'Playpen' THEN income ELSE 0 END) as playpen
FROM
(   SELECT a.*
    FROM a
    JOIN b ON b.live2 = a.live
    GROUP BY a.id
)t

DEMO what this is assuming is that besides house the only other live is apt that can have a job. if thats the case then this query will do what you want.

If you want to actually specify 'Job' in the query then you can do it like this.

SELECT
    SUM(CASE WHEN live = 'House' THEN income ELSE 0 END) as house,
    SUM(CASE WHEN attribute = 'Job' AND live2 <> 'House' THEN income ELSE 0 END) as apt,
    SUM(CASE WHEN live = 'Playpen' THEN income ELSE 0 END) as playpen
FROM
(   SELECT a.*, b.live2, b.attribute
    FROM a
    JOIN b ON b.live2 = a.live
    GROUP BY a.id
)t

you could also join with each field specified.. if you want an example I can show you

You're question is a bit strange, I'll agree. There isn't any complication since none of your persons live in a house and an apartment...

select live, 
       sum(income) income, 
       count(*) people 
from p 
     left join 
     a 
      on p.live = a.live2 
         and a.attribute = 'job' 
group by live

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