Du kan kombinere flere forespørgsler med UNION
, men kun hvis forespørgslerne har det samme antal kolonner. Ideelt set er kolonnerne de samme, ikke kun i datatype, men også i deres semantiske betydning; MySQL er dog ligeglad med semantikken og vil håndtere forskellige datatyper ved at lægge op til noget mere generisk - så om nødvendigt kan overbelast kolonnerne til at have forskellige betydninger fra hver tabel, og afgør derefter, hvilken betydning der er passende i din kode på højere niveau (selvom jeg ikke anbefaler at gøre det på denne måde).
Når antallet af kolonner er forskelligt, eller når du ønsker at opnå en bedre/mindre overbelastet justering af data fra to forespørgsler, kan du indsætte dummy literal-kolonner i din SELECT
udsagn. For eksempel:
SELECT t.cola, t.colb, NULL, t.colc, NULL FROM t;
Du kan endda have nogle kolonner reserveret til den første tabel og andre til den anden tabel, sådan at de er NULL
andre steder (men husk, at kolonnenavnene kommer fra den første forespørgsel, så du ønsker måske at sikre, at de alle er navngivet der):
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;
Du kan prøve at justere dine to forespørgsler på denne måde og derefter kombinere dem med en UNION
operatør; ved at anvende LIMIT
til UNION
, du er tæt på at nå dit mål:
(SELECT ...)
UNION
(SELECT ...)
LIMIT 10;
Det eneste problem, der er tilbage, er, at, som præsenteret ovenfor, 10 eller flere poster fra den første tabel vil "skubbe" alle poster ud fra den anden. Vi kan dog bruge en ORDER BY
i den ydre forespørgsel for at løse dette.
At sætte det hele sammen:
(
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;
Nu er det selvfølgelig op til dig at bestemme, hvilken type række du har at gøre med, når du læser hver post i resultatsættet (foreslå, at du tester request_id
og/eller alert_id
for NULL
værdier; alternativt kan man tilføje en ekstra kolonne til resultaterne, der udtrykkeligt angiver, fra hvilken tabel hver post stammer fra, men den bør være ækvivalent forudsat disse id
kolonner er NOT NULL
).