2011-04-12 4 views
3

Assez similaire à MYSQL - select first 4 records for each category in a table mais il n'y a pas une réponse acceptée et la seule réponse n'a pas beaucoup de sens alors je demande à nouveau.Sélectionnez 2 produits de chaque catégorie dans MySQL

J'ai une table PRODUCTS avec 3 colonnes: ID, NAME et CATEGORY Ce que je voudrais savoir est maintenant si elle est du tout possible de sélectionner 2 produits pour chaque catégorie distincte sans effectuer des requêtes dans une boucle de PHP.

L'ordre des produits sélectionnés n'a pas d'importance, ils pourraient aussi bien être aléatoires. Mais il est important que je n'ai que 2 produits maximum par catégorie.

donc un bon résultat ensemble serait

ID ; NAME ; CATEGORY 
::::::::::::::::::::::: 
152 ; APPLE ; FRUIT 
185 ; ORANGE ; FRUIT 
145 ; BEEF ; MEAT 
141 ; PORK ; MEAT 
410 ; PEPSI ; DRINKS 
585 ; CARROT ; VEGETABLES 
585 ; TOMATO ; VEGETABLES 
+0

comment votre résultat est censé être? Mettez-le dans votre code pour mieux comprendre – Omid

Répondre

3

Quelque chose le long de ces lignes fonctionnera:

SELECT id, name, category 
FROM (
    SELECT *, 
     IF(@prev <> category, 
      @rownum := 1, 
      @rownum := @rownum+1 
     ) AS rank, 
     @prev := category, 
     @rownum 
    FROM (
    SELECT * FROM products 
    ORDER BY category, rand() 
) random_prodcts 
) products_ranked 
WHERE rank <= 2; 

Il leur ordonne au hasard dans les catégories, puis sort de suivi combien il est obtenu de chacun.

Vous ne savez pas à quel point il s'agira bien d'une mise à l'échelle.

EDIT: J'ai essayé avec quelques milliers de disques et cela semble correct.

+1

Cela fonctionne magnifiquement. Assurez-vous simplement que vous avez défini les variables avant d'exécuter la requête. Sinon, cela ne fonctionnera pas. SET @ prev = 0, @ rownum = 0; –

1

Cela devrait faire ce que vous recherchez.

SET @I=0; 
SET @C=''; 
SELECT ID, Name, Category FROM (
    SELECT B.*, 
    IF(@C != B.Category, @I:=1, @I:[email protected]+1) AS RowNum, 
    @C:=B.Category 
    FROM (
     SELECT ID, Name, Category FROM Products GROUP BY Name, Category ORDER BY Category 
    ) AS B HAVING RowNum <= 2 
) AS A 
+0

Merci, cela semble fonctionner mais je n'arrive pas à comprendre le RowNum var ... quand je le sélectionne avec les colonnes ID, Nom et Catégorie qu'il contient parfois aussi 3 alors que la clause HAVING stipule qu'elle ne devrait pas être supérieure à 2? – ChrisR

+0

C'est vraiment bizarre - j'ai juste essayé ceci, et j'ai remarqué que cela fonctionne avec <= 2 et donne des rownums 1 et 3, mais les 2 enregistrements corrects, mais si vous le faites avec <= 3, ça ne marche plus - il donne seulement 2 enregistrements par catégorie et encore 1 et 3 rownums. Essayez-le avec une sélection de valeurs - je ne peux pas comprendre la relation. Avez-vous déjà essayé ma solution? – Simon

+0

@ Simon143: Oui, votre solution me donne en fait le bon numéro de téléphone ... merci! – ChrisR

1

COMPLET SQL:

SELECT t.id, t.name, t.category 
FROM the_table AS t 
, (SELECT MIN(id) AS id_min FROM the_table GROUP BY category) AS t1 
, (SELECT MAX(id) AS id_max FROM the_table GROUP BY category) AS t2 
WHERE (t.id=t1.id_min) OR (t.id=t2.id_max) 

La requête prend le min et le maximum de chaque catégorie et retourner tous les deux (ou une seule si elle est la même). Vous avez dit "L'ordre des produits sélectionnés est sans importance, ils pourraient aussi bien être aléatoire", donc cette méthode devrait être OK.

Questions connexes