2010-08-12 6 views
4

Je veux trier mes résultats avant de les regrouper, mais je n'arrive pas à le faire.MySQl GROUP BY et ORDER BY ne pas faire ce que je veux

J'ai cette requête:

 
SELECT DISTINCT 
product.id, 
product_number_value.att_value AS product_number, 
color_number_value.option_code AS color_number, 
size_value.option_code AS size_code, 
size_value.option_position AS size_position 
FROM 
product 
INNER JOIN product_attribute_relational AS product_number_relational ON product_number_relational.product_id = product.id 
INNER JOIN product_att_varchar AS product_number_value ON product_number_relational.product_att_id = product_number_value.product_att_id 
INNER JOIN product_attribute_relational AS color_number_relational ON color_number_relational.product_id = product.id 
INNER JOIN product_att_select AS color_number_select ON color_number_relational.product_att_id = color_number_select.product_att_id 
INNER JOIN attribute_option_value AS color_number_value ON color_number_select.att_value = color_number_value.option_id 
INNER JOIN product_attribute_relational AS size_relational ON product.id = size_relational.product_id 
INNER JOIN product_att_select AS size_select ON size_relational.product_att_id = size_select.product_att_id 
INNER JOIN attribute_option_value AS size_value ON size_select.att_value = size_value.option_id 
WHERE 
product_number_relational.att_id = 1 AND 
color_number_relational.att_id = 2 AND 
size_relational.att_id = 3 AND 
product.id IN (365, 366, 367, 368, 369, 371, 372, 373, 374) 
ORDER BY 
product.id ASC 

Le résultat est le tableau suivant:

 
id product_number color_number size_code size_position 
365 F23740 311 S 24 
366 F23740 311 M 25 
367 F23740 311 L 26 
368 F23740 311 XL 27 
369 F23740 311 XS 23 
371 F23745 213 S 24 
372 F23745 213 M 25 
373 F23745 213 L 26 
374 F23745 213 XL 27 

Si le groupe I par product_number, je reçois color_number id et 371.
Mais je Je veux obtenir l'identifiant et 371, car je veux que les résultats soient classés en premier par size_position, avant de les regrouper.

Je n'ai vraiment aucune idée sur la façon d'y arriver?! ??

Quelqu'un peut-il m'aider s'il vous plaît ??

Merci!

+0

Pouvez-vous expliquer à quoi devrait ressembler le résultat? – Kwebble

+0

Merci à tous, je l'ai résolu avec une boucle à travers les données «non groupées» avec php. C'était vraiment la façon de jeûner. Merci encore! – Johan

Répondre

0

Essayez de commander par les deux colonnes:

... ORDER BY product.id, size_position ASC 

Il triera par id d'abord, puis par size_position.

+0

Pas exactement ce que je veux, mais merci! – Johan

2

Il s'agit d'un problème d'utilisation de colonnes non groupées dans une requête groupée. Généralement, c'est quelque chose à éviter. Certains moteurs de base de données vous empêchent de le faire car cela n'a pas de sens logique - si je veux product.id pour un groupe, mais quel est le moteur DB supposé choisir car il y a plusieurs options pour un seul groupe? ORDER BY est uniquement destiné à travailler sur des agrégats ou des colonnes groupées lors de l'utilisation d'un GROUP BY, mais je ne suis pas sûr que vous puissiez facilement agréger. Vous recherchez product.id pour la ligne avec MIN (size_position) dans le groupe. Je pense qu'une sous-requête pour isoler cette rangée pour chaque groupe pourrait être le seul moyen; Je ne peux pas penser à un moyen facile de m'en sortir.

EDIT

Mon instinct dans ces cas est toujours de le faire en deux étapes. Je ne suis pas un amusement de requêtes géantes géantes avec des sous-requêtes imbriquées, simplement parce que je les trouve illisibles. Vous avez une très longue requête sur un schéma normalisé, donc je ne vais pas essayer de décomposer la requête ici, je vais probablement faire une erreur.

La requête 1 pousserait numéro_produit, numéro_color et MIN (taille_position) (regroupement par numéro_produit, numéro_color) dans une table temporaire.

La requête 2 récupère ensuite le code_produit pour chaque numéro_produit, numéro_color, taille_position dans la table temporaire. De cette façon, vous pouvez faire une jointure directement sur la position de taille minimale. Les performances négatives de l'utilisation des tables temporaires sont surclassées dans de nombreux cas (pas toutes, mais certainement pour 99% des requêtes que j'ai effectuées au cours des 10 dernières années dans les applications de trading).

Il y a une autre possibilité impliquant une auto-jointure de sous-requête mais avec le schéma si fortement normalisé je pense que cela ne serait pas particulièrement avantageux à implémenter.

+0

Je pense que je sais ce que vous voulez dire, merci pour votre réponse. – Johan

1

Si vous regroupez par numéro_produit, numéro_color, les valeurs renvoyées pour l'ID de colonne sont indéterminées (car elles ne sont pas identiques pour chaque paire numéro_produit, paire nombre_color). Voir here pour une explication détaillée.Donc, vous dites "je veux trier mes résultats avant de les regrouper", pouvez-vous dire pourquoi vous voulez les regrouper? Exactement ce que vous voulez en tirer.

EDIT: après un commentaire:

SELECT DISTINCT 

product_number_value.att_value AS product_number, 
color_number_value.option_code AS color_number, 
min(size_value.option_position) AS sizePosition 
from ... 

group by product_number, color_number order by sizePosition 

Vous aurez la product_number, mais pas l'id.

+0

Je veux obtenir les produits qui ont le même numéro de produit et numéro de couleur, mais parce que ces combinaisons ont plusieurs tailles, je veux seulement la combinaison avec la plus petite taille. Je sais que le tri n'est pas le bon mot, car cela ne peut pas être fait avec SORT BY. Je comprends ça. – Johan