2012-02-02 39 views
13

Trong MySQL:Chọn các hàng từ một bảng nơi hàng trong một bảng với cùng id có một giá trị đặc biệt trong một cột

Nếu chúng ta có hai bảng:

comments 
key | value 
================= 
1  | foo 
2  | bar 
3  | foobar 
4  | barfoo 

và:

meta 
comment_key | value 
========================= 
1    | 1 
2    | 1 
3    | 2 
4    | 1 

Tôi muốn nhận các nhận xét từ bảng comment có tương ứng comment_key trong bảng meta cócụ thể 10 (cột value trong bảng meta).

Ví dụ, tôi muốn chọn tất cả các hàng từ bảng comment rằng có một value của 1 trong bảng meta:

tôi mong đợi những kết quả này:

key | value 
================= 
1  | foo 
2  | bar 
4  | barfoo 

Và nếu tôi chọn tất cả các hàng từ bảng comment có một số value trong số 2 trong bảng meta:

Tôi mong đợi kết quả này:

key | value 
================= 
3  | foobar 

Tôi thực sự hy vọng ai đó có thể giúp đỡ, cảm ơn tất cả các bạn trước!

Tôi nghĩ mình cần tham gia? Bất kỳ con trỏ nào sẽ là tuyệt vời, và nếu có thể, một lời giải thích ngắn để tôi có thể làm việc ra nơi tôi đã đi sai -> vì vậy tôi sẽ biết trong thời gian tới!

Trả lời

20

Tôi thực sự sẽ không đề xuất JOIN cho số này — hoặc đúng hơn, tôi muốn giới thiệu "semijoin", là khái niệm đại số quan hệ không được thể hiện trực tiếp trong SQL. Một semijoin về cơ bản là một phép nối mà bạn muốn lấy các bản ghi từ chỉ một bảng, nhưng với điều kiện rằng chúng có các bản ghi tương ứng trong một bảng khác.

Trong ký hiệu SQL, khái niệm này được thể hiện gián tiếp, bằng cách sử dụng an IN clause với subquery:

SELECT key, value 
    FROM comments 
WHERE key IN 
     (SELECT comment_key 
      FROM meta 
      WHERE value = 1 
     ) 
; 

(MySQL sẽ thực sự kết thúc dịch đó trở lại thành một semijoin nội — bản chất là một loại thoái hóa inner- tham gia — nhưng điều khoản IN là cách tự nhiên để thể hiện nó trong SQL thô.)

+1

- không quan trọng nếu các biến vị ngữ 'join',' exist' hoặc 'in' được sử dụng, chúng đều là Semi Joins - được định nghĩa là các tham gia trả về các hàng từ một bảng dựa trên sự tồn tại của các hàng liên quan trong một bảng khác. –

+2

@JCooper: Tôi không thấy nó theo cách đó. Giả sử rằng đối với mỗi bản ghi trong 'parent', có 0, một hoặc nhiều hơn một bản ghi trong' child'. Sau đó, một phép nối bán sẽ bao gồm số không hoặc một bản sao của mỗi bản ghi 'cha', trong khi một câu lệnh SQL INNER JOIN sẽ bao gồm nhiều bản sao của một số bản ghi' cha mẹ'. Nhưng tôi có thể thấy nó theo cách của bạn. Trong đại số quan hệ, một bán kết nối tương đương với một tham gia bên trong theo sau là một phép chiếu thích hợp; vì vậy chúng ta có thể coi đây là sự khác biệt giữa dự đoán SQL 'SELECT' và đại số quan hệ thay vì giữa SQL' INNER JOIN' và tham số bán đại số quan hệ. – ruakh

+1

Wow, tôi đã rất gần, tôi chỉ có '=' thay vì 'IN'! Cảm ơn bạn, làm việc một điều trị! –

0

Bạn đang tìm kiếm một đồng bằng, vanilla equi-join tại đây.

SELECT `comment`.`key` AS `key`, 
     `comment`.`value` AS `value` 
    FROM `comments` 
     JOIN `meta` 
      ON `comments`.`key` = `meta`.`comment_key` 
    WHERE `meta`.`value` = 1; 

Tôi không thực sự chắc chắn những gì sắp xếp của tư vấn bạn đang tìm kiếm ở đây nhưng bạn có thể đọc thêm về các chủ đề (không MySQL cụ thể) tại Wikipedia's SQL JOIN page.

tôi khuyên bạn nên lập chỉ mục trên comment. keymeta. comment_key với cả hai chỉ mục CHÍNH PRIMARY giả định rằng bạn muốn có chỉ là 1 meta hàng cho mỗi hàng comment (PRIMARY KEYs là UNIQUE theo định nghĩa).Nếu bạn muốn cho phép nhiều hơn 1 meta mỗi comment sau đó thêm một chỉ mục riêng biệt id cột vào meta và đặt khóa CHÍNH CHÍNH là comment_key chỉ là một chỉ mục b-tree.

Tôi cũng không chắc chắn hiệu suất của điều này sẽ so sánh với câu trả lời "bán tham gia" cũng được liệt kê nhưng đối với tôi, đây là cách đơn giản và tự nhiên hơn để thể hiện truy vấn; với chỉ hai bảng, mặc dù, nó không phải là quá khó khăn cho MySQL để tối ưu hóa.

+0

Tôi không chắc chắn nếu đề cập đến chỉ mục là hơn bước câu hỏi không thích hợp hay không. Tôi vừa thấy quá nhiều lập trình viên không xem xét chúng vì các truy vấn luôn chạy nhanh trên dữ liệu thử nghiệm với hàng chục hàng trên mỗi bảng hoặc ít hơn. – SnowCrash

+0

Điều này sẽ không dẫn đến các hàng trùng lặp trong cấp độ gốc nếu có nhiều hàng con không? – CMCDragonkai

0

Tôi sẽ sử dụng "INNER JOIN" theo cách sau:

SELECT comments.key, comments.value FROM comments 
INNER JOIN meta ON comments.key=meta.comment_key WHERE meta.value = 1; 

Cheers! ;-)

Chỉnh sửa
Các vấn đề liên quan