2009-08-30 10 views
6

ich diese TabelleSQL Query, Auswählen 5 letzten in jeder Gruppe

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 bezieht sich auf welche Sprache die Platte ist in. haben Was würde ich tun, ist eine Liste der fünf letzten abrufen (ORDER BY time_posted DESC LIMIT 5) zeichnet in jeder language_id auf. Ich könnte dies in einer PHP-Schleife mit einer Reihe von verschiedenen SQL-Abfragen tun, aber ich denke, es gibt einen einfacheren Weg.

Ich muss ein Buch über SQL bekommen, haha.

Danke.

+1

Welche SQL-Engine? Das ist leider entscheidend - der SQL-Standard, PostgreSQL, MS SQL Server, Oracle, IBM DB2, usw., haben eine großartige Möglichkeit, genau das zu tun, was Sie wollen - aber wenn Sie mit MySQL festgefahren sind, arbeitet diese perfekte Lösung weiter jede gute relationale DB und entsprechend dem Standard selbst ist nicht verfügbar, also ist es Fudge-and-Kludge-Zeit (Par für den Kurs für MySQL - Seufzer). Also, was wird es sein - jede anständige SQL-Implementierung auf der einen Seite oder MySQL auf der anderen Seite ...? –

+0

@Alex: Hör auf zu plagen - lass uns wissen, wie du über MySQL denkst! Halten Sie es nicht in Flaschen. ;-) –

+0

mySQL> MS Access ...kaum –

Antwort

9

Hier ist, wie ich löse diese "Top-N pro Gruppe" Art der Abfrage in 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; 

Siehe auch "How do I select multiple items from each group in a mysql query?"

+0

Entschuldigung dafür, daft zu sein, aber woher kamen die C1 und C2? –

+0

Sie sind Tabellenalias –

+0

Beachten Sie, dass, wenn 'time_posted' Verbindungen haben kann, Sie einige interessante Ergebnisse erhalten können. Lass es mich wissen, wenn das ein Problem ist, weil es auch lösbar ist. –

-1

hier eine große Lösung, die ich gerade gefunden.

die TOP n Wählen Sie Zeilen für jede Gruppe Arnie Rowland, 13. März 2008

Es gibt mehrere Zeilen für jede Kategorie, und es gibt einen Wunsch, nur dann wählen, die beiden oberen (2) Zeilen pro Kategorie nach Preis. beispielsweise aus den folgenden Daten:

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 

Die gewünschte Ausgabe ist:

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 

Es gibt mehrere Methoden, um die gewünschte Ausgabe zu erzielen. Diese Demonstration stellt eine Lösung für SQL Server 2005/SQL Server 2008, und dann eine Lösung für SQL Server 2000

Erstellen von Beispieldaten für beiden Lösungen

-- 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-Lösung

--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-Lösung einen CTE mit (Hinzugefügt von: 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-Lösung

--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 

Von: Select the TOP n Rows For Each Group

+0

Beachten Sie, dass Link-Only-Antworten nicht empfohlen werden, SO-Antworten sollten der Endpunkt einer Suche nach einer Lösung sein (im Gegensatz zu einem anderen) Zwischenstopp von Referenzen, die im Laufe der Zeit abgestanden werden. Bitte beachten Sie, dass Sie hier eine eigenständige Zusammenfassung hinzufügen und den Link als Referenz beibehalten. – kleopatra

Verwandte Themen