MySQL视图连接多行的表

时间:2011-08-22 14:23:17

标签: mysql sql join

我有一些表已加入,并希望加入一个包含多列的表。我目前的查询如下:

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,
    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

我把我的整个查询放在了可能有点错误或更清洁的方法。问题在于tbl_children,因为它是“一对多”,它会为用户在tbl_children表中的每个子项为单个用户生成多行。

所以我的结果是:

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

我更愿意:

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

是否可以通过加入某种方式来做到这一点?显然,在视图中每个用户有多个条目是不可接受的。

2 个答案:

答案 0 :(得分:1)

您可以将函数GROUP_CONCAT与GROUP BY结合使用。 GROUP_CONCAT让你通过连接它来聚合列中的值。请注意,这不会为每个子项提供一列,而是为一列提供包含所有名称的字符串。

EDIT;您的查询将变为:

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

答案 1 :(得分:0)

假设在编写查询时孩子的数量是未知的(即,用户可能有0或1或5个孩子),制作这样的支点可能不是获取数据的最佳途径。前端应用程序。

根据您访问数据的方式,您最好每个用户返回多行,或者根据需要为每个用户检索子项(和电子邮件等)。这里的关键是只在需要时检索它们。我相信这在面向对象的世界中被称为延迟加载。

如果您这样做是为了填写某种类型的列表框,因此您需要为每个用户提供这些列表框,那么您可以考虑根据您的列表将如何设置一些限制来检索您将要检索的子项数量出现然后使用LEFT JOIN来获取您检索的行的确切数字,而不是为每个用户执行到服务器的往返。

换句话说,一切都取决于。 :)