[英]How do you display data from multiple entries in a mysql table that are JOINED with another via a single value match?
I need to select and display information from a pair of MySQL tables but the syntax eludes me. 我需要从一对MySQL表中选择并显示信息,但是语法使我难以理解。 Specifically, I need to JOIN the data from the cwd_user table with the data from the cwd_user_attribute table on the field cwd_user.id == cwd_user_attribute.user_id, but I also need to display values from several entries in the cwd_user_attribute table in a single line.
具体来说,我需要将cwd_user表中的数据与字段cwd_user.id == cwd_user_attribute.user_id上cwd_user_attribute表中的数据进行联接,但是我还需要在一行中显示cwd_user_attribute表中多个条目的值。 It's the latter that eludes me.
是后者使我难以理解。 Here are the gory details:
这是血腥的细节:
Given two tables: 给定两个表:
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 | |
+-----------------------+--------------+------+-----+---------+-------+
Assume that there are up to seven possible values for cwd_user_attribute.attribute_name and I'm interested in four of them: lastAuthenticated, Team, Manager Notes. 假设cwd_user_attribute.attribute_name最多有七个值,我对其中四个感兴趣:lastAuthenticated,Team,Manager Notes。 Example:
例:
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)
I can get a list of the users sorted by lastAuthenticated with this query: 我可以通过此查询获取按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;
Result: 结果:
+-----------------------+---------+-----------------------+---------------------+
| 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 |
What I need to add to the output is the value of cwd_user_attribute.attribute_value where cwd_user_attribute.attribute_name is Team, Manager, and/or Notes. 我需要添加到输出中的是cwd_user_attribute.attribute_value的值,其中cwd_user_attribute.attribute_name是团队,经理和/或Notes。 The output would look something like this:
输出看起来像这样:
+-----------------------+---------+-----------------------+-------------------------------------------------------------------+
| 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 |
+-----------------------+---------+-----------------------+-------------------------------------------------------------------+
You can achieve that result with an additional LEFT JOIN
with the attribute table. 您可以使用带有属性表的附加
LEFT JOIN
来实现该结果。 Then use GROUP BY
and aggregated CASE
statements to pivot the result (rows to columns). 然后使用
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
With strict mode you would need to list all not aggregated columns in the GROUP BY clause 使用严格模式时,您需要在GROUP BY子句中列出所有未聚合的列
GROUP BY
cwd_user.user_name,
cwd_user.id,
cwd_user.display_name,
cwd_user_attribute.attribute_value
Another way is just to use three LEFT JOINs (one join per attribute name): 另一种方法是只使用三个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
Note: I have removed the join with directory table because you seem not to use it. 注意:因为您似乎不使用它,所以我删除了带目录表的联接。 Add it again, if you need it for filtering.
如果需要进行过滤,请再次添加。
Note 2: Some attributes that you often use for a search (like lastAuthenticated
) should be converted to indexed columns in the users table to improve the search performance. 注意2:应将您经常用于搜索的某些属性(如
lastAuthenticated
)转换为users表中的索引列,以提高搜索性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.