2009-08-30 55 views
6

我有這個表中選擇最近5SQL查詢,每組

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是指記錄在不在。 什麼語言,我想什麼做的是檢索5個最近的列表(ORDER BY time_posted DESC LIMIT 5)在每個language_id中記錄。我可以在PHP中用一系列不同的SQL查詢在循環中做到這一點,但我覺得有一個更簡單的方法。

我得拿一本關於SQL的書,哈哈。

謝謝。

+1

什麼SQL引擎?不幸的是,SQL標準,PostgreSQL,MS SQL Server,Oracle,IBM DB2等等都有一種非常好的方式來完成你想要的任務 - 但是如果你堅持使用MySQL,那麼這個完美的解決方案每一個好的關係數據庫並且根據標準本身是不可用的,所以它是非常快速的(與MySQL有關的課程 - 嘆息)。那麼它將會是什麼樣子呢 - 這個星球上的每一個體面的SQL實現,或者另一方面的MySQL,或者其他......? – 2009-08-30 04:49:22

+0

@Alex:在叢林中跳動 - 讓我們知道您對MySQL的感受!不要讓它瓶裝。 ;-) – 2009-08-30 04:51:36

+0

mySQL> MS Access ...勉強 – 2009-08-30 05:05:01

回答

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

對不起,但C1和C2從哪裏來? – 2009-08-30 05:08:04

+0

他們是表別名 – 2009-08-30 05:15:01

+0

請注意,如果'time_posted'可以有關係,你可能會得到一些有趣的結果。讓我知道這是否是一個問題,因爲它也是可以解決的。 – 2009-08-30 05:20:26

-1

這裏是一個很好的解決方案我剛剛發現。

選擇TOP N行的每​​個組 阿尼·羅蘭,2008年3月13日

有每個類別多行,並有一個願望, 選擇每個類別的只有前兩(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/SQL 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中溶液的溶液

--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服務器使用CTE 2008解決方案(添加人:雅各塞巴斯蒂安)

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

請注意,只有鏈接的答案是不鼓勵的,所以答案應該是搜索解決方案的終點(而另一個答案參考文獻的中途停留,這些文獻往往會隨着時間推移而變得陳舊)。請考慮在此添加獨立的摘要,並將鏈接保留爲參考。 – kleopatra 2013-07-27 09:03:53