Bạn có thể kết hợp nhiều truy vấn với UNION
, nhưng chỉ khi các truy vấn có cùng số cột. Lý tưởng nhất là các cột giống nhau, không chỉ về kiểu dữ liệu, mà còn về ý nghĩa ngữ nghĩa của chúng; tuy nhiên, MySQL không quan tâm đến ngữ nghĩa và sẽ xử lý các kiểu dữ liệu khác nhau bằng cách truyền đến một thứ gì đó chung chung hơn - vì vậy nếu cần, bạn có thể nạp chồng các cột để có các ý nghĩa khác nhau từ mỗi bảng, sau đó xác định ý nghĩa nào phù hợp trong mã cấp cao hơn của bạn (mặc dù tôi không khuyên bạn nên làm theo cách này).
Khi số lượng cột khác nhau hoặc khi bạn muốn đạt được sự liên kết dữ liệu tốt hơn / ít bị quá tải hơn từ hai truy vấn, bạn có thể chèn các cột chữ giả vào SELECT
của mình các câu lệnh. Ví dụ:
SELECT t.cola, t.colb, NULL, t.colc, NULL FROM t;
Bạn thậm chí có thể có một số cột dành riêng cho bảng đầu tiên và những cột khác cho bảng thứ hai, chẳng hạn như chúng là NULL
ở nơi khác (nhưng hãy nhớ rằng tên cột đến từ truy vấn đầu tiên, vì vậy bạn có thể muốn đảm bảo rằng tất cả chúng đều được đặt tên ở đó):
SELECT a, b, c, d, NULL AS e, NULL AS f, NULL AS g FROM t1
UNION ALL -- specify ALL because default is DISTINCT, which is wasted here
SELECT NULL, NULL, NULL, NULL, a, b, c FROM t2;
Bạn có thể thử căn chỉnh hai truy vấn của mình theo cách này, sau đó kết hợp chúng với một UNION
nhà điều hành; bằng cách áp dụng LIMIT
tới UNION
, bạn sắp đạt được mục tiêu của mình:
(SELECT ...)
UNION
(SELECT ...)
LIMIT 10;
Vấn đề duy nhất còn lại là, như đã trình bày ở trên, 10 bản ghi trở lên từ bảng đầu tiên sẽ "đẩy ra" bất kỳ bản ghi nào từ bảng thứ hai. Tuy nhiên, chúng tôi có thể sử dụng ORDER BY
trong truy vấn bên ngoài để giải quyết vấn đề này.
Kết hợp tất cả lại với nhau:
(
SELECT
dr.request_time AS event_time, m.member_name, -- shared columns
dr.request_id, dr.member1, dr.member2, -- request-only columns
NULL AS alert_id, NULL AS alerter_id, -- alert-only columns
NULL AS alertee_id, NULL AS type
FROM dating_requests dr JOIN members m ON dr.member1=m.member_id
WHERE dr.member2=:loggedin_id
ORDER BY event_time LIMIT 10 -- save ourselves performing excessive UNION
) UNION ALL (
SELECT
da.alert_time AS event_time, m.member_name, -- shared columns
NULL, NULL, NULL, -- request-only columns
da.alert_id, da.alerter_id, da.alertee_id, da.type -- alert-only columns
FROM
dating_alerts da
JOIN dating_alerts_status das USING (alert_id, alertee_id)
JOIN members m ON da.alerter_id=m.member_id
WHERE
da.alertee_id=:loggedin_id
AND da.type='platonic'
AND das.viewed='0'
AND das.viewed_time<da.alert_time
ORDER BY event_time LIMIT 10 -- save ourselves performing excessive UNION
)
ORDER BY event_time
LIMIT 10;
Tất nhiên, bây giờ bạn phải xác định loại hàng bạn đang xử lý khi đọc từng bản ghi trong tập kết quả (khuyên bạn nên kiểm tra request_id
và / hoặc alert_id
cho NULL
các giá trị; cách khác, người ta có thể thêm một cột bổ sung vào kết quả cho biết rõ ràng mỗi bản ghi bắt nguồn từ bảng nào, nhưng nó phải tương đương với điều kiện id
đó các cột NOT NULL
).