MySQL - la Combinaison de deux instructions select dans une suite avec LIMITE efficacement
Pour une application de rencontre, j'ai quelques tableaux que j'ai besoin de requête pour une sortie unique avec une LIMITE de 10 de deux requêtes combinées. Il semble difficile pour le moment, même si ce n'est pas un problème de les interroger séparément, mais la LIMITE de 10 ne fonctionne pas comme les chiffres ne sont pas précis (ex. pas de LIMITE de 5 et de LIMITER à 5, une requête peut retourner 0 lignes, alors que les 10 autres, selon le scénario).
members table
member_id | member_name
------------------------
1 Herb
2 Karen
3 Megan
dating_requests
request_id | member1 | member2 | request_time
----------------------------------------------------
1 1 2 2012-12-21 12:51:45
dating_alerts
alert_id | alerter_id | alertee_id | type | alert_time
-------------------------------------------------------
5 3 2 platonic 2012-12-21 10:25:32
dating_alerts_status
status_id | alert_id | alertee_id | viewed | viewed_time
-----------------------------------------------------------
4 5 2 0 0000-00-00 00:00:00
Imaginez que vous êtes Karen et connecté, vous devriez voir ces 2 articles:
1. Herb requested a date with you.
2. Megan wants a platonic relationship with you.
Dans une requête avec une LIMITE de 10. Au lieu de cela, ici, sont deux requêtes qui doivent être combinés:
1. Herb requested a date with you.
-> query = "SELECT dr.request_id, dr.member1, dr.member2, m.member_name
FROM dating_requests dr
JOIN members m ON dr.member1=m.member_id
WHERE dr.member2=:loggedin_id
ORDER BY dr.request_time LIMIT 5";
2. Megan wants a platonic relationship with you.
-> query = "SELECT da.alert_id, da.alerter_id, da.alertee_id, da.type,
da.alert_time, m.member_name
FROM dating_alerts da
JOIN dating_alerts_status das ON da.alert_id=das.alert_id
AND da.alertee_id=das.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 da.alert_time LIMIT 5";
Encore une fois, parfois deux tables peut être vide, ou 1 table peut être vide ou plein (d'où la LIMITE de 10 coups de pied) et commandé par le temps. Des idées sur comment pour obtenir une requête pour effectuer cette tâche de manière efficace? Des pensées, des conseils, des carillons, des optimisations sont les bienvenus.
UNION
et de faire toute chose une sous-requête pour une requête externe qui effectue la LIMIT
. Sinon, vous pouvez déterminer la condition de LIMIT
à appliquer à la deuxième requête de (10 moins le nombre d'enregistrements renvoyés par la première requête) - il est probablement plus facile de le faire dans la langue que vous utilisez pour appeler les requêtes.Créer un tableau avec les résultats que vous attendiez. Vous verrez le problème.
Il n'est pas possible de combiner les 2 requêtes différentes listes de sélection.
les colonnes retournées sont différents, de sorte que les règles de l'UNION. La deuxième option sonne mieux (pour soustraire le reste), mais je tiens à les mélanger, de sorte que le moment est chronologique. C'est un peu un défi!
Avoir soumis ma réponse ci-dessous, il me semble que peut-être toute cette situation pourrait être évitée par la normalisation de vos données d'une touche: avoir une table supplémentaire de
events
qui enregistre à la fois requests
et alerts
, rejoignez alors que les données pertinentes, selon le cas.
OriginalL'auteur Wonka | 2012-04-25
Vous devez vous connecter pour publier un commentaire.
Vous pouvez combiner plusieurs requêtes avec
UNION
, mais seulement 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 sens sémantique; toutefois, MySQL ne se soucie pas de la sémantique et gérer différents types de données sur la coulée jusqu'à quelque chose de plus générique, donc, si nécessaire, vous pourrait surcharge les colonnes d'avoir différentes significations de chaque table, puis de déterminer quel est le sens approprié à votre niveau plus élevé de code (bien que je ne recommande pas de faire de cette façon).Lorsque le nombre de colonnes diffère, ou lorsque vous souhaitez obtenir une meilleure/moins surchargée d'alignement de données à partir de deux requêtes, vous pouvez insérer un littéral de colonnes dans votre
SELECT
consolidés. Par exemple:Vous pourriez même avoir un peu de colonnes réservées pour le premier tableau, et d'autres pour le deuxième tableau, tels qu'ils sont
NULL
ailleurs (mais n'oubliez pas que les noms de colonne proviennent de la première requête, de sorte que vous pouvez vous assurer qu'ils sont tous nommés):Vous pourriez essayer d'aligner vos deux questions dans ce mode, puis de les combiner avec un
UNION
de l'opérateur; en appliquantLIMIT
à laUNION
, vous êtes proche de la réalisation de votre objectif:La seule question qui demeure, c'est que, tel que présenté ci-dessus, 10 ou plusieurs enregistrements de la première table "pousser" des enregistrements à partir de la seconde. Cependant, nous pouvons utiliser un
ORDER BY
dans la requête externe de résoudre ce problème.Mettant tous ensemble:
Bien sûr, maintenant c'est à vous de déterminer quel type de ligne que vous avez à traiter avec que vous lisez chaque enregistrement dans le jeu de résultats (vous suggérons de tester
request_id
et/oualert_id
pourNULL
valeurs; à l'inverse, on pourrait ajouter une colonne supplémentaire pour les résultats qui énonce explicitement à partir de la table dans laquelle chaque enregistrement d'origine, mais il doit être équivalent à condition que cesid
colonnes sontNOT NULL
).On dirait que vous devriez être en mesure de réaliser cela avec un
ORDER BY
dans la requête externe - laissez-moi savoir si vous ne pouvez pas comprendre.Tu veux dire de l'ORDRE DE [time_here] LIMITE de 10? Quid des requêtes à l'intérieur, il suffit de déposer la COMMANDE PAR le dr.request_time LIMITE de 5 et de l'ORDRE PAR da.alert_time LIMITE de 5? Pouvez-vous me montrer ce que la requête finale pourrait ressembler à mes questions donc je suis confiant?
Ma solution proposée ci-dessus.
Semble comme il se doit le faire. Merci pour votre explication détaillée et aider eggyal!
OriginalL'auteur eggyal