2010-03-23 107 views
18

我有兩個表。 indRailType包含一個與我在其他表格中用於指示導軌類型的ID值配對的名稱列表。 WO_BreakerRail包含一個日期列和一個鐵路代碼列,它對應於indRailType中的同一代碼和一些其他數據。對於每個日期,每種軌道類型的任何活動都有WO_BreakerRail。所以我可以有3行記錄爲3/19/2010,每行代表一個不同的鐵路代碼,以及發生了什麼。使用WHERE子句的左外連接

當我使用下面的LEFT OUTER JOIN時,我得到了一張包含所有類型的導軌的表格,其中19行沒有任何事發生在行中的空值。現在,這只是工作,因爲我的WO_BreakerRail表中現在只有一個日期,第19個。當我用不同日期添加更多行時,事情就會變得不合時宜。

這是我的SQL語句,現在給了我正是我想要的結果:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType 
LEFT OUTER JOIN WO_BreakerRail 
    ON indRailType.RailCode = WO_BreakerRail.RailCode 

現在,當我在WHERE WO_BreakerRail.Date = @Date條款我失去了在什麼也沒有發生的JOIN所有行補充。我不想那樣。從閱讀起,這聽起來像是我想要的完整OUTER JOIN,但SQL Server Compact Edition不支持FULL OUTER JOIN s。有沒有辦法解決這個問題,還是我正在尋找其他的東西?

回答

35

Try:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType 
LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode 
      AND WO_BreakerRail.Date = @Date 

因此添加AND WO_BreakerRail.Date = @Date到加入

+1

不要忘記考慮@Date的「時間」部分。如果值在午夜和午夜之間可能有所不同,那麼必須使用某種形式的between子句。 – 2010-03-23 15:21:03

+0

這個答案完美無缺,謝謝。 菲利普:感謝那個指針,雖然我在這個項目的早些時候遇到了這個問題,但是我最終把它修復到了我的C#代碼中,刪除了所有的時間部分,每天都會默認到午夜。 – Wesley 2010-03-23 15:30:22

+1

@韋斯利,最好是「落地」日期時間數據類型來消除時間,所以時間是00:00:00.000而不是午夜。 – 2010-03-23 15:32:24

2

添加在LEFT OUTER JOIN聲明WO_BreakerRail.Date = @Date而不是WHERE

SELECT 
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
    FROM indRailType 
     LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode AND WO_BreakerRail.Date = @Date 

,或者你可以將其添加到WHERE:

SELECT 
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
    FROM indRailType 
     LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode 
    WHERE (WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL) 
5

您可以使用此where子句:

WHERE WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL 
+3

當與外部工作聯接,最好到f actor ON子句中的任何「isnull work」,而不是where子句 – 2010-03-23 15:22:01

15

謂詞條件需要是On子句的加入,where子句不英寸外連接的工作方式是,在分析連接條件之後,所有來自「外側」的與內側不匹配的行都被添加回....但這全部發生在處理where子句之前。因此,如果where子句謂詞從外連接的外側過濾屬性,所有這些行將再次被刪除......(它們全都爲空)。把謂語,而不是連接條件,那麼它將得到評估都回添加缺少的行之前...

SELECT b.ID, t.RailType, b.CreatedPieces, 
     b.OutsideSource, b.Charged, b.Rejected, 
     b.RejectedToCrop 
FROM indRailType t 
    LEFT JOIN WO_BreakerRail b 
     ON t.RailCode = b.RailCode 
      And b.Date = @Date 
0

你想要的是左側的接合部之前過濾您WO_BreakerRail所需的日期indRailType。如果您只是添加WHERE語句,則會以相反的方式完成,這會導致您描述的問題。

到目前爲止提供的資料應工作方案(移動狀態進入LEFT JOIN),但我想提出一個替代方案:您可以使用子查詢來指定哪些事情應該做的順序:

SELECT R.ID, indRailType.RailType, R.CreatedPieces, R.OutsideSource, R.Charged, R.Rejected, R.RejectedToCrop 
    FROM indRailType LEFT OUTER JOIN 
     (SELECT * FROM WO_BreakerRail WHERE Date = @Date) R 
     ON indRailType.RailCode = R.RailCode 

(未經測試,但據我所知,SQL Server CE的支持子查詢。)

1

,或者你可以把它添加到WHERE

SELECT WO_BreakerRail.ID, indRailType.RailType, 
    WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType, WO_BreakerRailCode 
WHERE indRailType.RailCode = WO_BreakerRail.RailCode(+) 
AND WO_BreakerRail.Date (+) [email protected] 
+0

'(+)'是一個Oracle加入運算符,並且OP正在使用SQL-Server。此外,不建議使用外連接的語法,因爲它更加有限,並且更難以閱讀標準的'Left Join'語法。 [Oracle Docs:Joins](https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm) – Wayne 2016-08-22 17:01:44