1
votes

MySQL joignant des tables et renvoyant la dernière ligne de la deuxième table lorsque la comparaison est faite entre des valeurs identiques

J'ai le tableau 1: les utilisateurs

SELECT u.id, u.name, p.title 
FROM users AS u 
LEFT JOIN posts AS p 
ON p.user_id= u.id 
WHERE p.posted = ( SELECT MAX(posted) FROM posts WHERE user_id = u.id )
ORDER BY u.id 
LIMIT 15

Et le tableau deux appelé posts:

id | user_id |     title    |   posted

1  |    1    | Something    | 1551128761
2  |    1    | Else         | 1551128761
3  |    3    | Some Title   | 1551122745
4  |    2    | Demo Title   | 1551129777
5  |    3    | Something    | 1551126793

user_id dans le deuxième tableau est l'id de l'utilisateur du premier tableau

J'ai besoin de sortir le dernier message du tableau et je le fais actuellement en utilisant cette requête:

id | name |

1  | john |
2  | garry|
3  | sam  |

Mais le problème avec cette requête est que si l'horodatage est le même pour le même utilisateur (dans cet exemple pour l'utilisateur avec user_id 1 , l'horodatage est le même), j'obtiens ces deux lignes à la place du dernier (le dernier a l'ID le plus élevé)


4 commentaires

ON p.ticker_id = u.id ne devrait-il pas être ON p.user_id = u.id ?


@Utkanos modifier l'erreur, merci


J'ai les données devant moi et j'obtiens ces deux lignes, mais si j'ajoute une seconde à l'une ou l'autre de ces deux lignes, je n'en reçois qu'une (ce qui est exactement ce dont j'ai besoin


Essayez DISTINCT dans votre partie de sélection, avant u.id


3 Réponses :


2
votes

Essayez cette requête MySQL:

ALTER TABLE posts ADD INDEX(user_id);
ALTER TABLE posts ADD INDEX(posted);

Testé et fonctionne très bien. Voici une démo: DBFiddle

Pour accélérer sélectionnez la requête , pensez à ajouter des indexes

SELECT u.id, 
       u.name, 
       p.title 
FROM   users AS u 
       JOIN posts AS p 
         ON p.id = (SELECT pi.id 
                    FROM   posts AS pi 
                    WHERE  pi.user_id = u.id 
                    ORDER  BY pi.id DESC 
                    LIMIT  1); 


8 commentaires

8000 comme pour le moment - cela prend environ 2 secondes avec mon ancien et environ 25 secondes avec celui-ci, mais le vôtre fait vraiment ce dont j'ai besoin


Suggestion: l'index utile est sur les articles (user_id, posté, id) .. essayez d'indexer et vérifiez à nouveau la vitesse


comment dois-je faire ça?


Si vous utilisez PHPMyAdmin pour afficher la structure de votre table, vous devriez pouvoir voir différents onglets en cliquant sur un nom de table. Cliquez sur Structure> Index dans chaque ligne pour ajouter des index sinon exécutez des requêtes SQL pour les trois colonnes comme celle-ci: ALTER TABLE posts ADD INDEX (user_id);


Ok, je l'ai fait comme tu l'as dit, ça va plus vite que jamais, merci!


Petite question, id n'est-il pas déjà indexé? (c'est la clé primaire et incrémentée automatiquement)


Oui, pas besoin d'ajouter un index sur les clés primaires - elles sont déjà indexées :)


un index fonctionnera-t-il si les données de la colonne ne sont pas uniques?



0
votes

Que diriez-vous de restructurer légèrement la requête?

SELECT posts.title, users.id, users.name
FROM posts, users 
WHERE posts.user_id = users.id 
ORDER BY posts.posted DESC, posts.id DESC
LIMIT 1

Essentiellement en sélectionnant parmi les articles, en triant par l'horodatage publié et deuxièmement par l ' id de le message dans l'ordre décroissant au cas où l'horodatage serait le même.


0 commentaires

1
votes

Une option utilisant la colonne id de la table des articles comme suit. Cela suppose que l'identifiant sera différent pour chaque enregistrement de publication dans la table des publications. Démo ici

SELECT u.id, u.name, p.title,p.posted
FROM users AS u 
LEFT JOIN posts AS p 
ON p.user_id= u.id 
WHERE (p.posted,p.id) = ( SELECT MAX(posted),MAX(id) FROM posts WHERE user_id = u.id )
ORDER BY u.id


5 commentaires

salut @vmaroli, cela fonctionne mais cela prend le temps de requête de 2 secondes à ~ 25 secondes :(


La colonne id est-elle la clé primaire ou possède-t-elle un index unique dans la table des publications? Si votre identifiant pour les publications est unique et garanti dans un ordre croissant, vous pouvez filtrer par identifiant au lieu de l'horodatage. Voir dbfiddle.uk/... Cela devrait donner de bien meilleures performances car il s'agit d'un accès par index / clé primaire unique


La colonne id est un auto_increment unique pour les deux tables. dans le post de table, j'identifie les messages / utilisateur par user_id qui peut être plus d'un (pas unique) - pour chaque message publié par cet utilisateur


Alors le SQL mentionné dans mon commentaire précédent devrait fonctionner correctement? Étant donné que son accès à l'aide de la clé primaire doit également être rapide.


Oui, c'est le cas et je l'utilise. J'ai juste utilisé celui ci-dessus en premier jusqu'à ce que j'aie atteint celui-ci, donc j'ai déjà "préféré" celui-là. Mais encore une fois, j'utilise celui-ci