2009-08-30 8 views
6

J'ai ce tableaurequête SQL, Sélection de 5 la plus récente dans chaque groupe

CREATE TABLE `codes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
`language_id` int(11) unsigned NOT NULL, 
`title` varchar(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, 
`time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 

language_id fait référence à quelle langue le dossier est. Ce que je voudrais faire est de récupérer une liste des cinq plus récents (ORDER BY time_posted DESC LIMITE 5) enregistre dans chaque langue id. Je pourrais faire ceci dans une boucle dans PHP avec un certain nombre de requêtes SQL différentes mais je pense qu'il y a un moyen plus simple.

Je dois obtenir un livre sur SQL, haha.

Merci.

+1

Quel est le moteur SQL? C'est malheureusement crucial - le SQL Standard, PostgreSQL, MS SQL Server, Oracle, IBM DB2, etc, etc, ont une excellente façon de faire exactement ce que vous voulez - mais si vous êtes bloqué avec MySQL, cette solution parfaite fonctionne sur tout bon DB relationnel et selon la norme elle-même n'est pas disponible, donc c'est le temps de fudge-et-kludge (pareil pour le cours pour MySQL - soupir). Alors qu'est-ce que ça va être - toutes les implémentations SQL décentes sur la planète, d'un côté, ou MySQL, de l'autre ...? –

+0

@Alex: Cessez de tourner autour du pot - dites-nous ce que vous pensez de MySQL! Ne le gardez pas embouteillé. ;-) –

+0

mySQL> MS Access ...à peine –

Répondre

9

Voilà comment je résous ce type de requête "top N par groupe" dans MySQL:

SELECT c1.* 
FROM codes c1 
LEFT OUTER JOIN codes c2 
    ON (c1.language_id = c2.language_id AND c1.time_posted < c2.time_posted) 
GROUP BY c1.id 
HAVING COUNT(*) < 5; 

Voir aussi "How do I select multiple items from each group in a mysql query?"

+0

Désolé d'être stupide, mais d'où viennent les C1 et C2? –

+0

ils sont des alias de table –

+0

Notez que si 'time_posted' peut avoir des liens, vous pourriez obtenir des résultats intéressants. Faites-moi savoir si c'est un problème, car il est résolu aussi. –

-1

Voici une excellente solution que je viens de trouver.

Sélectionnez les n lignes pour chaque groupe Arnie Rowland, le 13 Mars, 2008

Il y a plusieurs lignes pour chaque catégorie, et il y a un désir de sélectionner uniquement les deux principaux (2) lignes par catégorie par Price. Par exemple, à partir des données suivantes:

RowID Category ID Description  Price 
1  Pot   A1 Small Saucepan 21.50 
2  Pot   A2 1 Qt Saucepan 29.95 
3  Pot   A3 1.5 Qt Saucepan 33.95 
4  Pot   A4 Double Boiler 39.50 
5  Pot   A5 Stewpot   49.50 
6  Pot   A6 Pressure Cooker 79.95 
7  Pan   B1 8" Pie   6.95 
8  Pan   B2 8" Sq Cake  7.50 
9  Pan   B3 Bundt Cake  12.50 
10  Pan   B4 9x12 Brownie 7.95 
11  Bowl  C1 Lg Mixing  27.50 
12  Bowl  C2 Sm Mixing  17.50 
13  Tools  T1 14" Spatula  9.95 

La sortie désirée est:

RowID Category ID Description  Price 
11  Bowl  C1 Lg Mixing  27.50 
12  Bowl  C2 Sm Mixing  17.50 
9  Pan   B3 Bundt Cake  12.50 
10  Pan   B4 9x12 Brownie 7.95 
6  Pot   A6 Pressure Cooker 79.95 
5  Pot   A5 Stewpot   49.50 
13  Tools  T1 14" Spatula  9.95 

Il existe plusieurs méthodes pour y parvenir la sortie désirée. Cette démonstration fournit une solution pour SQL Server 2005/SQL Server 2008, puis une solution pour SQL Server 2000.

Créer des données d'échantillons pour les deux solutions

-- Suppress data loading messages 
SET NOCOUNT ON 

-- Create Sample Data using a Table Variable 
DECLARE @MyTable table 
    ( RowID   int IDENTITY, 
     Category  varchar(5), 
     [ID]   varchar(5), 
     [Description] varchar(25), 
     Price   decimal(10,2) 
    ) 

-- Load Sample Data 

