2011-08-22 97 views
2

我有我已经联合起来,并想加入具有多个列的表几桌。我目前的查询如下:MySQL的观点加入表多行

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 

是否有可能通过某种方式加入做到这一点?显然,我不能在视图上为每个用户输入多个条目。

感谢您的帮助

克雷格。

+0

我应该在发布前添加更多的信息。我将从儿童表中检索性和信息。目前我的tbl_contact_numbers和tbl_alternate_emails被唯一的userID绑定,但我打算在完成脚本后再打开它。所以稍后会有同样的问题。 –

回答

1

你可以结合使用功能GROUP_CONCAT与GROUP BY这一点。 GROUP_CONCAT让我们通过连接它们来聚合列中的值。请注意,这不会为每个孩子提供一列,而是一列包含所有姓名的字符串。

编辑;您的查询将成为类似:

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 
+0

感谢Lex的回复,请参阅我对原文的额外评论。如果这是一个关闭,我会考虑使用concat并在我的PHP脚本中爆炸它。简单地查询我的脚本中的tbl_children可能会更容易。我希望有一个明确的观点,我可以使用网站的范围。在你看来是不可能做到这一点? –

+0

在这种情况下,是的,每次查询tbl_children表可能会更好。 –

0

假设儿童的数量在编写查询时未知(即,用户可以有0,1或5个孩子),使得枢轴这样可能并不是获取数据到前端应用程序的最佳途径。

取决于你如何访问数据,你就要去好不返回每个用户多行,你有或者为每个用户检索的孩子(和电子邮件等),你需要他们。这里的关键是只有在需要时才能检索它们。我相信这在面向对象的世界中被称为延迟加载。

如果你这样做,以填补某种类型的列表框,因此你需要他们为每个用户,那么你可以考虑上,你会找回基于怎样名单上的孩子的数量设置一些限制将出现,然后使用LEFT JOIN s来获取您检索的行的确切数字,而不是为每个用户执行到服务器的往返行程。

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

+0

嗨汤姆,感谢您的评论。 SQL View的原因是仅为所有相关用户数据提供单一参考点。哪些将用于他们的“信息”页面,但广泛用于信息的金块,交叉引用和纳入一些AJAX功能。 我不认为有任何“懒加载”正在进行!我宁愿“从view_my_user中选择数据”,而不是在我的脚本中使用全面的SQL查询来获取一条信息。在我看来,懒加载将是“select * from table”并使用一列? –

+0

最终,我试图通过查询我知道包含所需数据的单个视图来减少“到服务器的往返行程”。 –

+0

问题是,您试图将关系数据库变为非关系型心态。如果您的数据层支持从单个数据库调用返回的分层记录集或多个记录集,那么这可能是要走的路线。我仍然希望只在需要时才能获取数据(或者至少在您需要获取数据时)。 –