mysql - 如何显示 mysql 表中通过单值匹配与另一个表连接的多个条目的数据?

标签 mysql atlassian-crowd

我需要从一对 MySQL 表中选择并显示信息,但语法让我困惑。具体来说,我需要在字段 cwd_user.id == cwd_user_attribute.user_id 上将 cwd_user 表中的数据与 cwd_user_attribute 表中的数据连接起来,但我还需要在一行中显示 cwd_user_attribute 表中多个条目的值。我无法理解的是后者。以下是血淋淋的细节:

给定两个表:

mysql (crowd@prod:crowddb)> desc cwd_user;
+---------------------+--------------+------+-----+---------+-------+
| Field               | Type         | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+-------+
| id                  | bigint(20)   | NO   | PRI | NULL    |       |
| user_name           | varchar(255) | NO   |     | NULL    |       |
| active              | char(1)      | NO   | MUL | NULL    |       |
| created_date        | datetime     | NO   |     | NULL    |       |
| updated_date        | datetime     | NO   |     | NULL    |       |
| display_name        | varchar(255) | YES  |     | NULL    |       |
| directory_id        | bigint(20)   | NO   | MUL | NULL    |       |
+---------------------+--------------+------+-----+---------+-------+


mysql (crowd@prod:crowddb)> desc cwd_user_attribute;
+-----------------------+--------------+------+-----+---------+-------+
| Field                 | Type         | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+-------+
| id                    | bigint(20)   | NO   | PRI | NULL    |       |
| user_id               | bigint(20)   | NO   | MUL | NULL    |       |
| directory_id          | bigint(20)   | NO   | MUL | NULL    |       |
| attribute_name        | varchar(255) | NO   |     | NULL    |       |
| attribute_value       | varchar(255) | YES  |     | NULL    |       |
+-----------------------+--------------+------+-----+---------+-------+

假设 cwd_user_attribute.attribute_name 最多有七个可能的值,我对其中四个感兴趣:lastAuthenticated、Team、Manager Notes。示例:

mysql (crowd@prod:crowddb)> select * from cwd_user_attribute where user_id = (select id from cwd_user where user_name = 'gspinrad');
+---------+---------+--------------+-------------------------+----------------------------------+
| id      | user_id | directory_id | attribute_name          | attribute_value                  |
+---------+---------+--------------+-------------------------+----------------------------------+
|   65788 |   32844 |            1 | invalidPasswordAttempts | 0                                | 
|   65787 |   32844 |            1 | lastAuthenticated       | 1473360428804                    |  
|   65790 |   32844 |            1 | passwordLastChanged     | 1374005378040                    | 
|   65789 |   32844 |            1 | requiresPasswordChange  | false                            | 
| 4292909 |   32844 |            1 | Team                    | Engineering - DevOps             | 
| 4292910 |   32844 |            1 | Manager                 | Matt Karaffa                     |  
| 4292911 |   32844 |            1 | Notes                   | Desk 32:2:11                     | 
+---------+---------+--------------+-------------------------+----------------------------------+
5 rows in set (0.00 sec)

我可以使用此查询获取按lastAuthenticated排序的用户列表:

SELECT cwd_user.user_name, cwd_user.id, cwd_user.display_name, from_unixtime(cwd_user_attribute.attribute_value/1000) as last_login FROM cwd_user JOIN cwd_directory ON cwd_user.directory_id = cwd_directory.id JOIN cwd_user_attribute ON cwd_user.id = cwd_user_attribute.user_id AND cwd_user_attribute.attribute_name='lastAuthenticated' WHERE DATEDIFF((NOW()), (from_unixtime(cwd_user_attribute.attribute_value/1000))) > 90 and cwd_user.active='T' order by last_login limit 4;

结果:

+-----------------------+---------+-----------------------+---------------------+
| user_name             | id      | display_name          | last_login |
+-----------------------+---------+-----------------------+---------------------+
| jenkins-administrator | 1605636 | Jenkins Administrator | 2011-10-27 17:28:05 |
| sonar-administrator   | 1605635 | Sonar Administrator   | 2012-02-06 15:59:59 |
| jfelix                | 1605690 | Joey Felix            | 2012-02-06 19:15:15 |
| kbitters              | 3178497 | Kitty Bitters         | 2013-09-03 10:09:59 |

我需要添加到输出的是 cwd_user_attribute.attribute_value 的值,其中 cwd_user_attribute.attribute_name 是团队、经理和/或注释。输出看起来像这样:

