2013-08-20 26 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值的字符串结果。”

在这种情况下,这个组似乎只是一个组,如你所说只有一个实体?我不确定您的描述是否属于这种情况。你为什么不通过名字,姓氏和职业进行分组,这可能会给你所有的成员。

我也不能确定你的加入,没有真正的数据其很难解释的部分为每一段组数据连接工作正常,即使它不是最好的方法编写一个查询