MySQL如何透视数据以显示属于多个组的数据库中的用户

时间:2018-02-09 17:39:37

标签: mysql pivot-table

我正在尝试为Modx编写一个导出脚本,以显示属于多个组的成员,我已经做到了这一点:

select u.id, u.username, u.primary_group, mgn.name,
    CASE WHEN mgn.name = 'Administrator' THEN 'TRUE' ELSE 'FALSE' END AS `Administrator`,
    CASE WHEN mgn.name = 'Members' THEN 'TRUE' ELSE 'FALSE' END AS `Members`,
    CASE WHEN mgn.name = 'Privileged Members' THEN 'TRUE' ELSE 'FALSE' END AS `Privileged Members`
from modx_users u
left join modx_member_groups mg on mg.member = u.id
left join modx_membergroup_names mgn on mgn.id = mg.user_group
#where u.username = 'administrator'
#group by u.username
limit 10000;

它确实在查询中将用户组成员身份显示为true或false,但如果用户属于多个组,则查询将返回3行。如果我按条件取消注释组,如果该成员属于多个组,则不会为多个组显示TRUE。

这也非常慢。在大约10,000个用户的数据库上10 ++秒。

如何解决此问题以在单行上显示每个用户(有意导出为CSV)并显示多个组成员身份?

2 个答案:

答案 0 :(得分:1)

要提高性能,您可能需要向表中添加适当的索引。此查询应该执行您正在寻找的内容:

SELECT
  id, username, primary_group,
  CASE MAX(`Administrator`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Administrator`,
  CASE MAX(`Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Members`,
  CASE MAX(`Privileged Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Privileged Members`
FROM (
  SELECT u.id, u.username, u.primary_group,
    CASE WHEN mgn.name = 'Administrator' THEN 1 ELSE 0 END AS `Administrator`,
    CASE WHEN mgn.name = 'Members' THEN 1 ELSE 0 END AS `Members`,
    CASE WHEN mgn.name = 'Privileged Members' THEN 1 ELSE 0 END AS `Privileged Members`
  FROM modx_users u
  LEFT JOIN modx_member_groups mg on mg.member = u.id
  LEFT JOIN modx_membergroup_names mgn on mgn.id = mg.user_group
) z
GROUP BY id, username, primary_group

答案 1 :(得分:0)

这是一个删除额外连接的版本(假设101,102和103分别是管理员,成员和特权成员的ID值),并从分组中删除用户名和primary_group。在所有条件相同的情况下,它应该比原始表现更好一点:

SELECT
  uuu.id,
  uuu.username,
  uuu.primary_group,
  `Administrator`,
  `Members`,
  `Privileged Members`
FROM
  modx_users uuu
  LEFT JOIN
  (
    SELECT
      z.id,
      CASE MAX(`Administrator`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Administrator`,
      CASE MAX(`Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Members`,
      CASE MAX(`Privileged Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Privileged Members`
    FROM
    (
      SELECT u.id,
        CASE WHEN mg.user_group = 101 THEN 1 ELSE 0 END AS `Administrator`,
        CASE WHEN mg.user_group = 102 THEN 1 ELSE 0 END AS `Members`,
        CASE WHEN mg.user_group = 103 THEN 1 ELSE 0 END AS `Privileged Members`
      FROM modx_users u
      LEFT JOIN modx_member_groups mg on mg.member = u.id
    ) z
    GROUP BY z.id
  ) zz on uuu.id=zz.id