MySQL GROUP_CONCAT 返回重复值。无法使用 DISTINCT

Posted

技术标签:

【中文标题】MySQL GROUP_CONCAT 返回重复值。无法使用 DISTINCT【英文标题】:MySQL GROUP_CONCAT returned duplicated values. Can't use DISTINCT 【发布时间】:2016-05-26 14:31:35 【问题描述】:

我正在使用 5 个表进行查询,使用 LEFT JOIN 连接它们并将一些结果与 GROUP_CONCAT 分组。

问题是GROUP_CONCAT 结果在此列中重复:

pedido_lentes
pedidos_lente_quantidades
pedidos_lente_solares
pedido_armacoes
pedidos_armacao_codigos
pedidos_armacao_tipos

这是 SQL 小提琴:http://sqlfiddle.com/#!9/efc27e/2

这里是查询:

SELECT 
pedidos.id_pedido AS id_pedido, lentes, armacao, pedidos.observacao AS observacao, 
valor, pagamento, sinal, parcelas, restante, tipo_pagamento, forma_pagamento, DATE_FORMAT(data, "%e/%m/%Y - %H:%i:%s") AS data, entrega, 
vendedor_pedidos, agendar_servico, 

receitas.receita AS receita,

GROUP_CONCAT(lentes.nome) AS pedido_lentes,
GROUP_CONCAT(pedidos_lentes.quantidade) AS pedidos_lente_quantidades,
GROUP_CONCAT(pedidos_lentes.solar) AS pedidos_lente_solares,

GROUP_CONCAT(armacoes.nome) AS pedido_armacoes,
GROUP_CONCAT(pedidos_armacoes.codigo) AS pedidos_armacao_codigos,
GROUP_CONCAT(pedidos_armacoes.tipo) AS pedidos_armacao_tipos

FROM pedidos 
JOIN receitas ON receitas.id_receita = pedidos.id_receita 

LEFT JOIN pedidos_lentes ON pedidos_lentes.id_pedido = pedidos.id_pedido
LEFT JOIN lentes ON lentes.id_lente = pedidos_lentes.id_lente

left JOIN pedidos_armacoes ON pedidos_armacoes.id_pedido = pedidos.id_pedido
left JOIN armacoes ON armacoes.id_armacao = pedidos_armacoes.id_armacao

WHERE pedidos.id_cliente = 5353 
GROUP BY pedidos.id_pedido
ORDER BY pedidos.data DESC

我的期望:

    | id_pedido |         lentes |          armacao | observacao |  valor | pagamento |  sinal | parcelas | restante | tipo_pagamento | forma_pagamento |                  data | entrega | vendedor_pedidos | agendar_servico |    receita |                                                         pedido_lentes | pedidos_lente_quantidades | pedidos_lente_solares |               pedido_armacoes | pedidos_armacao_codigos | pedidos_armacao_tipos |
    |-----------|----------------|------------------|------------|--------|-----------|--------|----------|----------|----------------|-----------------|-----------------------|---------|------------------|-----------------|------------|-----------------------------------------------------------------------|---------------------------|-----------------------|-------------------------------|-------------------------|-----------------------|
    |      9561 |         (null) |           (null) |      Teste |  20,00 |   à vista |        |        0 |          |       efetuado |        dinheiro | 15/02/2016 - 13:12:05 |  avisar |        webmaster |          (null) | 24/12/2014 | Orma Crizal Easy,Orma Crizal Forte |                 10,3 |               1,0,1,0 | Flair,Blacktop |               2,33 |               1,1 |
    |      7448 | teste de lente | teste de armação |            | 200,00 | parcelado | 100,00 |       10 |    10,00 |     na entrega |            Visa |  8/04/2015 - 11:07:36 |  avisar |        webmaster |          (null) | 24/12/2014 |                                                                (null) |                    (null) |                (null) |                        (null) |                  (null) |                (null) |

【问题讨论】:

请将您的查询和数据复制到网站 为什么不能使用DISTINCT @JoachimIsaksson 因为上面列出的列中的值的数量需要相等。 “它在复制”是什么意思?如果您提供有关您的表架构、示例数据、您获得的结果集以及您尝试获得的结果集的信息,这将非常有帮助。 那么这些字段的示例查询的期望输出是什么?例如,pedidos_armacao_tipos 只有一个不同的值,是否应该给出1,1?如果一个有 3 个而一个有 4 个不同的值,那么在这种情况下,所需的输出是什么?所有字段中的 12 个值,因为这是将所有字段复制相同次数并最终结果的唯一方法...? 【参考方案1】:

