11
votes

SQL "groupe par" problème

Je concevons un panier d'achat. Pour contourner le problème des anciennes factures montrant des prix inexacts après la modification du prix d'un produit, j'ai déplacé le champ de prix de la table des produits en une table de produits de produits composé de 3 champs, PID, date et prix. PID et date forment la clé primaire de la table. Voici un exemple de ce que la table ressemble à: xxx pré>

à l'aide de sélectionnez code> et groupe par code> pour trouver le dernier prix de chaque produit, je est venu avec: p> xxx pré>

La date et le PID renvoyé étaient exacts. J'ai reçu exactement 1 entrée pour chaque PID unique et la date qui l'a accompagnée était la dernière date de cette PID. Cependant, ce qui est arrivé comme une surprise était le prix renvoyé. Il a renvoyé le prix de la première rangée correspondant au PID, ce qui était dans ce cas 50. P>

Après avoir retravaillé ma déclaration, je suis venu avec ceci: p>

SELECT pp.pid, pp.price, pp.date FROM ProductPrice AS pp
INNER JOIN (
    SELECT pid AS lastPid, max(date) AS lastDate FROM ProductPrice GROUP BY pid
) AS m
ON pp.pid = lastPid AND pp.date = lastDate


1 commentaires

Plus simple, bien que sur PostgreSQL uniquement: Sélectionnez Distinct sur (PID) PID, date, prix de Productprice Commander par pid, date de descendance


7 Réponses :


1
votes

Vous voudrez peut-être essayer ceci:

SELECT pid, price, date FROM ProductPrice GROUP BY pid ORDER BY date DESC


1 commentaires

Cela ne fonctionnera pas. Il commande la table résultante par date descendante, pas la table d'origine, le dernier prix ne sera pas sélectionné.



3
votes

Je pense que vous avez enfreint votre schéma de base de données.

Pour contourner le problème des anciennes factures montrant des prix inexacts Après modification du prix d'un produit, j'ai déplacé le champ de prix de la table de produits dans une table de produits de produit composé de 3 champs, PID, date et prix. PID et date forment la clé primaire de la table.

Comme vous l'avez souligné, vous devez conserver une histoire de changement de prix. Mais vous pouvez toujours garder le prix actuel dans la table des produits en plus de cette nouvelle table. Cela rendrait votre vie beaucoup plus facile (et vos requêtes plus rapidement).


0 commentaires

9
votes

La raison pour laquelle vous obtenez un prix arbitraire est que MySQL ne peut pas savoir quelles colonnes à sélectionner si vous groupe par code> quelque chose. Il sait qu'il a besoin un em> prix et a em> date par pid et peut aller chercher la date la plus dernière que vous avez demandée avec max (date) code> mais choisit de revenir Un prix qui est le plus efficace pour lui de récupérer - vous n'avez pas fourni de fonction globale pour cette colonne (votre première requête n'est pas valide SQL, réellement.)

Votre deuxième requête semble ok, mais voici une alternative plus courte: P>

SELECT pid, price, date
FROM ProductPrice p
WHERE date = (SELECT MAX(date) FROM ProductPrice tmp WHERE tmp.pid = p.pid)


2 commentaires

D'autres SGBD se plainent que le prix n'est pas inclus en tant qu'agrégation ou en tant que groupement.


Je dois convenir que cela est beaucoup plus propre.



0
votes

Voici une autre-personne inefficace - un: xxx


0 commentaires

0
votes

Je pense que la clé ici est simple sondage Query - Vous pouvez voir ce que vous voulez, mais les ordinateurs ne sont pas humains et afin de produire le résultat souhaité à partir d'opérations basées sur définies, vous devez être explicite. Dans la deuxième requête.

La requête interne identifie le dernier prix pour chaque produit, puis la requête externe vous permet d'obtenir la valeur du dernier prix - c'est à peu près aussi simple que possible.

En tant que mis à part, si vous avez un système de facturation, vous devez vraiment stocker le prix du produit (et les taux d'imposition ainsi que les «codes») avec la facture, c'est-à-dire que les tables de facturation doivent contenir tous les besoins financiers nécessaires. informations pour reproduire la facture. En général, vous ne veulent pas vouloir compter sur la possibilité de rechercher un prix (ou un taux d'imposition) dans une table mutable, même permettant au système introduit comme ci-dessus. Indépendamment de cela que l'histoire de la tarification a son propre mérite.


0 commentaires

1
votes

Vous ne pouvez pas résoudre votre problème avec le groupe par clause, car pour chaque groupe de PID MySQL cherchera simplement la première PID, la date maximale et le premier prix trouvé (ce dont vous avez besoin).

Vous pouvez Utilisez une sous-requête (qui peut être inefficace): xxx

ou vous pouvez simplement rejoindre la table avec elle-même: xxx

Jetez un coup d'œil à Cette section < / a> de MySQL DOCS.


0 commentaires

0
votes

J'ai fait face au même problème dans l'un de mes projets, j'ai utilisé la sous-requête pour aller chercher la date, puis le comparer, mais cela rend le système lent lorsque les données augmentent. Donc, il est préférable de stocker le dernier prix de votre tableau en plus de la nouvelle table que vous avez créée pour conserver l'historique des changements de prix.

Vous pouvez toujours utiliser l'une quelconque de la requête PPL suggérée pour obtenir le dernier prix du produit à une date particulière. Mais aussi, vous pouvez ajouter un champ dans la même table est le plus dernier. Donc, pour une date, vous pouvez rendre le drapeau vrai une fois. et vous pouvez toujours trouver le dernier prix du produit pour une date particulière par une simple requête.


0 commentaires