J'ai une requête qui contient entre autres des batsmanID et des noms de ligue (extrait ci-dessous). J'ai mis en place une autre requête pour renvoyer tous les disques où un batteur a joué dans chacune des deux ligues.
La requête fonctionne mais elle est très, très lente.
Il y a 48 000 enregistrements renvoyés dans la première requête, mais lorsque je l'utilise, il s'exécute instantanément.
Quelqu'un peut-il suggérer comment accélérer la nouvelle requête?
Merci
Requete:
SELECT * FROM AddDateLeagueSeasontoScorecardBatting WHERE League ="Indian Premier League" AND batsmanId IN (SELECT batsmanId FROM AddDateLeagueSeasontoScorecardBatting WHERE League ="Big Bash League") OR League ="Big Bash League" AND batsmanId IN (SELECT batsmanId FROM AddDateLeagueSeasontoScorecardBatting WHERE League ="Indian Premier League");
4 Réponses :
Essayez avec cette clause where:
WHERE batsmanId IN (SELECT batsmanId FROM AddDateLeagueSeasontoScorecardBatting GROUP BY batsmanId HAVING (League IN ("Indian Premier League","Big Bash League")) AND Count(*) = 2)
Merci Gustav, mais chacune des suggestions inclut des résultats pour le batteur qui n'a joué que dans l'une des deux ligues, pas seulement pour le batteur qui a joué dans les deux ligues.
Oui, tu as raison. J'ai modifié la réponse (code aérien uniquement, car je n'ai pas de données similaires à tester).
Merci Gustav. J'obtiens une erreur "Impossible d'avoir une fonction d'agrégation dans la clause WHERE". Voici comment je l'ai ajouté: SELECT * FROM AddDateLeagueSeasontoScorecardBatting WHERE batsmanId IN (SELECT batsmanId FROM AddDateLeagueSeasontoScorecardBatting WHERE (League IN ("Indian Premier League","Big Bash League")) AND Count(*) = 2 GROUP BY batsmandId);
J'ai encore fait une modification. Voir la réponse corrigée, s'il vous plaît.
Vous devez simplifier votre requête. Essaye ça:
SELECT * FROM AddDateLeagueSeasontoScorecardBatting WHERE League = "Indian Premier League" or League = "Big Bash League"
Merci Nick, mais cela inclut également les résultats pour le batteur qui n'a joué que dans l'une des deux ligues, pas seulement pour le batteur qui a joué dans les deux ligues.
Donc, vous êtes intéressé pour obtenir un batteur qui a joué dans les deux ligues. Il y a un problème de conception dans votre base de données. Pensez à votre requête: vous recherchez par valeurs de chaîne, ce qui est très lent, en particulier dans le cas où il existe d'autres valeurs possibles pour ces chaînes, qui sont très similaires à celle que vous recherchez. Vous auriez besoin de créer une table pour les ligues, où vous stockeriez le nom de la ligue, éventuellement avec d'autres attributs et un identifiant numérique.
Créez une foreign key
dans votre AddDateLeagueSeasontoScorecardBatting
faisant référence à l'ID de l'autre table nouvellement créée pour les ligues. Indexez votre clé étrangère afin que les recherches s'accélèrent considérablement. Vous devez savoir que vous aurez un prix à payer en performance lorsque des enregistrements sont insérés ou que la clé indexée change lors d'une mise à jour. Maintenant que vous avez un tableau de classement et une clé étrangère indexée qui y fait référence, essayez cette requête:
SELECT * FROM AddDateLeagueSeasontoScorecardBatting MAIN JOIN League IPL on IPL.Name = 'Indian Premier League' JOIN League BBL on BBL.Name = 'Big Bash League' WHERE EXISTS ( SELECT 1 FROM AddDateLeagueSeasontoScorecardBatting FIRST JOIN AddDateLeagueSeasontoScorecardBatting SECOND ON FIRST.batsmanId = SECOND.batsmanId AND FIRST.batsmanId = MAIN.batsmanId AND FIRST.LeagueId = IPL.LeagueId AND SECOND.LeagueId = BBL.LeagueId );
Remarque: vous voudrez probablement utiliser le mot-clé distinct
ou group by
, mais c'est une autre histoire.
Vous pouvez accomplir cela en utilisant des inner joins
sorte que la requête ne renvoie que les enregistrements avec un batman apparaissant dans les deux sous-requêtes:
select t1.* from AddDateLeagueSeasontoScorecardBatting t1 inner join ( select batsmanid from AddDateLeagueSeasontoScorecardBatting group by batsmanid having sum(League not in ("Indian Premier League", "Big Bash League")) = 0 and sum(League = "Indian Premier League") < 0 and sum(League = "Big Bash League") < 0 ) t2 on t1.batsmanid = t2.batsmanid
EDIT: Pour sélectionner les batteurs qui ont seulement joué dans les deux ligues en question (et aucune autre), vous pouvez essayer:
select t1.* from ( AddDateLeagueSeasontoScorecardBatting t1 inner join ( select distinct batsmanid from AddDateLeagueSeasontoScorecardBatting where League ="Indian Premier League" ) t2 on t1.batsmanid = t2.batsmanid ) inner join ( select distinct batsmanid from AddDateLeagueSeasontoScorecardBatting where League ="Big Bash League" ) t3 on t1.batsmanid = t3.batsmanid
Merci Lee, cela semble bon, mais cela renvoie des records pour d'autres ligues en plus de l'IPL et de la BBL.
@rob Vous ne souhaitez que les batteurs qui ont seulement joué dans IPL et BBL, par opposition aux batteurs qui ont joué dans ces deux entre autres?
Salut Lee, oui exactement ça. Merci
@rob Pourriez-vous s'il vous plaît essayer le SQL dans ma modification ci-dessus?
Salut Lee, merci pour cela. Je l'ai testé et il montre des batteurs qui ont joué soit en IPL soit en BBL, pas en IPL et en BBL.
@rob Apologies - Je l'ai révisé à nouveau.