DISTINCTGROUP_CONCAT() 中的一个选项:

GROUP_CONCAT(DISTINCT lentes.nome) AS pedido_lentes,
GROUP_CONCAT(DISTINCT pedidos_lentes.quantidade) AS pedidos_lente_quantidades,
GROUP_CONCAT(DISTINCT pedidos_lentes.solar) AS pedidos_lente_solares,

GROUP_CONCAT(DISTINCT armacoes.nome) AS pedido_armacoes,
GROUP_CONCAT(DISTINCT pedidos_armacoes.codigo) AS pedidos_armacao_codigos,
GROUP_CONCAT(DISTINCT pedidos_armacoes.tipo) AS pedidos_armacao_tipos

虽然通常是解决这些问题的最简单方法,但它确实表明由于连接而正在发生笛卡尔积。通常,在进行连接之前预先聚合数据会更有效。

【讨论】:

据我了解,这并不能解决 cmets 中的"Because the numbers of values in the columns listed above need to be equal" @JoachimIsaksson 。 . .实际上,据我了解问题和 cmets,DISTINCT 正是 OP 正在寻找的。​​span> 【参考方案2】:

可以在 GROUP_CONCAT() 聚合函数中包含一些限定符。

你可以说,例如,

  GROUP_CONCAT(DISTINCT lentes.nome ORDER BY lentes.id_lente) AS pedido_lentes

这将从该结果中删除重复的nome 值,并对它们进行可预测的排序。看看这个。 http://sqlfiddle.com/#!9/efc27e/4/0

请注意:您正在滥用对GROUP BY 的邪恶非标准 mysql 扩展。这可能是你麻烦的一部分。请阅读这个。 http://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

【讨论】:

据我了解,这并不能解决 cmets 中的“因为上面列出的列中的值的数量需要相等”。 @JoachimIsaksson 正确。【参考方案3】:

找到解决办法:

SELECT 
pedidos.id_pedido AS id_pedido, lentes, armacao, pedidos.observacao AS observacao, 
valor, pagamento, sinal, parcelas, restante, tipo_pagamento, forma_pagamento, DATE_FORMAT(data, "%e/%m/%Y - %H:%i:%s") AS data, entrega, 
vendedor_pedidos, agendar_servico, 

receitas.receita AS receita,

lentes1.pedido_lentes,
lentes1.pedidos_lente_quantidades,
lentes1.pedidos_lente_solares,

armacoes1.pedido_armacoes,
armacoes1.pedidos_armacao_codigos,
armacoes1.pedidos_armacao_tipos

FROM pedidos 
JOIN receitas ON receitas.id_receita = pedidos.id_receita 


LEFT JOIN (
SELECT
id_pedido,
GROUP_CONCAT(lentes.nome) AS pedido_lentes,
GROUP_CONCAT(pedidos_lentes.quantidade) AS pedidos_lente_quantidades,
GROUP_CONCAT(pedidos_lentes.solar) AS pedidos_lente_solares
FROM pedidos_lentes
JOIN lentes ON lentes.id_lente = pedidos_lentes.id_lente
GROUP BY pedidos_lentes.id_pedido
) lentes1 ON pedidos.id_pedido = lentes1.id_pedido

LEFT JOIN(
SELECT
id_pedido,
GROUP_CONCAT(armacoes.nome) AS pedido_armacoes,
GROUP_CONCAT(pedidos_armacoes.codigo) AS pedidos_armacao_codigos,
GROUP_CONCAT(pedidos_armacoes.tipo) AS pedidos_armacao_tipos
FROM pedidos_armacoes
JOIN armacoes ON armacoes.id_armacao = pedidos_armacoes.id_armacao
GROUP BY pedidos_armacoes.id_pedido
) armacoes1 ON pedidos.id_pedido = armacoes1.id_pedido

WHERE pedidos.id_cliente = 5353 
GROUP BY pedidos.id_pedido
ORDER BY pedidos.data DESC

【讨论】:

以上是关于MySQL GROUP_CONCAT 返回重复值。无法使用 DISTINCT的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 的 GROUP_CONCAT 函数详解

MYSQL 合计每月值加上 group_concat

MySQL:GROUP_CONCAT 中的 DISTINCT 删除相同的值(不重复)

MySQL Group_Concat 按 ID 区分

MySQL使用多个左连接获取重复项

MySQL 使用 GROUP_CONCAT 和多个 JOINS