2012-07-13 90 views
1

我有一個複雜的域結構:會話<>掃描:獲取所有掃描還未執行

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是正確的。 Mark尚未執行掃描。約翰確實掃描了#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

因此,我假設'掃描'表中的'id'字段不是自動遞增的(可以重複),而且這些列在'id - > user_id - > session_id'的組合中是正確的?每個會話可以有多個掃描嗎? – 2012-07-13 21:51:11

+0

掃描ID是自動增量的,如果每個會話有多個用戶,則每個會話只有*多個掃描。與一個用戶的會話有一個用戶會話和一個掃描。 – 2012-07-13 22:09:54

+0

好的,一個用戶會話可以存在,但沒有相應的'掃描',並且你想要那些沒有相應掃描的用戶職位(不完整) - 以及與之不一致的scanid是否正確? – 2012-07-13 22:15:09

回答

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 

^在這種情況下,我的查詢不起作用,需要重寫(我知道如何)。

+0

這幾乎可以工作!唯一的修改是有一個掃描PER用戶。所以你的第一個假設是正確的,除了掃描ID也是自動遞增的,就像用戶會話一樣。但是,現在我只用馬克的名字回來了,所以我按用戶會話ID分組,並且據我現在看到的,這可以工作。 – 2012-07-14 08:09:40

+1

@JurianSluiman,只需在FROM子句中選擇子查詢,然後單獨使用它。它應該爲每個用戶會話提供一行,因此您不必使用「GROUP BY」使行不同。我的印象是你也想要他們失蹤的'scanid'。當然,如果你還需要用戶名,只需在'users'表中添加一個連接即可。 – 2012-07-14 08:13:41

1

消除查詢中的GROUP BY子句。如果沒有聚合函數,它是無效的,但在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 
+0

感謝您的回覆。不幸的是,這也返回null。如果我刪除WHERE子句來查看所有結果,它看起來像這樣:http://juriansluiman.nl/caps/96411e.png。我真的迷失在這裏,因爲我認真地不期待這樣的結果... – 2012-07-13 22:12:25

+0

@JurianSluiman在我看來你的結果,它應該返回NULL,因爲你的所有usersessions記錄都有一個有效的scan_id。你可以嘗試檢查'us.session_id是否爲NULL'並且消除'LEFT JOIN'(我將更新我的答案)。 – 2012-07-13 22:17:47

+0

@JurianSluiman,你的數據結構需要一些規範化。使用當前結構可能無法獲得您所需的內容。考慮將'scan_id'添加到'UserSession'並從'Scan'表中刪除'user_id,session_id'。 (我假設沒有用戶會話掃描不能存在。) – 2012-07-13 22:25:01