2009-08-30 11 views
6

mam tej tabelizapytań SQL, wybranie 5 ostatnich w każdej grupie

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 odnosi się do tego, co język zapis znajduje. Co chciałbym zrobić, to pobrać listę pięciu ostatnio (ORDER BY time_posted DESC LIMIT 5) zapisuje w każdym language_id. Mogłem to zrobić w pętli w PHP z wieloma różnymi zapytaniami SQL, ale czuję, że jest prostszy sposób.

Muszę dostać książkę o SQL, haha.

Dzięki.

+1

Jaki silnik SQL? To niestety ważne - SQL Standard, PostgreSQL, MS SQL Server, Oracle, IBM DB2 itp., Mają jeden świetny sposób, aby zrobić dokładnie to, co chcesz - ale jeśli utkniesz w MySQL, to idealne rozwiązanie działa na każdy dobry relacyjny DB i zgodnie z samym standardem nie jest dostępny, więc jest to czas krówki i kudła (par dla kursu dla MySQL - westchnienie). Więc co to będzie - każda przyzwoita implementacja SQL na planecie, z jednej strony, lub MySQL, z drugiej ...? –

+0

@Alex: Przestań kręcić w bawełnę - daj nam znać, co myślisz o MySQL! Nie trzymaj go w butelce. ;-) –

+0

mySQL> MS Access ...ledwie –

Odpowiedz

9

Oto jak rozwiązać ten „Top N na grupę” typ zapytania w 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; 

Patrz także „How do I select multiple items from each group in a mysql query?

+0

Przepraszamy za bycie głupim, ale skąd się wzięły C1 i C2? –

+0

są aliasami tabeli –

+0

Pamiętaj, że jeśli 'time_posted' może mieć powiązania, możesz uzyskać interesujące wyniki. Daj mi znać, jeśli to jest problem, ponieważ jest on również rozwiązalny. –

-1

Oto doskonałe rozwiązanie właśnie znalazłem.

wybrać górny N wierszy dla każdej grupy Arnie Rowland, 13 marca 2008

Istnieje wiele wierszy dla każdej kategorii, a tam jest pragnienie wybrać tylko dwa górne (2) Wiersze dla każdej kategorii według ceny. Na przykład, na podstawie następujących parametrów:

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 

pożądany wyjściowy:

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 

Istnieje kilka sposobów, celem uzyskania pożądanej wydajności. Ta demonstracja stanowi rozwiązanie dla SQL Server 2005/SQL Server 2008, a następnie rozwiązanie dla SQL Server 2000.

Tworzenie przykładowych danych dla obu roztworów

-- 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 Rozwiązanie

--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 Rozwiązanie użyciu CTE (Dodane przez: 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 Rozwiązanie

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

Od: Select the TOP n Rows For Each Group

+0

Należy pamiętać, że odradza się stosowanie wyłącznie linków, odpowiedzi SO powinny być punktem końcowym wyszukiwania rozwiązania (w porównaniu z innym zatrzymanie referencji, które z czasem zanikają). Proszę rozważyć dodanie samodzielnego streszczenia tutaj, zachowując odnośnik jako odniesienie. – kleopatra