Mysql

如何按行順序獲取缺失值?

  • May 21, 2020

在一個表中,許多行已被刪除,如何獲取下一個缺失行的 id INSERT

例如

id      col1
1       1
3       3
4       4
5       5
8       8
9       9

如何獲得 next 的第一個可用 id 的值INSERT。在這裡我想得到id = 2.

就像是

SELECT id+1 FROM table WHERE CLAUSE // pointing to the least available value
// or x = id +1 (after SELECT)
INSERT INTO table (id, ....) VALUES ('x', ....)

如果該列只是一個代理鍵並且不用於其他目的(顯示排序等),那麼我將只使用您的數據庫的AUTOINCREMENT等效項並忽略 ID 中存在間隙的事實,因為點是唯一的而不是服務於其他目的。備受推薦的“SQL Anti-Patterns”一書中有一章題為“pseudokey quiet-freak”。這取決於您要建模的內容以及當然,如果數字確實具有超出標識符的含義,那麼這一點是無關緊要的。

您想要閱讀的一般概念(值得閱讀一些背景知識,因為這些問題隨處可見,因此知道如何發現它們並有效地處理它們或設計它們非常有用)是gaps 和 island。有很多關於此的線上參考資料(這是快速搜尋發現的第一個,它是在談論 MSSQL,但概念是可以轉移的)。

除了WHERE NOT EXISTS通常建議的方法,因為程式碼讀取的方式使您的意圖更加明顯,您還可以執行以下操作:

SELECT TOP 1 t1.id-1
FROM     yourtable t1
LEFT OUTER JOIN 
        yourtable t2 
ON       t2.id=t1.id-1 -- will match if there is a row with the next ID down from the row in t1
WHERE    t2.id IS NULL -- the next ID down not found
AND      t1.id > 0     -- assume 1 is the lowest valid ID
ORDER BY t1.id

(即 MSSQL 語法,您可能需要對其進行調整)

兩種變體都應產生相似的查詢計劃,因此執行相同,但我已經看到上述方法作為更複雜查詢的一部分錶現更好,因此可能值得嘗試兩者您的情況並驗證哪個表現最佳。

如果表為空,也不是目前提供的任何方法都不會返回第一個 ID:您將不會返回任何行(如果您將其用作子查詢,則返回 NULL)。解決此問題的一種方法是使用“無效”行,id=0但這很髒(您最終不得不從許多其他查詢中過濾掉它),因此強烈建議您改為處理邏輯中的空/NULL。對於在生產中永遠不會為空的表(例如,使用者表,即使在初始安裝時,初始設置/管理員使用者也會有一條記錄),這或當然不是問題。

*編輯:*更正查詢以在未找到時返回第一個 ID,因為 ypercube 指出第一個版本不會這樣做

較新的 mySQL 版本

從這個答案開始,mySQL 和 MariaDB 增加了對視窗函式的支持(分別在版本 8 和 10.2 中),例如LAG()LEAD(). 您可以使用這些來檢查下一行(或上一行)並比較打算增加的值並查看是否存在間隙,這意味著您不需要將表連接到自身或EXISTS為此使用子查詢比較 - 使用正確的索引,這可能是一種更有效的方式來實現一些間隙/孤島查詢。

所有常見的 SQL 數據庫引擎(sqlite、postgres、SQL Server、Oracle 等)現在都支持視窗函式。

引用自:https://dba.stackexchange.com/questions/50016