+-----------------------+---------+-----------------------+-------------------------------------------------------------------+
| user_name             | id      | display_name          | last_login          | Team          | Manager      |  Notes       |
+-----------------------+---------+-----------------------+-------------------------------------------------------------------+
| jenkins-administrator | 1605636 | Jenkins Administrator | 2011-10-27 17:28:05 | Internal      | Internal     |              | 
| sonar-administrator   | 1605635 | Sonar Administrator   | 2012-02-06 15:59:59 | Internal      | Internal     |              |
| jfelix                | 1605690 | Joey Felix            | 2012-02-06 19:15:15 | Hardware Eng. | Gary Spinrad | Desk 32:1:51 |
| kbitters              | 3178497 | Kitty Bitters         | 2013-09-03 10:09:59 | Software QA   | Matt Karaffa | Desk 32:2:01 |
+-----------------------+---------+-----------------------+-------------------------------------------------------------------+

最佳答案

您可以通过属性表的附加 LEFT JOIN 来实现该结果。然后使用 GROUP BY 和聚合 CASE 语句来透视结果(行到列)。

SELECT
    cwd_user.user_name,
    cwd_user.id,
    cwd_user.display_name,
    from_unixtime(cwd_user_attribute.attribute_value/1000) as last_login,
    MIN(CASE WHEN attr2.attribute_name = 'TEAM'    THEN attr2.attribute_value END) as Team,
    MIN(CASE WHEN attr2.attribute_name = 'Manager' THEN attr2.attribute_value END) as Manager,
    MIN(CASE WHEN attr2.attribute_name = 'Notes'   THEN attr2.attribute_value END) as Notes
FROM 
    cwd_user 
JOIN 
    cwd_user_attribute ON cwd_user.id = cwd_user_attribute.user_id
                       AND cwd_user_attribute.attribute_name='lastAuthenticated'
LEFT JOIN 
    cwd_user_attribute attr2 ON  cwd_user.id = attr2.user_id
                             AND attr2.attribute_name IN ('Team', 'Manager', 'Notes')
WHERE 
    DATEDIFF((NOW()), (from_unixtime(cwd_user_attribute.attribute_value/1000))) > 90
    AND cwd_user.active = 'T'
GROUP BY 
    cwd_user.id
ORDER BY 
    last_login 
LIMIT 4

使用严格模式,您需要在 GROUP BY 子句中列出所有未聚合的列

GROUP BY 
    cwd_user.user_name,
    cwd_user.id,
    cwd_user.display_name,
    cwd_user_attribute.attribute_value

另一种方法是仅使用三个 LEFT JOIN(每个属性名称一个连接):

SELECT
    cwd_user.user_name,
    cwd_user.id,
    cwd_user.display_name,
    from_unixtime(cwd_user_attribute.attribute_value/1000) as last_login,
    attr_team.attribute_value as Team,
    attr_manager.attribute_value as Manager,
    attr_notes.attribute_value as Notes
FROM cwd_user 
JOIN cwd_user_attribute
  ON  cwd_user.id = cwd_user_attribute.user_id
  AND cwd_user_attribute.attribute_name='lastAuthenticated'
LEFT JOIN cwd_user_attribute attr_team
  ON  cwd_user.id = attr2.user_id
  AND attr2.attribute_name = 'Team'
LEFT JOIN cwd_user_attribute attr_manager
  ON  cwd_user.id = attr2.user_id
  AND attr2.attribute_name = 'Manager'
LEFT JOIN cwd_user_attribute attr_notes
  ON  cwd_user.id = attr2.user_id
  AND attr2.attribute_name = 'Notes'
WHERE DATEDIFF((NOW()), (from_unixtime(cwd_user_attribute.attribute_value/1000))) > 90
  and cwd_user.active='T'
order by last_login limit 4

注意:我已经删除了与目录表的连接,因为您似乎没有使用它。如果您需要它进行过滤,请再次添加。

注释 2:您经常用于搜索的一些属性(例如 lastAuthenticated)应转换为 users 表中的索引列,以提高搜索性能。

关于mysql - 如何显示 mysql 表中通过单值匹配与另一个表连接的多个条目的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39399554/

相关文章:

mysql - 我如何确保 MySQL 正在使用所有可用内存?

c# - 使用 Jira SOAP API 的 PasswordEncoderNotFoundException

php - MySQL 查询标签系统,仅选择使用过的标签

MySQL/RDBMS : Is it okay to index long strings? 它会完成这项工作吗?

php - html 表单选择选项,将 SQL 查询分配给选择上的每个选项

ssl - 使用 SSL 创建 OpenID 提供商

php - 对大表进行简单查询后失去连接

linux - Crowd 和 sonaqube 无法正常工作

single-sign-on - 是否可以使用 CAS 服务器对 Atlassian Crowd 用户进行身份验证?