我必须处理以下架构(简化):
LinkedList<LinkedList<Object>> superList = new LinkedList<LinkedList<Object>>();
我希望以最有效的方式获得以下数据:
CREATE TABLE user
(`id` int,
`name` varchar(255),
PRIMARY KEY (id));
CREATE TABLE user_extra
(`user_id` int,
`user_extra_name` varchar(64),
`value` varchar(255),
UNIQUE INDEX user_id_extra_name (user_id, user_extra_name));
INSERT INTO user
(`id`, `name`)
VALUES
(1, 'John Doe'),
(2, 'Don Joe');
INSERT INTO user_extra
(`user_id`, `user_extra_name`, `value`)
VALUES
(1, 'phone', '1234444'),
(1, 'email', 'doe@example.com'),
(2, 'email', 'joe@example.com'),
(1, 'nickname', 'johnny'),
(2, 'nickname', 'donny');
除了电话,电子邮件和昵称外,还会有很多用户和可能更多的额外条目。
我到目前为止所做的是user_extra上的多个左连接:
id name phone email nickname
1 John Doe 1234444 doe@example.com johnny
2 Don Joe (null) joe@example.com donny
有没有更好的方法来解决这个问题?这可能会导致性能问题,因为用户数量增长,或者是否会有十几个这样的左连接?
答案 0 :(得分:1)
由于您发布了简化表架构(没有索引),我无法确定您的查询是否存在任何性能问题。可能如果user.id
是主键并且user_extra.user_id
被编入索引,那么您的查询就相当不错了。
如果您要将user_extra
的复杂索引添加到(user_id,user_extra_name)
,那可能会更好。
但对于小型表而言,只是为了简化阅读此查询,这是另一种方法:
http://sqlfiddle.com/#!9/0ab56b/20
SELECT
u.id, u.name,
ue.phone,
ue.email,
ue.nickname
FROM
user u
LEFT JOIN (
SELECT
user_id,
MAX(IF(user_extra_name = 'phone',`value`,null)) AS phone,
MAX(IF(user_extra_name = 'email',`value`,null)) AS email,
MAX(IF(user_extra_name = 'nickname',`value`,null)) AS nickname
FROM user_extra
GROUP BY user_id
) ue
ON
ue.user_id = u.id
但实际上,如果您的桌子上有索引,我相信您的查询很好。
答案 1 :(得分:1)
问题归结为你 - 你是否注意到你的应用程序因为这段SQL而出现瓶颈?
Alex的答案是一个很好的方法,但如果您想使用CASE
,那么这样的解决方案可能很适合您!它只需要一个LEFT JOIN
:
SELECT
u.id, u.name,
(CASE WHEN uextra.user_extra_name = 'phone' THEN uextra.value ELSE null END) AS phone,
(CASE WHEN uextra.user_extra_name = 'email' THEN uextra.value ELSE null END) AS email,
(CASE WHEN uextra.user_extra_name = 'nickname' THEN uextra.value ELSE null END) AS nickname
FROM
user u
LEFT JOIN
user_extra AS uextra
ON
uextra.user_id = u.id
GROUP BY
u.name
ORDER BY
u.id
ASC
http://sqlfiddle.com/#!9/0ab56b/28
对索引的了解不多。