1. 程式人生 > >關於使用count(X) 函式的說明(附加:關於null的說明以及和0的區別)

關於使用count(X) 函式的說明(附加:關於null的說明以及和0的區別)

關於使用count(X) 函式的說明

count(X) 函式用於計算一個查詢所返回的行數,但是和其他的聚合函式AVG(X), SUM(X), MAX(X), MIN(X)一樣,它在統計的時候都會簡單的忽略含有空記錄的查詢,即count(X)中的表示式X的值為null時,count(X)(的返回值)為0。

例如,假設表test的內容如下:

select   *  from test;

ID   NAME        COUNTRY

---          ------------     ----------------

1            tone            china

2             lily             america

1            tone            america

null         null             null

null         null             null

3            null             china

SQL>select t.* ,count(name)from test t group by id,name;

ID   NAME        COUNT(NAME)

---          ------------     ----------------

1            tone           2

2             lily             america

null         null             0

3            null             0

雖然(id,name)=(3 , null  )這一組有一行,(id,name)=(null , null  )這一組有兩行,但是由於他們在name這一列值都是為null,所以count(name)的值就是0。同時,也說明雖然(id,name)=(null , null  )這一組id和name值都是null,但是group by不會忽略該空記錄

SQL>select t.* ,count(*)from test t group by id,name;

ID   NAME        COUNT(*NAME

---          ------------     ----------------

1            tone           2

2             lily             america

null         null             2

3            null             1

我們發現,使用count(*)時,(id,name)=(null , null  )這一組的count(*name)的值就=為2,說明此時count(*)裡的*所代表的表示式的值不為null也就是說*不等價於表裡的所有列的值(如果該值的資料型別不是字元型別,應該都會隱式轉換為字元)連線成的字串,具體到表test上,就是*不等價於id||name||country。

count(X) 函式裡的引數個數只有一個所以類似count(id,name) 時,就會提示“引數個數無效”。引數值為null時就不統計該值的。若想在count(X) 函式裡出現表的多個欄位,則使用如下方式:

例如,表test有欄位ID,NAME ,COUNTRY,我們想在count(X) 函式裡出現表test的ID,NAME 欄位,則用count(id||name)的形式。其中,id||name就是一個引數,id和name同時為null,則id||name也為null,故而被count(X) 函式統計。||是字串連線符,連線多個字串組成一個新的字串。具體結果如下:

SQL>select t.* ,count(id||name) from test t group by id,name;

ID   NAME        COUNT(ID||NAME)

---          ------------     ----------------

1            tone           2

2             lily             america

null         null             0

3            null             1

總結:

1、count(column)不統計null。

count(*) 和count(rowid)沒有類似的問題,不會只統計非空記錄。也可以用例如count(1),count(數字或是字元常量或是字串常量),不過還是用rowid快。

COUNT(*) operation countsall rows fed to it by execution plan branch under it.

COUNT(*) operation統計表對應的段中所有的資料行(包括其上各列的值為空值null的資料行)

COUNT(column) operation on the other handcountsall non-null values in that column from rows fed to it by execution plan branch under it.

COUNT(column) operation統計表對應的段中其列上的值不為空值null的資料行

註釋:COUNT(column)的一般形式為COUNT(column1||column2||......)。

參見:


疑問:

在同一張表上,Count(*)和count(常量)如count(1),count(‘f’)兩種形式的寫法統計出來的結果都是一致的,能說明Count(*)和count(常量)如count(1),count(‘f’)等的原理是一樣的?

這個要看具體的執行計劃。

參見:


2、count(*)查詢所消耗的時間比count(rowid) 長嗎?

count(*)也並不比count(rowid)慢,某些情況下比count(rowid)還要快得多,這個要看具體的執行計劃。

count(*)時走全表掃描方式,count(rowid)時索引範圍掃描??)

參見:


https://community.oracle.com/thread/523654?start=15&tstart=0

http://oracledba.co.uk/tips/count_speed.htm

3、關於*的疑問:

select   *  from test;

ID   NAME       COUNTRY

貌似說明,*等價於id||name||country

SQL>select t.* ,count(*)from test t group by id,name;

ID   NAME       COUNT(*NAME

---         ------------     ----------------

1           tone           2

2            lily            america

null        null             2

3           null             1

我們發現,使用count(*)時,(id,name)=(null , null  )這一組的count(*name)的值就=為2,說明此時count(*)裡的*所代表的表示式的值不為null,也就是說*不等價於表裡的所有列的值(如果該值的資料型別不是字元型別,應該都會隱式轉換為字元)連線成的字串,具體到表test上,就是*不等價於id||name||country。

那麼,*具體代表什麼呢?*等價於id||name||country||rowid?*等價於id||name||country||rowid||rownum?

Select    a.* ,count(b.*) from   t1 a ,t2 b  (where a.id=b.id(+));

出現錯誤:ORA01747: invalid user.table.column, table.column, orcolumnspecification

註釋:user.table.column, table.column, orcolumn是一個列名的三種不同的寫法。

Select     count(b.*) from t2 b;

Select     count(t2.*) from t2;

出現錯誤:ORA01747: invalid user.table.column, table.column, orcolumnspecification

註釋:user.table.column, table.column, orcolumn是一個列名的三種不同的寫法。

回答:

兩處中的*含義不一樣的,沒有統一的一個意思:

在SQL語句中的*表示表的所有列,即假如表test有id、name和country三個列,則select * from test等於select id,name,countryfrom test,即*等於表示id,name,country(這個字串在一條sql語句這種字串中)

設計程式設計count(X)函式時,引數值*,表示統計表對應的段中所有的資料行(包括其上各列的值為空值null的資料行)。而設計程式設計count(X)函式時,將引數值A.B的形式規定為表A上的列B的意思,故count(X)函式中的引數值為b.*時,count(X)函式就將其解釋為表b中的一列名為*的列,而實際上表b中不存在一列名為*的列,所以提示ORA-01747: 指定的列名無效(invalid user.table.column, table.column, orcolumn specification)。這是設計函式時沒考慮b.*的形式而造成的結果。

附加:

關於null的說明以及和0的區別

一個變數(例如,表上的各個列其實本質就是一個個變數)的值為null(即資料(值)為空),表示該變數沒有被賦予任何數值。換句話說,當一個變數的值為null時,表示該變數還不知道自己的值為多少,它的值可能是任一數值中的一個。所以說,一個變數的值為null,不等價於一個變數的值為0。一個變數的值為null,不等於說,就不用佔用儲存空間來存放null這個變數賦值中的一種狀態。例如,表test1上有一個數據行,其上的各列的值皆為null:

insert into test1 values(null,null,null);//這裡的null是個關鍵字,不是insert into test1 values(‘null’,‘null’,‘null’),這個是插入一行各列的值是字串值為null這些字元的資料行。

則不是說該表對應的段上的資料塊裡不用消耗一定儲存空間來儲存該行的資料的,而還要的,即佔據了一資料行的儲存空間,只是儲存的值不為什麼數值,為空值。

 附加2:

當表t2裡不含有資料行即0條資料行時,count(*)的返回值為0;

當表t3裡有2行資料如下:

id1    id2

----     -----

null   2

null   2

則select count(id1) from t3 where id2=2裡count(id1)的返回值為0


參考: