我有一个复杂的域结构:
User: id, name, email
Team: id, name
UserTeam: id, user_id, team_id
Session: id, data
UserSession: id, user_id, session_id
TeamSession: id, team_id, session_id
Scan: id, user_id, session_id, test_data
我可以邀请用户参加“会话”。用户可以进行会话(一个UserSession
),如果完成,结果将存储在Scan
中。我还可以邀请一个完整的团队,因此创建了一个TeamSession
,并为每个团队成员创建UserSession
。
现在我想执行查询:给我所有尚未执行的扫描(所以我记得用户拿一个)。对于这种情况,我想选择所有用户身份并加入扫描,其中扫描ID为NULL
。我认为这是从连接表中找出一行的方法尚不存在。
这是我的疑问:
SELECT us.id as userSessionId,
sc.id as scanId,
s.id as sessionId,
u.id, u.name
FROM usersessions us
LEFT JOIN sessions s ON us.session_id = s.id
LEFT JOIN scans sc ON us.session_id = sc.session_id
LEFT JOIN users u ON us.user_id = u.id
WHERE sc.id IS NULL
GROUP BY us.id
但是,它不起作用:当至少有一个用户尚未执行扫描时,不会返回任何内容。如果我删除WHERE
子句以查看数据是什么,我会回复:
userSessionId scanId sessionId id name
45 45 39 39 John
46 45 39 40 Jane
47 45 39 41 Tom
48 45 39 42 Mark
在这种情况下,所有人都在同一个小组中并得到一个会话(#39)。他们的用户ID和用户会话ID是正确的。马克没有进行过扫描。约翰确实扫描了#45(简为#46,汤姆#47)。
如果我添加where子句WHERE sc.user_id=u.id
,我会得到正确的三个结果(扫描#45,#46和#47)但是Mark丢失了。那是我到底想要抓住的唯一一个!如果你改变它,然后改为两个条款WHERE sc.user_id=u.id AND sc.id IS NULL
它(显然现在)不再返回任何内容。
让所有用户会话未连接到扫描的查询是什么?
答案 0 :(得分:1)
消除查询中的GROUP BY
子句。没有Aggregate函数它是无效的,但在MySQL中,它不会抛出错误并返回“随机”行。使用ORDER BY
对答案进行排序。
SELECT us.id as userSessionId,
sc.id as scanId,
s.id as sessionId,
u.id, u.name
FROM usersessions us
LEFT JOIN sessions s ON us.session_id = s.id
LEFT JOIN users u ON us.user_id = u.id
WHERE us.session_id IS NULL
ORDER BY us.id
答案 1 :(得分:1)
您可以尝试此解决方案。如果它适合您,我将编辑我的帖子以添加解释:
SELECT
a.id AS userSessionId,
b.id AS scanId,
a.session_id AS sessionId,
a.user_id,
c.name
FROM
(
SELECT a.*
FROM usersessions a
LEFT JOIN scans b ON a.user_id = b.user_id AND a.session_id = b.session_id
WHERE b.id IS NULL
) a
INNER JOIN
(
SELECT id, session_id
FROM scans
GROUP BY id, session_id
) b ON a.session_id = b.session_id
INNER JOIN
users c ON a.user_id = c.id
我假设你的数据看起来像这样:
usersessions:
id | uid | session_id
-------------------------
45 | 39 | 39
46 | 40 | 39
47 | 41 | 39
48 | 42 | 39
scans:
id | uid | session_id
-------------------------
45 | 39 | 39
45 | 40 | 39
45 | 41 | 39
在这种情况下,您最终应该:
userSessionId | scanId | sessionId | user_id | name
-----------------------------------------------------------
48 | 45 | 39 | 42 | Mark
如果允许您的扫描表看起来像:
,请告诉我scans:
id | uid | session_id
-------------------------
45 | 39 | 39
45 | 40 | 39
45 | 41 | 39
46 | 39 | 39
46 | 40 | 39
46 | 41 | 39
46 | 42 | 39
^在这种情况下我的查询不起作用,需要重写(我知道如何)。