天天看點

使用

    這篇SQL Server應用技巧的文章解釋了NULLS對資料操作的影響,以及通過内部連接配接和外部連接配接得到不同的查詢結果。

SQL Server 開發人員必須了解兩件事情:首先,内部連接配接和外部連接配接的差異;其次,NULLS對兩種連接配接操作的影響。這篇文章就涵蓋了這兩個方面。

讓我們一步步來分析問題。首先,内部連接配接和外部連接配接的差異,然後,查詢中NULLS的影響。為了研究内部連接配接和外部連接配接的差異,我們需要一些樣例資料。

假設我們有兩個資料表T1和T2,每個表中都含有資料列Testjoin。在資料表T1中,Testjoin列的資料值是1,2,3。在T2中,Testjoin列的資料值是NULL,2,3。基于Testjoin列的内部查詢将隻會傳回兩行,其中數值1和NULL無法連接配接。然而當為外部連接配接時,數值1和NULL卻可以連接配接。例如,下面查詢語句的傳回值就是那些下了訂單的客戶所在的行。

SELECT CustomerID, OrderID FROM Customers Inner Join Orders

On Customers.CustomerID = Orders.CustomerID

(在許多商務交易中,這麼做是有根據的,一些商務交易中,甚至規定了客戶必須至少下一個訂單。在我看來,資料庫的定義階段就應該反映這些商務交易規則,而不是在某些中間階段。當然,也存在着一些不同的情況。)

下面是一個外部連接配接:

SELECT CustomerID, OrderID FROM Customers LEFT OUTER JOIN Orders

OnOrders.CustomerID = Customers.CustomerID

它的傳回值是所有的客戶清單,而不管客戶是否下了訂單。

運作清單A中的腳本來建立一個測試表格.

下面的SQL語句對外部連接配接和内部連接配接進行了比較:

SELECT  InnerOuter.T1.T1ID, InnerOuter.T1.NameAS Name1,

        InnerOuter.T2.T2ID, InnerOuter.T2.NameAS Name2

FROM    InnerOuter.T1 LEFT OUTER JOIN

               InnerOuter.T2 ON InnerOuter.T1.T1ID = InnerOuter.T2.T1ID

當運作了腳本中的兩個查詢之後,你會發現内部連接配接傳回兩行,而外部連接配接傳回了三行。即使再添加第三個資料表,結果仍是遵循同樣的規則。如清單B示:

如果你在select查詢語句中加了第三個表格,仍會得到同樣的結果:内部連接配接傳回兩行,外部連接配接傳回三行。如清單C示:

下面看看NULLS對不同的集合函數的影響。為了更好的了解,在表T2上增加一列空的money列,稱為Amount。在T2種增加一些行資料,如下所示:

T2ID  T1ID  Name  Amount

1     1     T2Text1     NULL

2     NULL  T2Text2     NULL

3     3     T2Text3     120.0000

4     1     T2Text4     123.0000

5     1     T2Text5     234.0000

6     3     T2Text6     345.0000

NULL  NULL  NULL  NULL

有三行資料T1ID列的值是1,其中有一行的Amount值是NULL。有兩行資料的T1ID值是3,這兩行資料的Amount值都不為空(你還可以增加更多的行,但要確定行數目和Amount列為NULL的數目也不同)。

現在,運作下面的查詢語句:

SELECT  InnerOuter.T1.T1ID,

        Sum(InnerOuter.T2.Amount)AS TotalAmount,

        Count(InnerOuter.T2.T1ID)AS NumberOfRows,

        Count(InnerOuter.T2.Amount)AS NumberOfAmounts,

        Avg(InnerOuter.T2.Amount)AS AverageAmount

        InnerOuter.T2 ON InnerOuter.T1.T1ID = InnerOuter.T2.T1ID

GROUP BY

        InnerOuter.T1.T1ID

結果如下:

1     357.00      3     2     178.50

2     NULL  0     0     NULL

3     465.00      2     2     232.50

第一行的傳回結果表明:如果按照T1ID列統計,你将得到正确的行數,但是如果是按照Amount列統計,得到的将是非NULL值的行數。需要注意的是:平均值是按照非NULL值的數目進行計算的,而不是總行數。

你可能會認為這些事例并不真實,因為表格之間的聯系都是人為給定的。并且在實際中,似乎不允許外關鍵字為NULL。然而,我的确在資料庫中發現存在着這樣的情況。例如,HR招聘了一名新雇員,但是還沒有安排他的工作部門;又例如,我們将一名客戶加入到資料庫中,但是還沒為其安排一名銷售代表。

有很多方法處理類似這樣資訊缺失的情況。在我看來,最糟糕的處理方法就是在添加所謂的0th行,當外關鍵字是NULL時,就使用0值來代換。這樣,外關鍵字就永遠不會是NULL。這一方法會造成兩個問題:1)通過向資料表中引進一種新的資料類型,從概念上僞造了一個資料實體。然而關系資料庫認為資料表中都是确實存在的資料類型;2)它将查詢操作的處理變得更加的複雜化,因為你要将查詢結果中含0的這些行删除。

上一篇: 累計值
下一篇: 橋套子查詢