什麼情況下需要在間隙和島嶼中計數(x 或 null)?
在這個答案中,Erwin Brandstetter 說:
count(step OR NULL) OVER (ORDER BY date)
是最短的語法,也適用於 Postgres 9.3 或更早版本。count()
只計算非空值。在現代 Postgres 中,更簡潔、等效的語法是:count(step) FILTER (WHERE step) OVER (ORDER BY date)
我不確定為什麼
count(step OR NULL)
是首選。在我的查詢中,我執行以下操作。我在保持語法的同時重命名了我的變數以匹配他的變數。CASE WHEN lag(id_type) OVER (ORDER BY date) <> id_type THEN 1 END AS step
我們正在計算它返回的值。請注意,case 只能返回 1 或 null。
- 如果兩者不相等,則返回 1。
- 如果它們相等,則返回不計入的 null。
歐文的回答是:
這假設涉及的列是**
NOT NULL
**. 否則你需要做更多。所以我更加困惑。添加
count(step OR NULL)
保護我們查詢的內容有什麼意義?任何人都可以打破這一點,並可能展示兩個帶有數據的範例,其中只有一個 - 一個 -
count(x OR NULL)
有效嗎?
據我所知,這都是關於處理
false
notnull
。有程式碼和一些關於香草的背景知識count()
:案例count(x OR NULL)
的關鍵是什麼時候x=false
- **香草
count()
**抓住了錯誤。這將返回 1。SELECT count(x) FROM ( VALUES (false) ) AS t(x);
CASE
fold ,將 false折疊為 null ,與 false 不同,將其count()
排除在外。這將返回 0。SELECT count(x) FROM ( VALUES (CASE WHEN false THEN 1 END) ) AS t(x);
- 短路方法評估
false OR null
,因此null
排除count()
。這將返回 0。SELECT count(x OR NULL) FROM ( VALUES (false) ) AS t(x);
- **
FILTER
**方法,將 x 評估為布爾值。跳過假值和空值,將其他所有內容(真)發送到count()
. 這將返回 0。SELECT count(x) FILTER (WHERE x) FROM ( VALUES (false) ) AS t(x);
結論
在我的範例中,我使用了 method
2
,Erwin 使用 method3
既不是修復也不是更好;既不是更優化也不是更快。
這都是關於 NULL 處理的。該表達式的
lag(id_type) OVER (ORDER BY date) <> id_type
計算結果為布爾值,可以TRUE
是FALSE
或NULL
。如果左操作數或右操作數為 NULL,我們得到 NULL。可以通過多種方式在任一側引入 NULL:
- 沒有上一個(或下一個或相關情況下類似的)行。
- 基礎表中的列可以為 NULL。
- An
OUTER JOIN
引入 NULL(未找到匹配行)。- 涉及一個可以計算為 NULL 的表達式。
有多種方法可以將三值邏輯折疊為兩種情況。
CASE
語句、表達式等。OR
相關答案及詳細資訊:這是所涉及技術的比較,以及(更新的)基準。基本上,它們都執行相同的操作,這是一種廉價的操作。
FILTER
在更新的基準測試中,引入 Postgres 9.4的聚合子句似乎更快一些:沒有案例
wherein only one of them works
,這些技術是可以互換的。確切地計算或求和的內容取決於設置和要求的詳細資訊。在這種情況下,我們只計算TRUE
- 只要基礎表或查詢產生所有非空值(第一行的極端情況有待討論)。而這種情況只需要簡單的比較。相關案例需要更仔細地查看上一個或下一個值。然後提供一個預設值作為
lag()
or的第三個參數可能會派上用場lead()
。