9
votes

Joindre à gauche revenant plus que prévu

Utilisation de la requête suivante

select *
from table1
left join table2 on table1.name = table2.name


13 commentaires

Les lignes supplémentaires sont-elles retournées avec des valeurs null?


S'il y a un lien entre tout le nom dans les lignes TBL1 et les lignes de TBL2, la requête retournera 35 rangées.


Je dirais que la relation entre table et table2 est un à plusieurs . Est-ce le cas?


@oshirowanen Dans ce cas, vous devrez fournir davantage de conditions précisant la manière dont vous vous attendez à ce que les résultats soient limités.


Sans voir les données, il est difficile de vous donner une réponse complète. Cependant, cela ressemble à au moins certaines de vos 16 lignes dans TABLE1 relient à plusieurs lignes dans Table2 .


@Phil, Fondamentalement, si Table1 contient 1 nom que "Oshirowanen" et Table2 contient 3 noms comme "Oshirowanen", ceux-ci doivent être comptés comme 1 dans le tableau2. Je pensais que la jointure de gauche ferait cela, mais clairement je me suis trompé.


@oshirowanen, comment vous attendez-vous à MySQL "Comptez 3 lignes comme 1"?


Ils sont trois rangées différentes avec trois ensembles de données différents, comment voulez-vous qu'ils soient effondrés? MySQL peut les grouper et exécuter des fonctions agrégées, mais vous devez préciser d'abord comment les agrégats sont censés travailler.


@oshirowanen "comme 1" quoi? Vous devrez donner quelques exemples de données des deux tables et de ce que vous attendez que le résultat de la requête ressemble.


@Ben Lee, je pensais que si la jointure avait 1 de la gauche et 3 à partir de la droite, cela compterait comme 1 rejoindre.


@oshirowanen, non. Joindre gauche Retourne une copie du tableau 1 pour chaque copie dans le tableau2.


Parce que table2 a plusieurs enregistrements avec le même champ Nom.


Oui, et je veux une affectation individuelle en fonction de certains paramètres


7 Réponses :


17
votes

La join gauche peut renvoyer plusieurs copies des données de la table1, si la clé étrangère pour une ligne du tableau 1 est référencée par plusieurs rangées dans le tableau2.

Si vous voulez seulement retourner 16 lignes, une pour chaque table 1 rangée, et avec un ensemble de données aléatoires pour le tableau 2, vous pouvez utiliser simplement un groupe ordinaire par: xxx

groupe par des lignes d'agrégats basées sur Un champ, cela va donc réduire tous les doublons de la table1 dans une rangée. Généralement, vous spécifiez des fonctions globales pour expliquer comment les lignes devraient s'effondrer (par exemple, pour une ligne de numéros, vous pourriez l'effondrer à l'aide de SUM () de sorte que la première ligne serait le total). Si vous voulez juste une ligne aléatoire, ne spécifiez aucune fonction d'agrégat. MySQL va par défaut, choisissez simplement une ligne (note que celle-ci est spécifique à MySQL, la plupart des bases de données vous demanderont de spécifier des agrégats lorsque vous groupe). La façon dont il choisit n'est pas techniquement "aléatoire", mais ce n'est pas nécessairement prévisible pour vous. Je suppose que par "aléatoire", vous voulez vraiment dire "toute ligne fera".


8 commentaires

Une rangée aléatoire de la table2, tant que le nom de Table1 correspond à Nom du tableau2.


D'accord: L'OP doit nous montrer que les données source utilisées et la sortie souhaitée.


@oshirowanen, j'ai mis à jour pour expliquer comment obtenir seulement 16 rangées, en choisissant une seule ligne pour chaque association de table2.


@Benlee Merci d'information, je ne connaissais pas ce comportement de MySQL.


@Sergeykudriadvtsev, notez que je viens de clarifier les détails. MySQL ne retournera pas une ligne aléatoire par défaut, mais il retournera une seule ligne par défaut, et pas nécessairement de manière prévisible. Donc, si vous venez de «n'importe quelle ligne fera», vous pouvez utiliser cette méthode. Si vous avez besoin d'une ligne vraiment aléatoire, c'est une requête beaucoup plus complexe.


Conseil: j'ai ajouté un champ d'incrémentation unique unique à utiliser dans le groupe par déclaration. C'était parce que la table de gauche dans la jointure n'avait pas un seul champ unique.


Le problème peut être lorsque vous devez disposer de tous les résultats commandés par un FieldX dans le tableau2, mais groupé par le fibrey dans le tableau1. Je suis coincé à ce stade.


@Decadenza Avez-vous réellement besoin de COMMANDER par FieldX dans TABLE-TABLE2? Ou une fonction d'agrégation simple ferait-elle? Par exemple, si vous souhaitez trouver la ligne avec le premier alphabétique table2.name mais groupé par une ligne sur la table1, vous pouvez sélectionner l'agrégat min (nom2.name) . Semblable pour les autres types de données en plus des chaînes.



0
votes

Si la colonne Nom n'est pas unique dans les tables, vous pouvez simplement avoir des doublons sur la table2.

Essayez d'exécuter: xxx

si vous n'obtenez aucun résultat Les doublons sur la colonne Nom sont la raison des lignes supplémentaires revenant.


0 commentaires

7
votes

Supposons que vous disposions des tableaux suivants:

select tbl1.Name, SOME_AGGREGATE_FUNCTION(tbl2.specific_field), ...
from table1
left join table2 on table1.name = table2.name
GROUP BY tbl1.Name


0 commentaires

-2
votes

Selon votre commentaire "Une rangée aléatoire de la table2, tant que le nom de la table1 correspond à partir du nom de Table2", vous pouvez utiliser ce qui suit: XXX

Notez que le top 1 n'est pas MySQL mais c'est pour SQL Server


1 commentaires

MySQL utilise limite . Aussi, où est le hasard?



2
votes

Un moyen d'utiliser ceci consiste à utiliser la puissance de SQL distincte.

select distinct tbl1.id, *
from table1 tbl1
left join table2 tbl2 on tbl2.name = tbl1.name

where
 ....................


0 commentaires

0
votes

La duplication peut être une raison. Voir exemple dans la poste
https://alexpetralia.com/ Messages / 2017/7/19 / plus-Dangerous-Subtleties-of-Sunins-in-SQL


0 commentaires

0
votes

Si vous souhaitez rejoindre la dernière ligne relative la plus récente / la plus proche de la table droite, vous pouvez limiter les données de jointure à l'aide de la touche principale min / max , puis limitant à 1 rangée à l'aide de groupe < / code> Comme ceci: xxx

et rappelez-vous N'utilisez pas * pour une jointure gauche car elle désactive min / max et retourne toujours la première rangée.


0 commentaires