2010-04-01 24 views
13

Whats sự khác biệt giữaSự khác nhau giữa "và" và "ở đâu" trong tham gia

SELECT DISTINCT field1 
    FROM table1 cd 
    JOIN table2 
    ON  cd.Company = table2.Name 
     and table2.Id IN (2728) 

SELECT DISTINCT field1 
    FROM table1 cd 
    JOIN table2 
    ON cd.Company = table2.Name 
where table2.Id IN (2728) 

cả trả lại kết quả tương tự và cả hai đều có cùng giải thích đầu ra

+1

Mẹo nhỏ: Hãy xem xét kế hoạch thực hiện, có thể cung cấp thông tin chi tiết hơn một chút. SQL thực hiện rất nhiều tối ưu hóa truy vấn. – Zyphrax

Trả lời

24

Thứ nhất có sự khác biệt ngữ nghĩa. Khi bạn tham gia, bạn đang nói rằng mối quan hệ giữa hai bảng được xác định bởi điều kiện đó. Vì vậy, trong ví dụ đầu tiên của bạn, bạn đang nói rằng các bảng có liên quan bởi cd.Company = table2.Name AND table2.Id IN (2728). Khi bạn sử dụng mệnh đề WHERE, bạn đang nói rằng mối quan hệ được xác định bởi cd.Company = table2.Name và bạn chỉ muốn các hàng có điều kiện table2.Id IN (2728) áp dụng. Mặc dù những câu trả lời tương tự, nó có nghĩa là những điều rất khác nhau để một lập trình viên đọc mã của bạn.

Trong trường hợp này, mệnh đề WHERE gần như chắc chắn là ý của bạn để bạn nên sử dụng nó.

Thứ hai có sự khác biệt thực sự về kết quả trong trường hợp bạn sử dụng LEFT JOIN thay vì INNER JOIN. Nếu bạn bao gồm điều kiện thứ hai là một phần của kết nối, bạn sẽ vẫn nhận được một hàng kết quả nếu điều kiện không thành công - bạn sẽ nhận được các giá trị từ bảng bên trái và các giá trị rỗng cho bảng bên phải. Nếu bạn bao gồm điều kiện như một phần của mệnh đề WHERE và điều kiện đó không thành công, bạn sẽ không nhận được hàng nào cả.

Dưới đây là ví dụ để minh họa điều này.

Query 1

(WHERE):

SELECT DISTINCT field1 
    FROM table1 cd 
    LEFT JOIN table2 
    ON cd.Company = table2.Name 
WHERE table2.Id IN (2728); 

Kết quả:

field1 
200 

Query 2 (AND):

SELECT DISTINCT field1 
    FROM table1 cd 
    LEFT JOIN table2 
    ON cd.Company = table2.Name 
    AND table2.Id IN (2728); 

Kết quả:

field1 
100 
200 

Dữ liệu thử nghiệm được sử dụng:

CREATE TABLE table1 (Company NVARCHAR(100) NOT NULL, Field1 INT NOT NULL); 
INSERT INTO table1 (Company, Field1) VALUES 
('FooSoft', 100), 
('BarSoft', 200); 

CREATE TABLE table2 (Id INT NOT NULL, Name NVARCHAR(100) NOT NULL); 
INSERT INTO table2 (Id, Name) VALUES 
(2727, 'FooSoft'), 
(2728, 'BarSoft'); 
+1

+1 cho kịch bản 'LEFT JOIN' – cjk

+0

+1 để đề cập đến LEFT JOINs. Tôi sẽ không biết xấu hổ về câu trả lời của tôi http://stackoverflow.com/questions/2559194/difference-between-and-and-where-in-joins/2559769#2559769 để biết thêm chi tiết và lý do nữa :) – Unreason

+0

Trong ví dụ (truy vấn 2 với AND) nếu chúng ta có table1.Id IN (100); nó sẽ vẫn trả về hai hàng .. tại sao lại như vậy? ... – psj01

1

