使用GROUP_CONCAT()打包Tri-INNER JOIN-Relation的重复值

时间:2018-02-12 16:32:04

标签: mysql sql

我应该得到以下一行

[id -              gamma             -              omega            ]
[1  - Gamma1, Gamma2, Gamma3, Gamma4 - Omega1, Omega2, Omega3, Omega4]

但我得到了SQLFiddle

上显示的结果

如果我删除了SET并保留了GROUP_CONCAT(),那么它可以正常运行。

为什么关系会相互影响并产生重复的值?

SQL:

SELECT a.id, 
       GROUP_CONCAT(g.name) AS gamma, 
       GROUP_CONCAT(o.name) AS omega 
FROM alpha a

     #SET A.O.
     INNER JOIN alpha_omega ao ON ao.alpha_id = a.id 
     INNER JOIN omega o ON o.id = ao.omega_id 

     #SET A.G.
     INNER JOIN alpha_gamma ag ON ag.alpha_id = a.id 
     INNER JOIN gamma g ON g.id = ag.gamma_id

WHERE a.id = 1
GROUP BY a.id

3 个答案:

答案 0 :(得分:2)

可能是正确的连接(不使用GROUP_CONCAT(DISTINCT ...)):

SELECT a.id, GROUP_CONCAT(o.name) AS omega  
FROM alpha a
JOIN delta d ON d.alpha_id = a.id 
JOIN omega o ON o.id = d.omega_id 
GROUP BY a.id
UNION ALL
SELECT a.id, GROUP_CONCAT(g.name) AS gamma
FROM alpha a
JOIN beta b ON b.alpha_id = a.id 
JOIN gamma g ON g.id = b.gamma_id
GROUP BY a.id;

并在一行内:

SELECT id, MIN(gamma) AS gamma, MIN(omega) AS omega
FROM (
SELECT a.id, NULL AS gamma, GROUP_CONCAT(o.name ORDER BY o.name) AS omega  
  FROM alpha a
  JOIN delta d ON d.alpha_id = a.id 
  JOIN omega o ON o.id = d.omega_id
  GROUP BY a.id
  UNION ALL
  SELECT a.id, GROUP_CONCAT(g.name ORDER BY g.name) AS gamma, NULL
  FROM alpha a
  JOIN beta b ON b.alpha_id = a.id 
  JOIN gamma g ON g.id = b.gamma_id
  GROUP BY a.id
) sub
GROUP BY id;

<强> SQL Fiddle Demo

答案 1 :(得分:1)

您的查询包含两个&#34;分支&#34; (gamma和omega):如果你group by树的两个分支中from分开{并且你不再有重复问题,那么这个逻辑就更好了:

select a.id,
       g.names as gamma,
       o.names as omega
  from alpha a
       join ( select ao.alpha_id,
                     group_concat(o.name) as names
                from alpha_omega ao
                     join omega o on o.id = ao.omega_id
               group by ao.alpha_id ) o on o.alpha_id = a.id
       join ( select ag.alpha_id,
                     group_concat(g.name) as names
                from alpha_gamma ag
                     join gamma g on g.id = ag.gamma_id
               group by ag.alpha_id ) g on g.alpha_id = a.id
 where a.id = 1

请注意,在实际操作中,您需要分别在两个子查询中重复where alpha_id = 1过滤器(如果查询计划程序发现它没有&#39,那么非常会感到惊讶; t需要读取子查询中的所有表而不需要额外的where)。

或者,聚合函数支持您的用例distinct

SELECT a.id, 
       GROUP_CONCAT(distinct g.name) AS gamma, 
       GROUP_CONCAT(distinct o.name) AS omega 
  FROM ...

答案 2 :(得分:0)

你有重复的原因是因为alpha和gamma之间以及alpha和omega之间存在多对多的关系。因此,关联表的某些列中的重复项将在连接后传输到最终结果。

要在聚合期间删除重复项,请向group_concat函数添加distinct:

SELECT a.id, 
GROUP_CONCAT(DISTINCT g.name) AS gamma, 
GROUP_CONCAT( DISTINCT o.name) AS omega 

FROM alpha a

#SET D.O.
INNER JOIN delta d ON d.alpha_id = a.id 
INNER JOIN omega o ON o.id = d.omega_id 

#SET B.G.
INNER JOIN beta b ON b.alpha_id = a.id 
INNER JOIN gamma g ON g.id = b.gamma_id;

有关详细信息,请参阅MySQL GROUP_CONCAT Function