2010-03-23 59 views
18

Tôi có hai bảng. indRailType chứa danh sách các tên được ghép nối với một giá trị ID mà tôi sử dụng trong các bảng khác để biểu thị loại đường ray. WO_BreakerRail chứa cột ngày và cột mã đường sắt tương ứng với cùng mã trong indRailType và một số dữ liệu khác. Có một hàng trong WO_BreakerRail cho bất kỳ hoạt động nào trên từng loại đường ray, cho mỗi ngày. Vì vậy, tôi có thể có 3 hàng ngày cho 3/19/2010, mỗi hàng chỉ ra một mã vạch khác nhau và những gì đã xảy ra.LEFT OUTER JOIN với mệnh đề WHERE

Khi tôi sử dụng LEFT OUTER JOIN sau đây, tôi nhận được một bảng với tất cả các loại đường ray, có null trong các hàng không có gì xảy ra vào ngày 19. Bây giờ, điều này chỉ hoạt động bởi vì tôi chỉ có một ngày được đại diện trong bảng WO_BreakerRail của tôi ngay bây giờ, thứ 19. Khi tôi thêm nhiều hàng hơn với các ngày khác nhau, mọi thứ sẽ đi haywire.

Đây là tuyên bố của tôi SQL, mà ngay bây giờ mang lại cho tôi một cách chính xác kết quả tôi muốn:

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 

Bây giờ, khi tôi thêm vào một điều khoản WHERE WO_BreakerRail.Date = @Date tôi mất tất cả các hàng trong JOIN mà không có gì xảy ra. Tôi không muốn điều đó. Từ việc đọc lên, có vẻ như một FULL OUTER JOIN là những gì tôi muốn, nhưng SQL Server Compact Edition không hỗ trợ FULL OUTER JOIN s. Có cách nào xung quanh vấn đề này không, hay tôi đang tìm cái gì khác hoàn toàn?

Trả lời

35

Thử:

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 

Như vậy thêm AND WO_BreakerRail.Date = @Date vào tham gia

+1

Đừng quên yếu tố trong phần "thời gian" của @Date. Nếu các giá trị có thể thay đổi giữa nửa đêm và nửa đêm, bạn sẽ phải sử dụng một số dạng giữa mệnh đề. –

+0

Câu trả lời này hoạt động hoàn hảo, cảm ơn bạn. Philip: Cảm ơn con trỏ đó, mặc dù tôi gặp phải vấn đề đó trước đó trong dự án này, nhưng tôi đã sửa nó trong mã C#, xóa tất cả các phần thời gian, mặc định mỗi ngày đến nửa đêm. – Wesley

+1

@Wesley, cách tốt nhất là loại dữ liệu datetime "sàn" để xóa thời gian, do đó, thời gian là 00: 00: 00.000 và không phải nửa đêm. –

2

thêm WO_BreakerRail.Date = @Date trên báo cáo kết quả LEFT OUTER JOIN và không phải là 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 

hoặc bạn có thể thêm nó vào ĐỊA ĐIỂM:

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

Bạn có thể sử dụng này mệnh đề where:

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

Khi làm việc với bên ngoài tham gia, cách tốt nhất là f diễn viên bất kỳ "công việc isnull" trong mệnh đề ON, và không phải là khoản khoản –

15

Tình trạng ngữ cần phải được trong mệnh đề On cho tham gia, không phải trong mệnh đề where. Cách bên ngoài tham gia làm việc, sau khi các điều kiện tham gia được phân tích, tất cả các hàng từ "bên ngoài" không khớp với bên trong được thêm vào lại .... Nhưng điều này xảy ra trước khi mệnh đề where được xử lý. Vì vậy, nếu mệnh đề where predicate lọc trên một thuộc tính từ bên ngoài của một phép nối ngoài, tất cả các hàng đó sẽ bị loại bỏ một lần nữa ... (Chúng đều là null). Đặt vị trong điều kiện tham gia thay vào đó, sau đó nó sẽ được đánh giá trước hàng thiếu được bổ sung trở lại trong ...

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

gì bạn muốn là để lọc của bạn WO_BreakerRail đến ngày mong muốn trước LEFT tham gia nó đến indRailType. Nếu bạn chỉ cần thêm câu lệnh WHERE, nó được thực hiện theo cách khác, điều này dẫn đến sự cố bạn mô tả.

Các giải pháp cung cấp cho đến nay nên làm việc (di chuyển điều kiện vào LEFT JOIN), nhưng tôi muốn đề nghị một sự thay thế: Bạn có thể sử dụng một subquery để xác định thứ tự mà điều này nên được thực hiện:

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 

(chưa được kiểm tra, nhưng như xa như tôi biết, SQL server CE hỗ trợ truy vấn con.)

1

hoặc bạn có thể thêm nó vào 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

'(+)' là một toán tử tham gia Oracle và OP đang sử dụng SQL-Server. Ngoài ra, cú pháp cho phép nối ngoài không được khuyến nghị sử dụng vì nó bị hạn chế và khó đọc hơn là cú pháp 'Left Join' chuẩn. [Tài liệu Oracle: Tham gia] (https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm) – Wayne

Các vấn đề liên quan