2013-08-20 48 views
1

我有三個表。 TB_Main是一個實體表。 TB_BoardMembers是人物表。 TB_BoardMembersLINK是一個橋接表,它通過ID引用其他兩個表,並且具有一個Person在一個實體的板上時的開始和結束日期。這些日期通常不完整。使用GROUP_CONCAT

我被要求將一個CSV格式的報表作爲報表的一部分導出,每個實體每年一行,其中我有一個當年的董事會成員名單,他們的職業是由換行符分隔的單個字段中。

我不需要結果中的bml.Entity,但添加它來嘗試調試。我得到了一行,我期望85.試圖有和沒有GROUP BY和結果是相同的事實表明我濫用GROUP_CONCAT。我應該如何構建這個來獲得他們想要的結果?

SELECT 
GROUP_CONCAT(
DISTINCT CONCAT(bm.First, ' ', bm.Last, 
IF (bm.Occupation != '', ' - ', ''), 
bm.Occupation) SEPARATOR "\n") as Board, 
bml.Entity 
FROM 
TB_Main arfe, 
TB_BoardMembers bm, 
TB_BoardMembersLINK bml 
WHERE YEAR(bml.start) <= 2011 
AND (YEAR(bml.end) >= 2011 OR bml.end IS NULL) 
AND bml.start > 0 
AND bml.Entity = arfe.ID 
GROUP BY bml.Entity 
ORDER BY Board 
+2

恕我直言,這個問題是不是'GROUP_CONCAT'而是不當連接。 – peterm

回答

2

有這個查詢有幾個問題。主要問題似乎是你沒有把董事會成員鏈接到鏈接表的條件,所以你有一個交叉連接,即你將返回每個寬帶成員,無論他們的開始/結束日期,並假設你有85行在標準匹配的情況下,您將實際返回每位董事會成員85次。這突出了從您正在使用的ANSI 89隱式連接切換到ANSI 92顯式連接語法的非常好的理由。 This article突出顯示了一些非常好的理由來使交換機。

所以,你的查詢將成爲(我已經在你的字段名猜測):

SELECT * 
FROM TB_Main arfe 
     INNER JOIN TB_BoardMembersLINK bml 
      ON bml.Entity = arfe.ID 
     INNER JOIN TB_BoardMembers bm 
      ON bm.ID = bml.BoardMemberID 

我注意到了有關查詢接下來的事情是,在WHERE子句中使用的功能是不是非常有效所有的,所以因爲這樣:

WHERE YEAR(bml.start) <= 2011 
AND  (YEAR(bml.end) >= 2011 OR bml.end IS NULL) 

您在操作YEAR函數兩次每一行,並在bml.Startbml.End移除使用索引的任何可能的機會(如果有的話)。再次阿龍貝特朗寫a nice article查詢日期範圍時突出良好做法,它是目標在SQL-Server中,但原則仍然是相同的,所以你的where子句將成爲:

WHERE bml.Start <= '20110101' 
AND  (bml.End >= '20110101' OR bml.End IS NULL) 
AND  bml.start > 0 

你最終的查詢應該再是:

SELECT bml.Entity, 
     GROUP_CONCAT(DISTINCT CONCAT(bm.First, ' ', bm.Last, 
      IF (bm.Occupation != '', ' - ', ''), bm.Occupation) 
      SEPARATOR "\n") as Board 
FROM TB_Main arfe 
     INNER JOIN TB_BoardMembersLINK bml 
      ON bml.Entity = arfe.ID 
     INNER JOIN TB_BoardMembers bm 
      ON bm.ID = bml.BoardMemberID 
WHERE bml.Start <= '20110101' 
AND  (bml.End >= '20110101' OR bml.End IS NULL) 
AND  bml.start > 0 
GROUP BY bml.Entity 
ORDER BY Board; 

Example on SQL Fiddle

+0

謝謝你提供這樣一個很好的解釋!我喜歡StackOverflow,因爲這樣的課程! – jerrygarciuh

0

如果您在GROUP_CONCAT

讀了「該函數返回從一組連鎖的非NULL值的字符串結果。」

在這種情況下,這個組似乎只是一個組,如你所說只有一個實體?我不確定您的描述是否屬於這種情況。你爲什麼不通過名字,姓氏和職業進行分組,這可能會給你所有的成員。

我也不能確定你的加入,沒有真正的數據其很難解釋的部分爲每一段組數據連接工作正常,即使它不是最好的方法編寫一個查詢