【问题标题】:GROUP_CONCAT(SELECT * FROM table) is something like this possible?GROUP_CONCAT(SELECT * FROM table) 是这样的可能吗?
【发布时间】:2017-09-27 22:11:04
【问题描述】:

所以我想使用关联表连接两个表,因为表“a”连接到表“b”中的多行,并且我想从每个表中获取与我的 a.value 匹配的所有结果但是表 'b' 中的值应该以某种方式连接起来。

现在我的查询如下所示:

SELECT *, 
    GROUP_CONCAT(DISTINCT g.group_name) group_name, 
    GROUP_CONCAT(DISTINCT g.group_profile_id) group_profile_id, 
    GROUP_CONCAT(DISTINCT g.group_publications) group_publications, 
    GROUP_CONCAT(DISTINCT g.group_followers) group_followers, 
    GROUP_CONCAT(DISTINCT g.group_ongoing_projects) group_ongoing_projects, 
    GROUP_CONCAT(DISTINCT g.group_finished_projects) group_finished_projects, 
    GROUP_CONCAT(DISTINCT g.group_members) group_members 
FROM projects_groups pg 
LEFT JOIN projects p on p.projectid = pg.projectid 
RIGHT JOIN groups g on g.groupid = pg.groupid 
WHERE p.projectid IN ($projectIds) 
GROUP BY p.projectid

问题是我什至没有选择组表的一半列,但我想获得所有列。我可以像上面一样写下所有列,但它看起来真的很丑,而且每次我改变我的表时我都必须修改它。

为了进一步解释项目可以连接到多个组的问题,我想获取项目数据及其组的所有数据。我可以分别查询这些组,但这似乎不合逻辑,因为我必须为每个项目(例如 100 个项目)都这样做。因此,我在一个查询中获取所有项目,然后对每个项目进行查询以获取其组。或者我可以在一个查询中将项目与关联表连接,然后从关联表中获取 id,并使用这些 id 进行第二次查询以通过关联获取所有组,但我正在寻找一种更简单的解决方案。

【问题讨论】:

  • 也不起作用,因为表 a 中的不同行可以连接到表 b 中的同一行,因此它们不是唯一的。
  • 您永远不应该在子表中GROUP BY 列,因为对于任何不匹配的行,该列将是NULL,然后所有不匹配的行将被组合在一起。
  • 要解决必须列出所有列的问题,您可以编写一个存储过程,从INFORMATION_SCHEMA.COLUMNS 动态构建查询。
  • 您确定要使用LEFT JOINRIGHT JOIN 吗?如果project_groups 中的列是外键,它们在主表中应该总是有一个匹配项。
  • 谢谢Barmar,我已经纠正了你指出的错误。从INFORMATION_SCHEMA.COLUMNS 构建查询有点像我想要的。

标签: mysql join group-concat


【解决方案1】:

遗憾的是,这个问题没有包含示例数据或预期结果,但是有一些语法问题值得一提。你从你的 FROM 子句开始:

FROM projects_groups pg 
LEFT JOIN projects p on p.projectid = pg.projectid

即使没有关联的项目,这也允许 projects_groups 中的所有行。如果没有关联的项目,则所有项目。* 列将为 NULL。但是,在 where 子句中,您需要:WHERE p.projectid IN ($projectIds),这意味着项目表中的任何 NULL 都将被忽略,因此 LEFT JOIN 是无用的。

因此,由于项目似乎是主要关注点,请将其与 FROM 一起使用,然后加入适合您需要的其他表。现在我的猜测是你可以有一个没有项目组的项目(即使只是暂时的),所以你可以在这里使用左连接,所以查询可能看起来像这样

FROM projects p
LEFT JOIN  projects_groups pg on p.projectid = pg.projectid
WHERE p.projectid IN ($projectIds)

但请注意,如果您想列出项目,即使它们没有关联的项目组,您也只会这样做。所以假设你确实需要,然后继续这个左连接到组:

FROM projects p
LEFT JOIN  projects_groups pg on p.projectid = pg.projectid
LEFT JOIN groups g on g.groupid = pg.groupid 
WHERE p.projectid IN ($projectIds)

如果假设是错误的,那么使用内连接会更有效:

FROM projects p
INNER JOIN  projects_groups pg on p.projectid = pg.projectid
INNER JOIN groups g on g.groupid = pg.groupid 
WHERE p.projectid IN ($projectIds)

现在我们需要查看 SELECT 和 GROUP BY 子句。 MySQL 历来允许非常非标准的 GROUP BY 语法,默认设置允许像您这样的查询,其中只有一列被列出到 GROUP BY。

例如过去这是允许的:

select p.* from projects p group by p.id

这是非常糟糕的做法,现在 MySQL 的当前版本现在默认使用标准 SQL 语法。根据标准 SQL 语法规则,您必须在 group by 子句中指定每个“非聚合列”。所以上面的例子会产生语法错误

例如您应该始终准确地按列分组

select p.id, p.name, count(*) from projects p group by p.id, p.name

因此,为了帮助避免语法错误,您可能更喜欢使用这样的“派生表”:

SELECT
       p.* 
     , d.*
FROM projects p
INNER JOIN (
        SELECT
            p.projectid 
          , GROUP_CONCAT(DISTINCT g.group_name) group_name
          , GROUP_CONCAT(DISTINCT g.group_profile_id) group_profile_id
          , GROUP_CONCAT(DISTINCT g.group_publications) group_publications
          , GROUP_CONCAT(DISTINCT g.group_followers) group_followers
          , GROUP_CONCAT(DISTINCT g.group_ongoing_projects) group_ongoing_projects
          , GROUP_CONCAT(DISTINCT g.group_finished_projects) group_finished_projects
          , GROUP_CONCAT(DISTINCT g.group_members) group_members
        FROM projects p
        LEFT JOIN  projects_groups pg on p.projectid = pg.projectid
        LEFT JOIN groups g on g.groupid = pg.groupid 
        WHERE p.projectid IN ($projectIds)
        GROUP BY
            p.projectid 
        ) d on p.projectid = d.projectid

【讨论】:

  • 感谢您指出我的错误。您可能已经发现我在编写 mysql 查询方面的经验很少,所以找出我做错了什么总是很棒的。我最初的问题现在似乎毫无意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-20
  • 1970-01-01
  • 2014-12-12
  • 2011-04-06
  • 2014-12-02
  • 1970-01-01
  • 2012-05-07
相关资源
最近更新 更多