2012-08-14 39 views
0

我有这个查询,很好。我与我的Freetrials和Contacts建立了N:N关系,并与Freetrials和Companies建立了N:1的关系。 Freetrial可以有多个联系人,联系人可能会注册多个Freetrials。 Freetrial只能有1家公司,而且公司可能会注册多个Freetrials。MySQL - 选择不同的单列

SELECT `freetrial`.*,`company`.name as name, `contact`.first_name,`contact`.last_name FROM `contact_freetrial` 
    INNER JOIN `freetrial` ON `contact_freetrial`.freetrial_id=`freetrial`.id 
    INNER JOIN `contact` ON `contact_freetrial`.contact_id=`contact`.id 
    LEFT JOIN `company` ON `company`.id=`freetrial`.company_id 

这个伟大的工程,直到我有2个联系人:

Id Company Contact   Date  
110 MCC  P Sh***  08/14/2012 
110 MCC  W Bu***  08/14/2012 
111 Foo  x yy***  08/14/2012 
112 BAR  y zz***  08/14/2012 

我想,如果有多个联系人,只显示一个单一的公司/ freetrial。所以我基本上只是想它看起来像这样:

Id Company Contact   Date  
110 MCC  P Sh***  08/14/2012 
111 Foo  x yy***  08/14/2012 
112 BAR  y zz***  08/14/2012 

任何帮助,让它这样做将不胜感激。

+0

您是否确实想从联系人表中选择一个联系人?你想选择哪一个? – codingbiz 2012-08-14 18:53:04

+1

你可以只是GROUP BY公司吗? – ficuscr 2012-08-14 18:56:22

回答

2

想法是,你想得到一个随机的联系。然后加入在联系人信息:

select t.*, c.first_name, c.last_name 
from (SELECT `freetrial`.*,`company`.name as name, 
      (select ContactId 
       from Contact where contact.company_id = company.id 
       order by rand() 
       limit 1 
      ) as thecontactid 
     FROM `contact_freetrial` INNER JOIN 
      freetrial` 
      ON `contact_freetrial`.freetrial_id=`freetrial`.id LEFT JOIN 
      `company` ON `company`.id=`freetrial`.company_id 
    ) t join 
    contact c 
    on t.thecontactid = c.contactid 

这将选择使用相关子查询的随机接触。然后它加入这些信息。

使用“group by”方法的问题是mysql不能保证不同的字段来自同一记录。你可能会从一个记录中得到第一个名字,而从另一个记录中得到姓氏。所以,即使它看起来有效,它也不能保证工作。 (这是因为它使用非标准组的语法这一事实。)

+0

我从来没有见过MySQL的GROUP BY使用来自同一个表的不同列值 - 你有参考吗?另外,你是什么意思关于“使用非标准组的语法”?什么不是标准的呢? – newfurniturey 2012-08-14 19:52:45

+0

@newfurniturey。 。 。非标准的是在选择中有没有聚合功能的列。 Mysql对此并不害羞。在http://dev.mysql.com/doc/refman/5.5/en/group-by-hidden-columns.html中明确记录为“隐藏列”。 – 2012-08-14 20:06:06

+0

这实际上是关于标准语法问题的一个很好的解释 - 好的呼叫!在我看来,仍然不值得“这是一个问题”声明,但仍然是一个好的呼叫。 – newfurniturey 2012-08-14 20:09:12

1

您可以使用GROUP BY,如GROUP BY freetrial.id, company.name有由freetrial /公司组合分组的所有结果 - 从而返回只有每freetrial /公司单排:

SELECT 
    `freetrial`.*,`company`.name as name, `contact`.first_name,`contact`.last_name 
FROM 
    `contact_freetrial` 
    INNER JOIN `freetrial` ON `contact_freetrial`.freetrial_id=`freetrial`.id 
    INNER JOIN `contact` ON `contact_freetrial`.contact_id=`contact`.id 
    LEFT JOIN `company` ON `company`.id=`freetrial`.company_id 
GROUP BY 
    freetrial.id, company.name 

作为一个额外的奖金,你可以使用GROUP_CONCAT()获得的列表对于给定的freetrial /公司每接触 - 所有在同一行:

SELECT 
    `freetrial`.*,`company`.name as name, 
    GROUP_CONCAT(CONCAT(contact.first_name, ' ', contact.last_name)) AS contacts 
FROM 
    `contact_freetrial` 
    INNER JOIN `freetrial` ON `contact_freetrial`.freetrial_id=`freetrial`.id 
    INNER JOIN `contact` ON `contact_freetrial`.contact_id=`contact`.id 
    LEFT JOIN `company` ON `company`.id=`freetrial`.company_id 
GROUP BY 
    freetrial.id, company.name 

在这个例子中,我也用CONCAT()合并联系人的姓氏和名字。它将返回的列表将是每个联系人的逗号分隔列表(如果有多个联系人),则针对每个免费联合/公司组合。

0

这会给你最新的联系方式。

SELECT `freetrial`.*,`company`.name as name, `contact`.first_name, 
        `contact`.last_name FROM `contact_freetrial` A 
    INNER JOIN `freetrial` ON `contact_freetrial`.freetrial_id=`freetrial`.id 
    INNER JOIN `contact` ON `A`.contact_id=`contact`.id 
    LEFT JOIN `company` ON `company`.id=`freetrial`.company_id 
where A.id = (select max(id) from contact_freetrial where contact_id = A.id)