开发者

MySQL view joining table with multiple rows

I have a few tables which I have joined together and would like to join a table that has multiple columns. My current query is as follows:

select
    usrs.firstname, usrs.middleNames, usrs.surname,
    if (usrs.sex=0,'Male','Female') as sex,
    usrs.DOB,
   (YEAR(CURDATE())-YEAR(usrs.DOB)) - (RIGHT(C开发者_运维技巧URDATE(),5)<RIGHT(usrs.DOB,5)) AS age,
    birth.townName AS 'birthTown', birth.regionName AS 'birthRegion', birth.countryName AS 'birthCountry',
    location.townName AS 'curTown', location.regionName AS 'curRegion', location.countryName AS 'curCountry',
    usrs.email, emails.email AS 'alternateEmail',
    numbers.number,
    usrs.website,
    usrs.aboutMe,
    family.mother, family.father, family.partner, marital.status, family.aboutFamily,
    children.name AS 'childsName'
from ch09.tbl_users usrs
LEFT JOIN vw_town_region_country birth ON birth.townID = usrs.birthPlace
LEFT JOIN vw_town_region_country location ON location.townID = usrs.currentLocation
LEFT JOIN tbl_alternate_emails emails ON emails.userID = usrs.id
LEFT JOIN tbl_contact_numbers numbers ON numbers.userID = usrs.id
LEFT JOIN tbl_family family ON family.userID = usrs.id
LEFT JOIN tbl_marital_status marital ON family.maritalStatusID = marital.id
LEFT JOIN tbl_children children ON family.id = children.familyID

I put my whole query it might be a bit wrong or cleaner way to do it. The issue is with the tbl_children, as it is "one to many" it results in multiple rows for a single user for every child that user has in the tbl_children table.

So my results are:

userID:1 firstName middleNames surname ....... childsName
userID:1 firstName middleNames surname ....... childsName
userID:1 firstName middleNames surname ....... childsName

I would prefer:

userID:1 firstName middleNames surname ....... childsName childsName2 childsName3

Is it possible to do this through a Join somehow? Obviously it isn't acceptable for me to have multiple entries per user on the view.


You could use the function GROUP_CONCAT in combination with GROUP BY for this. GROUP_CONCAT let's you aggregate values from a column by concatenating them. Note that this will not give you a column for every child, but one column with a string containing all the names.

EDIT; your query would become something like:

select
    usrs.firstname, usrs.middleNames, usrs.surname,
    if (usrs.sex=0,'Male','Female') as sex,
    usrs.DOB,    (YEAR(CURDATE())-YEAR(usrs.DOB)) - (RIGHT(CURDATE(),5)<RIGHT(usrs.DOB,5)) AS age,
    birth.townName AS 'birthTown', birth.regionName AS 'birthRegion', birth.countryName AS 'birthCountry',
    location.townName AS 'curTown', location.regionName AS 'curRegion', location.countryName AS 'curCountry',
    usrs.email, emails.email AS 'alternateEmail',
    numbers.number,
    usrs.website,
    usrs.aboutMe,
    family.mother, family.father, family.partner, marital.status, family.aboutFamily,
    GROUP_CONCAT(children.name SEPERATOR ",") AS 'childsName' 
FROM ch09.tbl_users usrs 
LEFT JOIN vw_town_region_country birth ON birth.townID = usrs.birthPlace 
LEFT JOIN vw_town_region_country location ON location.townID = usrs.currentLocation
LEFT JOIN tbl_alternate_emails emails ON emails.userID = usrs.id 
LEFT JOIN tbl_contact_numbers numbers ON numbers.userID = usrs.id 
LEFT JOIN tbl_family family ON family.userID = usrs.id 
LEFT JOIN tbl_marital_status marital ON family.maritalStatusID = marital.id 
LEFT JOIN tbl_children children ON family.id = children.familyID 
GROUP BY userID


Assuming that the number of children is unknown at the time of writing the query (i.e., a user could have 0 or 1 or 5 children), making a pivot like this probably isn't the best route for getting data into a front end application.

Depending on how you're accessing the data, you're better off either returning multiple rows per user as you have or retrieving the children (and emails, etc.) for each user as you need them. The key here is to only retrieve them if you need them. I believe that this is known as Lazy Loading in the Object Oriented world.

If you're doing this to fill a list box of some kind, and therefore you need them for each user, then you might consider setting some limit on the number of children that you'll retrieve based on how your list will appear and then use LEFT JOINs to get exactly that number for the rows that you retrieve, rather than doing the round trip to the server for every user.

In other words, it all depends. :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