INSERT INTO @MyTable VALUES ('Pot', 'A1', 'Small Saucepan', 21.50) 
INSERT INTO @MyTable VALUES ('Pot', 'A2', '1 Qt Saucepan', 29.95) 
INSERT INTO @MyTable VALUES ('Pot', 'A3', '1.5 Qt Saucepan', 33.95) 
INSERT INTO @MyTable VALUES ('Pot', 'A4', 'Double Boiler', 39.50) 
INSERT INTO @MyTable VALUES ('Pot', 'A5', 'Stewpot', 49.50) 
INSERT INTO @MyTable VALUES ('Pot', 'A6', 'Pressure Cooker', 79.95) 
INSERT INTO @MyTable VALUES ('Pan', 'B1', '8"" Pie', 6.95) 
INSERT INTO @MyTable VALUES ('Pan', 'B2', '8"" Sq Cake', 7.50) 
INSERT INTO @MyTable VALUES ('Pan', 'B3', 'Bundt Cake', 12.50) 
INSERT INTO @MyTable VALUES ('Pan', 'B4', '9x12 Brownie', 7.95) 
INSERT INTO @MyTable VALUES ('Bowl', 'C1', 'Lg Mixing', 27.50) 
INSERT INTO @MyTable VALUES ('Bowl', 'C2', 'Sm Mixing', 17.50) 
INSERT INTO @MyTable VALUES ('Tools', 'T1', '14"" Spatula', 9.95) 
Return to Top 

SQL Server 2005/SQL Server 2008 Solution

--Query to Retrieve Desired Data 
SELECT 
    RowID, 
    Category, 
    [ID], 
    [Description], 
    Price 
FROM (SELECT 
     ROW_NUMBER() OVER (PARTITION BY Category ORDER BY Price DESC) AS 'RowNumber', 
     RowID, 
     Category, 
     [ID], 
     [Description], 
     Price 
     FROM @MyTable 
    ) dt 
WHERE RowNumber <= 2 

-- Results 
RowID Category ID Description  Price 
11 Bowl  C1 Lg Mixing  27.50 
12 Bowl  C2 Sm Mixing  17.50 
9  Pan  B3 Bundt Cake  12.50 
10 Pan  B4 9x12 Brownie 7.95 
6  Pot  A6 Pressure Cooker 79.95 
5  Pot  A5 Stewpot   49.50 
13 Tools  T1 14" Spatula  9.95 
Return to Top 

SQL Server 2005/SQL Server 2008 solution en utilisant un CTE (Ajouté par: Jacob Sebastian)

-- Define a CTE with the name "dt" 
;WITH dt AS (
    SELECT 
     ROW_NUMBER() OVER (PARTITION BY Category ORDER BY Price DESC) AS 'RowNumber', 
     RowID, 
     Category, 
     [ID], 
     [Description], 
     Price 
     FROM @MyTable 
) 
-- and select the data from the CTE 
SELECT 
    RowID, 
    Category, 
    [ID], 
    [Description], 
    Price 
FROM dt 
WHERE RowNumber <= 2 

-- Results 
RowID Category ID Description  Price 
11 Bowl  C1 Lg Mixing  27.50 
12 Bowl  C2 Sm Mixing  17.50 
9  Pan  B3 Bundt Cake  12.50 
10 Pan  B4 9x12 Brownie 7.95 
6  Pot  A6 Pressure Cooker 79.95 
5  Pot  A5 Stewpot   49.50 
13 Tools  T1 14" Spatula  9.95 
Return to Top 

SQL 2000 Solution

--Query to Retrieve Desired Data 
SELECT DISTINCT 
    RowID, 
    Category, 
    [ID], 
    [Description], 
    Price 
FROM @MyTable t1 
WHERE RowID IN (SELECT TOP 2 
        RowID 
       FROM @MyTable t2 
       WHERE t2.Category = t1.Category 
       ORDER BY Price DESC 
       ) 
ORDER BY 
    Category, 
    Price DESC 

-- Results 
RowID Category ID Description  Price 
11 Bowl  C1 Lg Mixing  27.50 
12 Bowl  C2 Sm Mixing  17.50 
9  Pan  B3 Bundt Cake  12.50 
10 Pan  B4 9x12 Brownie 7.95 
6  Pot  A6 Pressure Cooker 79.95 
5  Pot  A5 Stewpot   49.50 
13 Tools  T1 14" Spatula  9.95 

De: Select the TOP n Rows For Each Group

+0

Notez que les réponses à lien uniquement sont déconseillées, les réponses SO devraient être l'aboutissement d'une recherche de solution (contre une autre escale de références, qui tendent à se périmer avec le temps). S'il vous plaît envisager d'ajouter un synopsis autonome ici, en gardant le lien comme référence. – kleopatra

Questions connexes