2011-05-13 75 views
1

我有一個表如下PostgreSQL的循環ID號

|GroupID | UserID | 
-------------------- 
|1  | 1  | 
|1  | 2  | 
|1  | 3  | 
|2  | 1  | 
|2  | 2  | 
|3  | 20  | 
|3  | 30  | 
|5  | 200 | 
|5  | 100 | 

基本上,這樣做是創建該用戶ID獲取有關關聯的「組」,所以,當我想申請一組我可以調用的成員在桌子上。

用戶可以選擇離開組並創建一個新組。

當所有用戶都離開一個組時,我的表中不再有該組ID。

假設這是一個聊天應用程序,用戶可能會經常關閉和開放聊天,羣組ID會很快加起來,但聊天的數量實際上不會達到數百個用戶的數百萬聊天。

我想回收組ID號碼,例如當我插入新記錄時,如果組4未使用(如上所述),它將被分配。

+2

這些ID是代理鍵。沒有人應該看到他們/關心他們的價值觀。留下他們吧。如果您想顯示某些內容並且不喜歡「group345876」或「user9013758235」,請添加對人類可讀顯示名稱的支持。 – Olaf 2011-05-13 16:53:34

+0

我的問題是,9223372036854775807聽起來像一個很大的數字,直到幾年滾動。 – Incognito 2011-05-13 17:28:02

+3

只需停止擔心。如果您獲得10億用戶,並且他們每天每一小時的每秒鐘都會創建一個新ID,則用盡ID將耗時近300年。如果我的數學是正確的。 – Olaf 2011-05-13 17:34:30

回答

3

有很好的理由不這樣做,但在PostgreSQL中非常簡單。該技術 - 使用generate_series()來查找序列中的空位 - 在其他情況下也很有用。

WITH group_id_range AS (
    SELECT generate_series((SELECT MIN(group_id) FROM groups), 
          (SELECT MAX(group_id) FROM groups)) group_id 
) 
SELECT min(gir.group_id) 
FROM group_id_range gir 
LEFT JOIN groups g ON (gir.group_id = g.group_id) 
WHERE g.group_id IS NULL; 

如果沒有間隙或者表「groups」中沒有任何行,那麼該查詢將返回NULL。如果您想使用它來返回下一個組ID號碼,而不管表格「組」的狀態如何,請改用它。

WITH group_id_range AS (
    SELECT generate_series(
         (COALESCE((SELECT MIN(group_id) FROM groups), 1)), 
         (COALESCE((SELECT MAX(group_id) FROM groups), 1)) 
       ) group_id 
) 
SELECT COALESCE(min(gir.group_id), (SELECT MAX(group_id)+1 FROM groups)) 
FROM group_id_range gir 
LEFT JOIN groups g ON (gir.group_id = g.group_id) 
WHERE g.group_id IS NULL;