如何连接多个表?
Posted
技术标签:
【中文标题】如何连接多个表?【英文标题】:How do I join multible tables? 【发布时间】:2009-03-28 19:10:08 【问题描述】:我有以下表格(和示例值):
**user:**
user_id (1, 2, 3)
username (john33, reddiamond...)
password (pass1, pass2...)
**session:**
session_id (4,5, 6)
user_id (1, 2, 3)
**activity**
activity_id (1, 2)
name (running, walking...)
**user_activity**
user_activity_id (1, 2, 3, 4, 5)
session_id (4, 5)
activity_id (1, 2)
所有同名的列都是相关的。在user_activity
表中,有几行描述了会话的活动以及活动指的是用户。
但是我想获取描述用户当前正在做什么的表格:
**result**
username(john33)
activity.name(walking)
获取结果表的SQL语句是什么?
(我正在使用 MSSQL)。
【问题讨论】:
【参考方案1】:SELECT u.username, a.name
FROM user_activity ua
INNER JOIN session s
ON ua.session_id = s.session_id
INNER JOIN user u
ON s.user_id = u.user_id
INNER JOIN activity a
ON ua.activity_id = a.activity_id
【讨论】:
请注意,如果您有多个 user_activity 或 session 记录,那么这将返回所有记录,而不是当前记录,但当前已定义【参考方案2】:我假设 session.session_id
和 user_activity.user_activity_id
是 IDENTITY
列,所以它们是单调递增的。因此它们是唯一的,最大值表示最近的条目。
所以你需要做的是:
将user
与session
中具有最大session_id
值的对应行匹配(即,找不到具有相同user_id
和更大session_id
的其他行)。
然后将session
中的那一行匹配到user_activity
中具有最大user_activity_id
的对应行。
然后将user_activity
中的那一行与activity
中的对应行进行匹配,得到name
。
这是一个应该实现这一点的查询(虽然我还没有测试过):
SELECT u.username, a.name
FROM user u
JOIN session s1 ON (u.user_id = s1.user_id)
LEFT OUTER JOIN session s2 ON (u.user_id = s2.user_id
AND s1.session_id < s2.session_id)
JOIN user_activity ua1 ON (ua1.session_id = s1.session_id)
LEFT OUTER JOIN user_activity ua2 ON (ua2.session_id = s1.session_id
AND ua1.user_activity_id < ua2.user_activity_id)
JOIN activity a ON (a.activity_id = ua1.activity_id)
WHERE s2.session_id IS NULL AND ua2.user_activity_id IS NULL;
这是另一种查询形式,应该得到相同的结果,并且可能更容易可视化:
SELECT u.username, a.name
FROM user u
JOIN session s1 ON (u.user_id = s1.user_id)
JOIN user_activity ua1 ON (ua1.session_id = s1.session_id)
JOIN activity a ON (a.activity_id = ua1.activity_id)
WHERE s1.session_id = (
SELECT MAX(s2.session_id) FROM session s2
WHERE s2.user_id = u.user_id)
AND ua1.user_activity_id = (
SELECT MAX(ua2.user_activity_id) FROM user_activity ua2
WHERE ua2.session_id = s1.session_id);
【讨论】:
+1 为什么需要选择 max(session_id) 不会让最大的 user_activity 记录起作用) @Steve:当然,把逻辑带入问题。 ;-)【参考方案3】:我从您对期望结果的陈述中假设您希望找到每个用户的当前活动。我还假设一个用户可能有很多会话,并且当前会话是具有最高 session_id 的会话。
当然,如果您每个用户只有一个会话,每个用户只有一个 user_activity 记录,那么这不是问题,您接受的答案很好。
这里的关键问题是识别每个用户的最新 user_activity 记录并使用它来访问活动。
这可以通过以下方式完成:-
SELECT u.username,
a.name
FROM user_activity AS ua
JOIN session AS s ON ua.session_id = s.session_id
JOIN user AS u ON u.user_id = s.user_id
JOIN activity AS a ON ua.activity_id = a.activity_id
WHERE ua.user_activity_id IN (
SELECT MAX(ua2.user_activity_id)
FROM user_activity AS ua2
JOIN session AS s2 ON ua2.session_id = s2.session_id
GROUP BY s2.user_id);
以下测试数据证明了 SQL。它创建 4 个用户和 4 个活动,然后为每个做家务的用户创建一个 user_activity 记录。然后它将三个用户设置为正常活动。
INSERT INTO user (username) VALUES ('sneezy');
INSERT INTO user (username) VALUES ('grumpy');
INSERT INTO user (username) VALUES ('happy');
INSERT INTO user (username) VALUES ('snow_white');
INSERT INTO session (user_id) SELECT u.user_id FROM user AS u;
INSERT INTO activity(name) VALUES ("Sneezing");
INSERT INTO activity(name) VALUES ("Frowning");
INSERT INTO activity(name) VALUES ("Smiling");
INSERT INTO activity(name) VALUES ("Housework");
INSERT INTO user_activity (session_id, activity_id)
SELECT s.session_id, a.activity_id
FROM session AS s JOIN activity AS a
WHERE a.name IN ("Housework");
INSERT INTO user_activity(session_id, activity_id)
SELECT s.session_id, a.activity_id
FROM session AS s
JOIN USER as u ON s.user_id = u.user_id
JOIN activity AS a ON a.name = 'Sneezing'
WHERE u.username = 'sneezy' ;
INSERT INTO user_activity(session_id, activity_id)
SELECT s.session_id, a.activity_id
FROM session AS s
JOIN USER as u ON s.user_id = u.user_id
JOIN activity AS a ON a.name = 'Frowning'
WHERE u.username = 'grumpy' ;
INSERT INTO user_activity(session_id, activity_id)
SELECT s.session_id, a.activity_id
FROM session AS s
JOIN USER as u ON s.user_id = u.user_id
JOIN activity AS a ON a.name = 'Smiling'
WHERE u.username = 'happy' ;
这会产生以下结果
snow_white 家务 打喷嚏打喷嚏 脾气暴躁的皱着眉头 快乐微笑【讨论】:
【参考方案4】:我认为会是这样的:
select u.username, a.name
from user u
join session s on u.user_id = s.user_id
join user_activity ua on ua.session_id = s.session_id
join activity a on a.activity_id = ua.activity_id
【讨论】:
【参考方案5】:SELECT user.user_name,
activity.name1
FROM activity
INNER JOIN user
INNER JOIN session
ON user.user_id = session.user_id
INNER JOIN user_activity
ON session.session_id = user_activity.session_id
ON activity.activity_id = user_activity.activity_id
【讨论】:
以上是关于如何连接多个表?的主要内容,如果未能解决你的问题,请参考以下文章