Vous pouvez combiner plusieurs requêtes avec UNION
, mais uniquement si les requêtes ont le même nombre de colonnes. Idéalement, les colonnes sont les mêmes, non seulement dans le type de données, mais aussi dans leur signification sémantique ; cependant, MySQL ne se soucie pas de la sémantique et gérera différents types de données en convertissant en quelque chose de plus générique - donc si nécessaire, vous pourriez surchargez les colonnes pour avoir des significations différentes de chaque table, puis déterminez quelle signification est appropriée dans votre code de niveau supérieur (bien que je ne recommande pas de le faire de cette façon).
Lorsque le nombre de colonnes diffère, ou lorsque vous souhaitez obtenir un alignement meilleur/moins surchargé des données de deux requêtes, vous pouvez insérer des colonnes littérales factices dans votre SELECT
déclarations. Par exemple :
SELECT t.cola, t.colb, NULL, t.colc, NULL FROM t;
Vous pourriez même avoir des colonnes réservées pour la première table et d'autres pour la deuxième table, de sorte qu'elles soient NULL
ailleurs (mais n'oubliez pas que les noms de colonne proviennent de la première requête, vous pouvez donc vous assurer qu'ils sont tous nommés ici) :
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;
Vous pouvez essayer d'aligner vos deux requêtes de cette manière, puis les combiner avec un UNION
opérateur; en appliquant LIMIT
à l'UNION
, vous êtes sur le point d'atteindre votre objectif :
(SELECT ...)
UNION
(SELECT ...)
LIMIT 10;
Le seul problème qui subsiste est que, comme présenté ci-dessus, 10 enregistrements ou plus de la première table "poussent" tous les enregistrements de la seconde. Cependant, nous pouvons utiliser un ORDER BY
dans la requête externe pour résoudre ce problème.
Rassembler le tout :
(
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;
Bien sûr, c'est maintenant à vous de déterminer à quel type de ligne vous avez affaire lorsque vous lisez chaque enregistrement dans le jeu de résultats (nous vous suggérons de tester request_id
et/ou alert_id
pour NULL
valeurs; alternativement, on pourrait ajouter une colonne supplémentaire aux résultats qui indique explicitement de quelle table provient chaque enregistrement, mais cela devrait être équivalent à condition que ces id
les colonnes sont NOT NULL
).