会话<>扫描:获取尚未执行的所有扫描

时间:2012-07-13 21:04:37

标签: mysql sql

我有一个复杂的域结构:

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它(显然现在)不再返回任何内容。

让所有用户会话未连接到扫描的查询是什么?

2 个答案:

答案 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

^在这种情况下我的查询不起作用,需要重写(我知道如何)。