2
votes

Accélérer la requête Access 2016

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");

Table: entrez la description de l'image ici


0 commentaires

4 Réponses :


0
votes

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)


4 commentaires

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.



0
votes

Vous devez simplifier votre requête. Essaye ça:

SELECT * FROM AddDateLeagueSeasontoScorecardBatting WHERE League = "Indian Premier League" or League = "Big Bash League"


1 commentaires

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.



1
votes

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.


0 commentaires

1
votes

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


6 commentaires

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.