2013-10-28 66 views
2

我有users表:MySQL--加入用戶最新級別,沒有任何級別?

id | name 
1 | Mike 

我有rights表,這給我的用戶的一些權利,如:

id | user | elevation | starts  | ends 
1 1  2   1382950736 1383555536 

這裏,我已經升高麥克比2平,在開始1382950736結束於1383555536.在此時間範圍內,用戶是級別2.在其他時間,用戶是級別1.

我有一個查詢來查明用戶的級別:

SELECT IF(`z`.`elevation` IS NULL, 1, `z`.`elevation`) as `elevation`, `users`.`id` 
FROM `users` 
LEFT JOIN (
    SELECT `user`, `elevation` 
    FROM `rights` 
    WHERE (`starts` <= $time) AND (`ends` > $time) 
    GROUP BY `user` 
) as `z` ON `z`.`user` = `users`.`id` 

這是偉大的,完美的作品。但是,對於某個用戶的海拔高度重疊的情況,我有一個問題。

例如:讓我們來想一個簡單的例子,現在是10

我們創建該條目:

id | user | elevation | starts  | ends 
1 1  2   1   15 
2 1  3   5   20 

在這種情況下,這兩個項目符合(`starts` <= $time) AND (`ends` > $time)狀態(當前時間爲10)。我的SELECT查詢在這些情況下的作用是爲我的用戶返回級別2,但他的最新條目是級別3

如何修復我的查詢以返回最新級別,而不是任何級別,以防更多級別重疊

+0

只要是明確的,是'latest'equal到最高'starts'或最高的'id' – Strawberry

+0

@Strawberry:''latest''等於最高的''starts''小於當前時間。 –

+0

SELECT x。* FROM my_table JOIN(SELECT user,MAX(starts)max_starts FROM my_table GROUP BY user)y ON y.user = x.user AND y.max_starts = x.starts; – Strawberry

回答

2
SELECT COALESCE(z.elevation,1) elevation 
    , u.id 
    FROM users u 
    LEFT 
    JOIN 
    (SELECT user 
      , elevation 
     FROM rights x 
     JOIN 
      (SELECT user,MAX(starts) max_starts FROM rights GROUP BY user) y 
      ON y.user = x.user 
      AND y.max_starts = x.starts 
     WHERE '$time' BETWEEN starts AND ends 
    ) z 
    ON z.user = u.id 

明白嗎?

+0

實際上,這不能正常工作。如果某個用戶的MAX('starts')條目在當前時間之後(不是有效),則該查詢不會返回該用戶的特權,但事實上,他應該具有(較舊的)特權。 –

+0

您可能必須在JOIN條件中包含時間約束 - 使用sqlfiddle或至少適當的DDL會更容易。 – Strawberry

0

我無法真正瞭解使用情況背後的邏輯,但爲什麼不使用

order by elevation desc 
limit 1; 
+0

因爲這不起作用,並且因爲您並不總是宣傳用戶。你也可以降級他們。 –

+0

然後通過id desc命令 –

0

如何:

select if(rs.user is null, 1, r.elevation) as elevation, u.id 
from users u 
left outer join rights r on u.id = r.user 
left outer join (
    select user, max(starts) as starts 
    from rights 
    where (starts <= $time) AND (ends > $time) 
    group by user 
) rs on r.user = rs.user and r.starts = rs.starts 
where r.user is null or (r.user is not null and rs.user is not null);