Możesz łączyć wiele zapytań za pomocą UNION
, ale tylko wtedy, gdy zapytania mają taką samą liczbę kolumn. Najlepiej byłoby, gdyby kolumny były takie same, nie tylko pod względem typu danych, ale także ich znaczenia semantycznego; jednak MySQL nie dba o semantykę i będzie obsługiwał różne typy danych, rzutując na coś bardziej ogólnego - więc w razie potrzeby możesz przeciąż kolumny, aby miały różne znaczenia z każdej tabeli, a następnie określ, jakie znaczenie jest odpowiednie w kodzie wyższego poziomu (chociaż nie polecam robienia tego w ten sposób).
Gdy liczba kolumn jest różna lub gdy chcesz uzyskać lepsze/mniej przeciążone wyrównanie danych z dwóch zapytań, możesz wstawić kolumny fikcyjne literału do SELECT
sprawozdania. Na przykład:
SELECT t.cola, t.colb, NULL, t.colc, NULL FROM t;
Możesz nawet mieć niektóre kolumny zarezerwowane dla pierwszej tabeli, a inne dla drugiej tabeli, tak aby były NULL
gdzie indziej (ale pamiętaj, że nazwy kolumn pochodzą z pierwszego zapytania, więc możesz chcieć się upewnić, że wszystkie są tam wymienione):
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;
Możesz spróbować wyrównać swoje dwa zapytania w ten sposób, a następnie połączyć je z UNION
operator; przez zastosowanie LIMIT
do UNION
, jesteś blisko osiągnięcia celu:
(SELECT ...)
UNION
(SELECT ...)
LIMIT 10;
Jedyną kwestią, która pozostaje, jest to, że, jak przedstawiono powyżej, 10 lub więcej rekordów z pierwszej tabeli „wypchnie” wszystkie rekordy z drugiej. Możemy jednak użyć ORDER BY
w zewnętrznym zapytaniu, aby rozwiązać ten problem.
Wszystko razem:
(
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;
Oczywiście teraz od Ciebie zależy określenie, z jakim typem wiersza masz do czynienia, czytając każdy rekord w zestawie wyników (sugeruj przetestowanie request_id
i/lub alert_id
dla NULL
wartości; alternatywnie można dodać do wyników dodatkową kolumnę, która wyraźnie określa, z której tabeli pochodzi każdy rekord, ale powinna być równoważna pod warunkiem, że te id
kolumny są NOT NULL
).