2014-12-10 31 views
17

Tôi đang bối rối bởi một truy vấn SQL, và trung thực, một trong những điều mà tôi thậm chí không chắc chắn làm thế nào để google cho. Do đó StackOverflow.Tại sao truy vấn con này KHÔNG gây ra lỗi?

Tôi có những gì tôi nghĩ là một truy vấn đơn giản.

SELECT Id 
FROM Customer 
WHERE Id IN (SELECT Id from @CustomersWithCancelledOrders) 

Đây là nơi tôi thấy sự kỳ quặc. Không có cột nào được gọi là Id trong biến bảng @CustomersWithCancelledOrders. Nhưng không có lỗi.

Kết quả này là các Id cho tất cả Khách hàng. Từng người một. Mà rõ ràng là đánh bại các điểm làm một truy vấn phụ ở nơi đầu tiên.

Giống như việc sử dụng cột Id từ bảng bên ngoài (Khách hàng), nhưng tôi không hiểu tại sao nó lại làm điều đó. Có bao giờ là lý do bạn muốn làm điều đó không? Tôi có thiếu cái gì đó vô cùng rõ ràng không?

SQLFiddle sự kỳ quặc. Nó không phải là SQL Fiddle tốt nhất, vì tôi không thể tìm ra cách trả lại nhiều tập kết quả trên trang web đó, nhưng nó thể hiện cách tôi chạy qua vấn đề này.

Tôi cho rằng những gì tôi đang tìm kiếm là tên cho "tính năng" ở trên, một số loại thông tin về lý do tại sao nó hoạt động và những gì truy vấn không chính xác thực sự có ý nghĩa.


Tôi đã cập nhật câu hỏi trên để sử dụng ví dụ tốt hơn một chút. Nó vẫn còn tiếp tục, nhưng nó gần gũi hơn với kịch bản tôi đã viết khi tôi thực sự gặp phải vấn đề.


Sau khi đọc một số truy vấn con tương quan, có vẻ như lỗi đánh máy của tôi (sử dụng cột Id sai trong truy vấn phụ) sẽ thay đổi hành vi của truy vấn phụ.

Thay vì đánh giá các kết quả của truy vấn phụ một lần và sau đó xử lý các kết quả đó dưới dạng tập hợp (đó là những gì tôi dự định), nó đánh giá truy vấn con cho mỗi hàng trong truy vấn bên ngoài.

Điều này có nghĩa là truy vấn phụ sẽ đánh giá một tập hợp các kết quả khác nhau cho mỗi hàng và tập hợp kết quả đó được đảm bảo để có Id khách hàng của hàng đó trong đó. Truy vấn con trả về một tập hợp gồm Id của hàng lặp lại số lần X, trong đó X là số hàng trong biến bảng đang được chọn.

...

Thật khó để viết ra mô tả ngắn gọn về sự hiểu biết của tôi về vấn đề này. Lấy làm tiếc. Tôi nghĩ rằng tôi tốt bây giờ mặc dù.

+0

Thật không may, khó có thể biết được bạn là người mới hay đã đơn giản hóa một trường hợp hợp lệ, nhưng hầu hết thời gian bạn có lẽ nên tham gia các bảng thay vì sử dụng truy vấn phụ. – JamesRyan

+3

Thuật ngữ kỹ thuật bạn đang tìm kiếm là 'truy vấn con tương quan '. – Brandon

+0

@JamesRyan Tôi đã viết một truy vấn nhanh ngày hôm qua và tình cờ vô tình viết một truy vấn UPDATE tương tự như trên. Việc sử dụng ID bên ngoài trong truy vấn con là một lỗi đánh máy, và tôi đã rất ngạc nhiên khi nó cập nhật tất cả các bản ghi trong bảng thay vì tập hợp con mà tôi dự định. –

Trả lời

36

Đó là hành vi dự định vì trong truy vấn phụ bạn có thể truy cập tên cột 'truy vấn bên ngoài'. Có nghĩa là bạn có thể sử dụng Id từ Bảng trong Truy vấn con và truy vấn do đó cho rằng bạn đang sử dụng Id.

Đó là lý do tại sao bạn nên đủ điều kiện với bí danh hoặc tên đủ điều kiện khi làm việc với các truy vấn phụ.

Ví dụ; kiểm tra
http://support.microsoft.com/kb/298674

+0

Điều đó làm rõ hành vi như dự định, mà tôi giả định. Tuy nhiên, truy vấn thực sự có ý nghĩa gì? Tìm cho tôi tất cả các giá trị Id bên trong Bảng trong đó giá trị Id nằm trong tập hợp các giá trị được mô tả bởi? –

+8

Truy vấn có nghĩa là về cơ bản: 'SELECT Id FROM Table WHERE Id IN (SELECT Table.Id FROM OtherTable)' Đó là lý do tại sao nó trả về mọi thứ miễn là có bất kỳ hàng nào trong OtherTable. Nó chọn tất cả Table.Id từ truy vấn phụ nếu có các hàng trong truy vấn con. Hãy thử nhận xét ra chèn vào CustomerMap trong ví dụ fiddle của bạn. –

12
SELECT ID 
FROM [Table] 
WHERE ID IN (SELECT OtherTable.ID FROM OtherTable) 

này sẽ tạo ra một lỗi. Như Allan S. Hanses đã nói, trong truy vấn con, bạn có thể sử dụng colums từ truy vấn chính.

Xem ví dụ này

SELECT ID 
FROM [Table] 
WHERE ID IN (SELECT ID) 
1

Truy vấn là một phụ truy vấn tương quan và thường được sử dụng để giới hạn kết quả của truy vấn bên ngoài dựa trên một cột được trả về bởi truy vấn phụ; do đó 'tương quan'. Trong ví dụ này, ID trong truy vấn bên trong thực sự là ID từ bảng trong truy vấn bên ngoài. Điều này làm cho truy vấn hợp lệ nhưng có thể không cung cấp cho bạn bất kỳ kết quả hữu ích nào vì nó không thực sự tương quan giữa các truy vấn bên ngoài và bên trong.

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