1

我有三张桌子。TB_Main 是一个实体表。TB_BoardMembers 是一个人员表。TB_BoardMembersLINK 是一个桥接表,它通过 id 引用其他两个表,并且还有一个人在实体董事会上的开始和结束日期。这些日期通常不完整。

我被要求作为报告的一部分导出一个 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
4

2 回答 2

2

此查询存在一些问题。主要问题似乎是您缺少将董事会成员链接到链接表的条件,因此您有一个交叉连接,即您将返回每个宽带成员,无论他们的开始/结束日期如何,并假设您有 85 行如果条件匹配,您实际上将返回每个董事会成员 85 次。这突出了从您正在使用的 ANSI 89 隐式连接切换到 ANSI 92 显式连接语法的一个很好的理由。本文重点介绍了进行转换的一些非常好的理由。

因此,您的查询将变为(我不得不猜测您的字段名称):

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)

您为每一行操作该函数两次,并消除在orYEAR上使用索引的任何可能(如果存在)。Aaron Bertrand 再次写了一篇很好的文章,重点介绍了查询日期范围时的良好做法,它针对 SQL-Server,但原理仍然相同,因此您的 where 子句将变为:bml.Startbml.End

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;

SQL Fiddle 示例

于 2013-08-20T08:23:08.600 回答
0

如果您阅读 Group_Concat

“此函数返回一个字符串结果,其中包含来自组的串联非 NULL 值。”

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

我也不确定您的联接,没有真实数据很难解释该部分,因为每个联接都适用于某些数据集,即使它不是编写查询的最佳方式

于 2013-08-20T04:07:23.697 回答