2013-06-13 23 views
6

Tôi có hai bảng với cấu trúc rất giống nhau.Chọn cùng một cột từ nhiều bảng Chỉ WHERE something = something

Universidades 
nombre | contenido | becas | fotos etc etc etc 
Internados 
nombre | todo | becas | fotos etc etc etc 

Tôi muốn viết một câu lệnh SQL sẽ chọn nombre từ cả hai và trả về nó như một mảng chỉ khi nó khớp. Từ những gì tôi đã thấy UNION SELECT dường như là cách để làm điều này. Tôi đã thêm WHERE vào cuối và tôi nghĩ đây là nơi xảy ra sự cố. Cho đến nay tôi nhận được hàng đầu tiên của bảng đầu tiên.

Tôi nhập sai gì?

$db = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); 
$data = $db->prepare("SELECT nombre FROM internados UNION SELECT nombre FROM universidades WHERE nombre = ?"); 
$data->execute(array($nombre)); 

xin lỗi, tôi muốn lấy lại một kết quả từ hai bảng này. Namees trong cột nombre đều riêng biệt và khác nhau trong cả hai bảng

+0

"Chỉ trả lại dưới dạng mảng khi nó khớp" có nghĩa là gì? – ErikE

+0

Trả lại tất cả thông tin từ hàng đó ở định dạng mảng khi nombre bằng giá trị được chuyển đến nó –

+0

DBMS và phiên bản nào, vui lòng? Ngoài ra, "định dạng mảng" nghĩa là gì? Trong SQL có các hàng và cột. Đó là nó! – ErikE

Trả lời

16

Một vấn đề để chỉ ra trước khi chúng tôi giải quyết vấn đề là mỗi truy vấn trong một UNION là khác biệt và đòi hỏi WHERE khoản riêng của mình. Mệnh đề duy nhất áp dụng cho toàn bộ số UNIONORDER BY. Vì vậy, câu hỏi của bạn như là cần một số tinh chỉnh:

SELECT nombre 
FROM dbo.internados 
WHERE nombre = ? -- the added line 
UNION 
SELECT nombre 
FROM dbo.universidades 
WHERE nombre = ? 
; 

Thứ hai, nếu bạn muốn hai bảng để cả hai có cùng nombre (mà không phải là hoàn toàn rõ ràng nhưng tôi đoán đó là bên phải), sau đó sẽ không làm việc vì nó chỉ trả về một nombre nếu giá trị được tìm thấy trong hoặc bảng. Có lẽ cách tốt nhất để giải quyết vấn đề này là chỉ cần tham gia:

SELECT I.nombre 
FROM 
    dbo.internados I 
    INNER JOIN dbo.universidades U 
     ON I.nombre = U.nombre 
WHERE 
    I.nombre = ? 
    AND U.nombre = ? -- perhaps not needed, but perhaps helpful 
; 

Tôi không chắc chắn 100% rằng tôi hiểu chính xác những gì bạn đang tìm kiếm, vì vậy hãy nói lên nếu tôi đã bỏ lỡ điểm.

Bạn có thể suy nghĩ về JOINUNION theo cách này:

  • JOIN: kết nối hàng ngang
    • Matches họ về điều kiện
    • Tạo cột mới
    • doesn' t chính xác crea các hàng te vì tất cả dữ liệu đến từ các hàng hiện tại, nhưng nó sẽ sao chép một hàng từ một đầu vào khi các điều kiện khớp với nhiều hàng trong đầu vào khác. Nếu cả hai yếu tố đầu vào đều có bản sao thì nó sẽ nhân số lượng hàng từ một đầu vào bằng số lượng hàng phù hợp với nhau.
    • Nếu hoàn toàn không có điều kiện đối sánh (suy nghĩ CROSS JOIN) thì bạn có thể có được một sản phẩm Descartes là mỗi hàng trong một đầu vào phù hợp với mỗi hàng trong hàng còn lại.
    • Khi sử dụng một OUTER join-- LEFT, RIGHT, FULL --Nếu như hàng từ các đầu vào bên trong (hoặc một trong hai đầu vào với FULL) không phù hợp với người kia, NULL s sẽ được đặt vào các cột cho các đầu vào khác.
  • UNION: ngăn xếp hàng theo chiều dọc
    • Nói chung, tạo mới hàng
    • Không có điều kiện được sử dụng, không có phù hợp với thực
    • UNION bởi chính nó (không UNION ALL) sẽ xóa các hàng trùng lặp, ngay cả khi một đầu vào không có hàng

Lưu ý rằng UNION có thể được sửa đổi để thực hiện công việc, mặc dù đây không phải là lý tưởng:

SELECT nombre 
FROM (
    SELECT nombre 
    FROM dbo.internados 
    WHERE nombre = ? 
    UNION ALL 
    SELECT nombre 
    FROM dbo.universidades 
    WHERE nombre = ? 
) N 
GROUP BY nombre 
HAVING Count(*) = 2 
; 

Bằng cách này chúng tôi đảm bảo có hai giá trị. Lưu ý điều này giả định rằng không thể có hai cùng tên trong mỗi bảng. Nếu đó là sự thật, cần phải có nhiều công việc hơn để thực hiện phương thức UNION.

+3

Cảm ơn bạn đây là một lời giải thích tuyệt vời của JOIN và UNION. Tôi nghĩ rằng tôi đầu tiên hiểu sai họ và tôi cần phải tái cơ cấu điều này. –

+4

Tôi đã thêm chi tiết hơn một chút về 'JOIN' và' UNION'. – ErikE

+0

và tôi sẽ thêm +1 cho phiên bản chính xác của 'union' sử dụng' nhóm bởi' và 'có'. Đó là cách chúng tôi được dạy mọi thứ ở trường (cùng với các giáo viên luôn nói "không sử dụng công đoàn hoặc các truy vấn phụ, tham gia FTW!") – zmo

5

phần lớn thời gian một union có thể đạt được bằng cách thực hiện một tham gia:

SELECT nombre 
    FROM internados 
UNION 
SELECT nombre 
    FROM universidades 
WHERE nombre = ? 

sẽ tốt hơn:

SELECT nombre 
    FROM internados i 
    JOIN universidades u 
    ON i.nombre = u.nombre 
    AND nombre = ? 

đó là cách đơn giản để đọc. (bạn cũng có thể sử dụng cú pháp JOIN, nhưng tôi thích tham gia thủ công cũ hơn).

Nhưng cho dù đây là một union hoặc một join, hãy luôn nhớ rằng cả hai bảng được sáp nhập trong kết quả:

nombre | todo | becas | fotos | ... | contenido | becas | ... 

nên về cơ bản, khi bạn đặt một điều kiện trên nombre, bạn sẽ nhận được một trong hai sản phẩm nào hoặc tên bạn đã đặt cho truy vấn. Nhưng theo cách bạn đã viết công đoàn của mình, chỉ tập hợp thứ hai mới được áp dụng điều kiện where, không phải là điều kiện đầu tiên. Bạn phải đặt điều kiện trên cả các truy vấn của đoàn:

SELECT nombre 
    FROM internados 
WHERE nombre = ? 
UNION 
SELECT nombre 
    FROM universidades 
WHERE nombre = ? 
+3

Tham gia không kiểu ANSI kiểu cũ? Vào 2013!?!? Những gì được thế giới sắp tới? Tôi không thể đề nghị điều này. – ErikE

+3

ok, ok, sửa lỗi này, bạn đúng đó là thời gian tôi nhận được trong thế kỷ XXI của SQL ;-) – zmo

+3

Tôi đã được histrionic, nhưng cảm ơn bạn đã lắng nghe. :) – ErikE

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