Có không có sự khác biệt. "ON" giống như một từ đồng nghĩa với "WHERE", do đó t ông thứ hai loại đọc như:

JOIN table2 WHERE cd.Company = table2.Name AND table2.Id IN (2728)

+0

Theo http://dev.mysql.com/doc/refman/4.1/en/join.html nó không có vẻ như ON là một từ đồng nghĩa cho WHERE. –

+2

Tôi đã nói nó giống như một từ đồng nghĩa. –

+0

và chỉ để tham gia joins.inner. – nawfal

3
  • Các tham gia được sử dụng để phản ánh các mối quan hệ thực thể
  • mệnh đề where lọc xuống kết quả .

Vì vậy, các mệnh đề tham gia là 'tĩnh' (trừ khi quan hệ thực thể thay đổi),
trong khi mệnh đề ở đâu là trường hợp cụ thể.

0

Không có sự khác biệt khi công cụ tối ưu hóa truy vấn phá vỡ nó xuống các toán tử truy vấn có liên quan của nó.

5

SQL đến từ relational algebra.

Một cách để xem xét sự khác biệt là JOINs hoạt động trên các tập hợp có thể tạo ra nhiều bản ghi hoặc ít bản ghi hơn trong kết quả mà bạn có trong bảng gốc. Ở phía bên kia WHERE sẽ luôn hạn chế số lượng kết quả.

Phần còn lại của văn bản là giải thích thêm.


Để biết tổng quan về loại tham gia, hãy xem lại article.

Khi tôi nói rằng điều kiện nơi sẽ luôn hạn chế kết quả, bạn phải tính đến khi chúng ta nói về các truy vấn trên hai (hoặc nhiều) bảng bạn phải bằng cách nào đó ghép các bản ghi từ các bảng này ngay cả khi có không có từ khóa JOIN. Vì vậy, trong SQL nếu các bảng được phân cách đơn giản bằng dấu phẩy, bạn thực sự đang sử dụng CROSS JOIN (sản phẩm Descartes) trả về mọi hàng từ một bảng cho mỗi hàng trong hàng khác. Và vì đây là số kết hợp tối đa các hàng từ hai bảng nên kết quả của bất kỳ WHERE nào trên các bảng được nối chéo có thể được biểu diễn dưới dạng một phép toán JOIN.

Nhưng giữ, có những trường hợp ngoại lệ tối đa này khi bạn giới thiệu LEFT, RIGHT và FULL OUTER tham gia.

LEFT JOIN sẽ nối các bản ghi từ bảng bên trái vào tiêu chí nhất định với các bản ghi từ bảng bên phải, NHƯNG nếu tiêu chí tham gia, nhìn vào hàng từ bảng bên trái không hài lòng với bất kỳ bản ghi nào trong bảng bên phải JOIN sẽ vẫn trả về một bản ghi từ bảng bên trái và trong các cột sẽ đến từ bảng bên phải nó sẽ trả về NULLs (RIGHT JOIN hoạt động tương tự nhưng từ phía bên kia, FULL OUTER hoạt động giống như cả hai cùng một lúc).

Vì kết nối chéo mặc định KHÔNG trả về các bản ghi đó, bạn không thể biểu diễn các tiêu chí kết hợp này với điều kiện WHERE và bạn buộc phải sử dụng cú pháp JOIN (oracle là một ngoại lệ với phần mở rộng này tới tiêu chuẩn SQL và = toán tử, nhưng điều này không được chấp nhận bởi các nhà cung cấp khác và tiêu chuẩn).

Ngoài ra, tham gia thường, nhưng không phải lúc nào cũng trùng khớp với tính toàn vẹn tham chiếu hiện tại và đề xuất mối quan hệ giữa các thực thể, nhưng tôi sẽ không đặt trọng số vào điều đó vì điều kiện có thể thực hiện tương tự (ngoại trừ trường hợp được đề cập trước đó) và với một RDBMS tốt, nó sẽ không tạo ra sự khác biệt nơi bạn chỉ định tiêu chí của mình.

+0

giải thích rất rõ ràng – user187291

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