2009-08-30 2 views
6

У меня есть эта таблицаSQL Query, Выбор 5 самых последних в каждой группе

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 относится к тому, что язык записи в. То, что я хотел бы сделать, это получить список из пяти последних (ORDER BY time_posted DESC LIMIT 5) записывает на каждый language_id. Я мог бы сделать это в цикле внутри PHP с несколькими различными SQL-запросами, но я чувствую, что есть более простой способ.

Мне нужно получить книгу о SQL, ха-ха.

Спасибо.

+1

Что SQL двигателя? Это, к сожалению, имеет решающее значение - SQL Standard, PostgreSQL, MS SQL Server, Oracle, IBM DB2 и т. Д. И т. Д. Имеют один превосходный способ сделать именно то, что вы хотите, но если вы застряли с MySQL, это идеальное решение, работающее над каждая хорошая реляционная БД и по самому стандарту недоступна, так что это время fudge-and-kludge (par для курса для MySQL - вздох). Так что же это будет - всякая приличная реализация SQL на планете, с одной стороны, или MySQL, с другой ...? –

+0

@Alex: Прекратите бить вокруг куста - сообщите нам, как вы относитесь к MySQL! Не держите его в бутылках. ;-) –

+0

mySQL> MS Access ...едва –

ответ

9

Вот как я решить эту «топ N на группу» тип запроса в 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; 

Смотрите также «How do I select multiple items from each group in a mysql query?»

+0

Извините за то, что вы были глупыми, но откуда взялись С1 и С2? –

+0

это псевдонимы таблицы –

+0

Обратите внимание, что если 'time_posted' может иметь связи, вы можете получить интересные результаты. Дайте мне знать, если это вызывает беспокойство, потому что оно также разрешимо. –

-1

Здесь большое решение, которое я только что нашел.

Выберите TOP п строк для каждой группы Арни Rowland, 13 марта 2008

Есть несколько строк для каждой категории, и есть желание выбрать только две верхние (2) Ряды для каждой категории по цене. Например, из следующих данных:

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 

Желаемый результат:

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 

Есть несколько способов, чтобы достичь желаемых результатов. Эта демонстрация предоставляет решение для SQL Server 2005 Server 2008, , а затем решение для SQL Server 2000.

Создание образца данных для обоих решений

-- 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 Решение/SQL

--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 Решение с использованием CTE (Добавил: 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 Решение

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

От: Select the TOP n Rows For Each Group

+0

Обратите внимание, что ссылки только ответы не приветствуются, SO ответы должны быть конечной точкой поиска решения (по сравнению с другим остановка ссылок, которые со временем становятся устаревшими). Пожалуйста, подумайте о добавлении отдельного резюме здесь, сохранив ссылку в качестве ссылки. – kleopatra