2012-08-14 45 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)