2008-10-27 63 views
39

我有一個表有一個processed_timestamp列 - 如果一個記錄已被處理,那麼該字段包含它被處理的日期時間,否則它是空的。如何返回由NULL和NOT NULL分組的記錄?

我想寫一個返回兩行的查詢:

NULL  xx -- count of records with null timestamps 
NOT NULL yy -- count of records with non-null timestamps 

這可能嗎?

更新:表格很大,所以效率很重要。我可以運行兩個查詢來分別計算每個總數,但如果我可以避免的話,我想避免兩次查詢表。

回答

18

甲骨文:

組由NVL2(字段, 'NOT NULL', 'NULL')

42

在MySQL中,你可以做類似

SELECT 
    IF(ISNULL(processed_timestamp), 'NULL', 'NOT NULL') as myfield, 
    COUNT(*) 
FROM mytable 
GROUP BY myfield 
+0

這是真棒,我要玩的IF條件的一些更多 – 2014-04-11 17:31:17

+0

MySQL的最佳答案。 – marijnz0r 2015-04-17 09:57:07

5

如果它是甲骨文,那麼你可以這樣做:

select decode(field,NULL,'NULL','NOT NULL'), count(*) 
from table 
group by decode(field,NULL,'NULL','NOT NULL'); 

我敢肯定,其他的DB允許類似的伎倆。

20

嘗試以下,這是供應商中立的:

select 
    'null ' as type, 
    count(*) as quant 
    from  tbl 
    where  tmstmp is null 
union all 
select 
    'not null' as type, 
    count(*) as quant 
    from  tbl 
    where  tmstmp is not null 

有我們本地DB2大師看在這之後,他同意:沒有提交日期(包括本文)的解決方案,可避免全表掃描(如果時間戳未編入索引,或者其他索引不匹配)。他們全部掃描表中的每個記錄一次。

所有CASE/IF/NVL2()解決方案對每行都進行空字符串轉換,從而在DBMS上引入不必要的負載。這個解決方案沒有這個問題。

+0

這是一張非常大的桌子 - 打了兩次這樣效率很低,不是嗎? – 2008-10-27 10:55:32

+0

不,實際上(至少在DB2中是我使用的數據庫),這種解決方案將與所有解碼/ nvl2類型的解決方案一樣快 - 它們都必須執行全表掃描(我的解決方案將處理相同的數字整體記錄但分兩組) - 兩種情況下的時間戳字段索引。 – paxdiablo 2008-10-27 11:29:25

+0

明天我開始工作時,嘗試將此解決方案與供應商特定的解決方案並排使用會很有趣。 – 2008-10-27 12:10:41

31

在T-SQL(MS SQL服務器),這工作:

SELECT 
    CASE WHEN Field IS NULL THEN 'NULL' ELSE 'NOT NULL' END FieldContent, 
    COUNT(*) FieldCount 
FROM 
    TheTable 
GROUP BY 
    CASE WHEN Field IS NULL THEN 'NULL' ELSE 'NOT NULL' END 
0

另一個MySQL的方法是使用CASE operator,它可以推廣到比IF()更多的選擇:

SELECT CASE WHEN processed_timestamp IS NULL THEN 'NULL' 
      ELSE 'NOT NULL' END AS a, 
     COUNT(*) AS n 
     FROM logs 
     GROUP BY a 
0

我個人比較喜歡和平的解決方案,但如果你絕對只需要一個返回行(像我最近),在MS SQL Server 2005/2008可以「堆疊」兩個查詢使用CTE

with NullRows (countOf) 
AS 
(
    SELECT count(*) 
    FORM table 
    WHERE [processed_timestamp] IS NOT NULL 
) 
SELECT count(*) AS nulls, countOf 
FROM table, NullRows 
WHERE [processed_timestamp] IS NULL 
GROUP BY countOf 

希望這幫助

0

[T-SQL]:

select [case], count(*) tally 
from (
    select 
    case when [processed_timestamp] is null then 'null' 
    else 'not null' 
    end [case] 
    from myTable 
) a 

,你可以添加到您想要的任何其他值,形成一個分區的情況,例如聲明今天,昨天中午至下午2點,週四下午6點以後。

5

斯圖爾特,

也許考慮這個方案。這也是(也!)供應商非特定的。

SELECT count([processed_timestamp]) AS notnullrows, 
     count(*) - count([processed_timestamp]) AS nullrows 
FROM table 

至於效率,這避免了2倍索引查找/表掃描/任何通過將結果包括在一行中。如果您在結果中絕對需要2行,則由於聯合聚合可能無法避免該集合上的兩次傳遞。

希望這有助於

0
Select Sum(Case When processed_timestamp IS NULL 
         Then 1 
         Else 0 
       End)                not_processed_count, 
      Sum(Case When processed_timestamp Is Not NULL 
         Then 1 
         Else 0 
       End)                processed_count, 
      Count(1)                total 
From table 

編輯:沒仔細看,這一次返回單行。

0

在Oracle

SELECT COUNT(*), COUNT(TIME_STAMP_COLUMN) 
FROM TABLE; 

計數(*)返回的所有行

計數(列)的計數返回其不是NULL的行數,所以

SELECT COUNT(*) - COUNT(TIME_STAMP_COLUMN) NUL_COUNT, 
        COUNT(TIME_STAMP_COLUMN) NON_NUL_COUNT 
FROM TABLE 

應該做這項工作。

如果列被編入索引,最終可能會進行某種範圍掃描並且避免實際讀取表格。

1

如果你的數據庫有一個有效的COUNT(*)函數用於一個表,你可以COUNT取較小的數字,然後減去。

1

的SQL Server(從2012):

SELECT IIF(ISDATE(processed_timestamp) = 0, 'NULL', 'NON NULL'), COUNT(*) 
FROM MyTable 
GROUP BY ISDATE(processed_timestamp); 
0

在T-SQL的另一種方法(SQL服務器)

select count(case when t.timestamps is null 
        then 1 
        else null end) NULLROWS, 
     count(case when t.timestamps is not null 
        then 1 
        else null end) NOTNULLROWS 
from myTable t