L'optimisation d'une requête MySQL avec une clause grande IN () ou se joindre à la table dérivée

StackOverflow https://stackoverflow.com/questions/2091777

Question

Disons que je dois interroger les associés d'une société. J'ai une table, des « transactions », qui contient des données sur toutes les transactions effectuées.

CREATE TABLE `transactions` (
  `transactionID` int(11) unsigned NOT NULL,
  `orderID` int(11) unsigned NOT NULL,
  `customerID` int(11) unsigned NOT NULL,
  `employeeID` int(11) unsigned NOT NULL, 
  `corporationID` int(11) unsigned NOT NULL,
  PRIMARY KEY (`transactionID`),
  KEY `orderID` (`orderID`),
  KEY `customerID` (`customerID`),
  KEY `employeeID` (`employeeID`),
  KEY `corporationID` (`corporationID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Il est assez simple d'interroger ce tableau pour les associés, mais il y a une torsion: Un enregistrement de la transaction est enregistrée une fois par employé, et donc il peut y avoir plusieurs enregistrements pour une société par commande

.

Par exemple, si les employés A et B de 1 société ont tous deux été impliqués dans la vente d'un aspirateur à 2 société, il y aurait deux enregistrements de la table « transactions »; un pour chaque employé, et tant pour les sociétés 1. Cela ne doit pas affecter les résultats, cependant. Un commerce de société 1, quel que soit le nombre de ses employés ont été impliqués, doit être traité comme un.

Facile

, je pensais. Je vais juste faire une jointure sur une table dérivée, comme suit:

SELECT corporationID FROM transactions JOIN (SELECT DISTINCT orderID FROM transactions WHERE corporationID = 1) AS foo USING (orderID)

La requête renvoie une liste des sociétés qui ont été impliqués dans les métiers avec société 1. C'est exactement ce que j'ai besoin, mais il est très lent parce que MySQL ne peut pas utiliser l'index corporationID pour déterminer la table dérivée. Je comprends que cela est le cas pour tous les sous-requêtes / tables dérivées dans MySQL.

J'ai aussi essayé d'interroger une collection de OrderIDs séparément et utiliser une ridiculement grande clause IN () (typhically 100 000 + ID), mais il se trouve que MySQL a des problèmes en utilisant des indices sur les clauses ridiculement grande (IN) comme bien et par conséquent le temps de requête n'améliore pas.

Y at-il d'autres options disponibles, ou je les ai épuisé les deux?

Était-ce utile?

La solution

Si je comprends bien vos besoins, vous pouvez essayer cela.

select distinct t1.corporationID
from transactions t1
where exists (
    select 1
    from transactions t2
    where t2.corporationID =  1
    and t2.orderID = t1.orderID)
and t1.corporationID != 1;

ou ceci:

select distinct t1.corporationID
from transactions t1
join transactions t2
on t2.orderID = t1.orderID
and t1.transactionID != t2.transactionID
where t2.corporationID = 1
and t1.corporationID != 1;

Autres conseils

Vos données n'a pas de sens pour moi, je pense que vous utilisez corporationID où vous dire ID client à un moment donné là-bas, que votre requête joint la table de transaction à la table de transaction pour corporationID = 1 sur la base orderID pour obtenir les corporationIDs ... qui serait alors 1, droit?

Pouvez-vous s'il vous plaît préciser ce que le customerID, employeeID et corporationIDs signifient? Comment puis-je savoir les employés A et B de 1 société - dans ce cas, est la société 1 corporationID et société 2 est le client, et ainsi remisée dans le customerID

Si tel est le cas, il vous suffit de faire un groupe par:

SELECT customerID
FROM transactions
WHERE corporationID = 1
GROUP BY customerID

(ou sélectionnez et par groupe orderID si vous voulez une ligne par commande au lieu d'une ligne par client.)

En utilisant le groupe par, vous ignorez le fait qu'il ya plusieurs enregistrements qui sont en double, sauf pour le employeeID.

A l'inverse, les rendements de toutes les sociétés qui ont vendu à une société 2.

SELECT corporationID
FROM transactions
WHERE customerID = 2
GROUP BY corporationID
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top