2015-04-04 39 views
2

我有以下查詢:Oracle11g的 - 獲取了GROUP BY和最大值順序按

SELECT CC.phone_ID, 
     COUNT(CC.phone_id) "Count", 
     PR.manuf_id 
FROM CONTRACT_CELLPHONE CC 
INNER JOIN product PR ON CC.phone_id = PR.product_id 
GROUP BY CC.phone_id, 
     PR.manuf_id 
ORDER BY 3; 

這給了我下面的輸出:

PHONE_ID COUNT(CC.PHONE_ID) MANUF_ID 
---------- ------------------ ---------- 
    87555     6  567000 
    43342     2  567001 
    58667     3  567001 
    46627     5  567002 
    11243     3  567003 
    87549     3  567003 
    86865     2  567005 
    65267     4  567006 

8 rows selected. 

我想獲取手機的phone_idmanufacturer有最高count。事情是這樣的:

PHONE_ID COUNT(CC.PHONE_ID) MANUF_ID 
---------- ------------------ ---------- 
    87555     6  567000 
    58667     3  567001 
    46627     5  567002 
    11243     3  567003 
    87549     3  567003 
    86865     2  567005 
    65267     4  567006 

這是主數據集:

SQL> SELECT * FROM CONTRACT_CELLPHONE CC INNER JOIN product PR ON CC.phone_id = PR.product_id; 

CONTRACT_ID PHONE_ID  SEQ# PAIDPRICE  ESN PRODUCT_ID NAME        MANUF_ID COSTPAID BASEPRICE TYPE 
----------- ---------- ---------- ---------- ---------- ---------- ------------------------------ ---------- ---------- ---------- --------- 
     10010  11243   1  310 1234567890  11243 Galaxy        567003  276  345 CellPhone 
     10011  11243   1  310 1232145654  11243 Galaxy        567003  276  345 CellPhone 
     10011  87549   2  320 2323565678  87549 Galaxy        567003  280  350 CellPhone 
     10012  58667   1  300 3452123533  58667 Droid        567001  275  320 CellPhone 
     10013  87555   1  425 3445421789  87555 iPhone        567000  360  450 CellPhone 
     10014  65267   1   85 8752570865  65267 Bold        567006  63.75   75 CellPhone 
     10014  65267   2   85 5421785345  65267 Bold        567006  63.75   75 CellPhone 
     10014  65267   3   85 3454323457  65267 Bold        567006  63.75   75 CellPhone 
     10016  46627   1  250 9876554321  46627 HTC One       567002  200  250 CellPhone 
     10016  65267   2   85 1002938475  65267 Bold        567006  63.75   75 CellPhone 
     10017  46627   1  250 8766543289  46627 HTC One       567002  200  250 CellPhone 
     10018  87555   1  425 3454334532  87555 iPhone        567000  360  450 CellPhone 
     10019  43342   1  450 2334567654  43342 Droid        567001  400  500 CellPhone 
     10020  87549   1  320 2345678912  87549 Galaxy        567003  280  350 CellPhone 
     10021  87555   1  425 3456129642  87555 iPhone        567000  360  450 CellPhone 
     10021  87555   2  425 8732786480  87555 iPhone        567000  360  450 CellPhone 
     10022  46627   1  250 5634512345  46627 HTC One       567002  200  250 CellPhone 
     10023  11243   1  300 1276349812  11243 Galaxy        567003  276  345 CellPhone 
     10024  46627   1  250 3456123457  46627 HTC One       567002  200  250 CellPhone 
     10025  58667   1  300 5438767651  58667 Droid        567001  275  320 CellPhone 
     10026  87555   1  425 6541835680  87555 iPhone        567000  360  450 CellPhone 
     10027  86865   1  210 9826485932  86865 Lumia        567005  160  200 CellPhone 
     10028  86865   1  210 3218759604  86865 Lumia        567005  160  200 CellPhone 
     10029  87549   1  320 4328753902  87549 Galaxy        567003  280  350 CellPhone 
     10030  58667   1  300 9742467907  58667 Droid        567001  275  320 CellPhone 
     10031  46627   1  250 2938465831  46627 HTC One       567002  200  250 CellPhone 
     10032  87555   1  425 2319347891  87555 iPhone        567000  360  450 CellPhone 
     10033  43342   1  450 2319752032  43342 Droid        567001  400  500 CellPhone 

28 rows selected. 

我使用MAX嘗試,但它給了我一個錯誤。

有人可以幫忙嗎?

+0

我編輯我的答案,因爲** ** DENSE_RANK是更好的貼合,** ** ROW_NUMBER將跳過類似的計數。看到我的答案。 – 2015-04-04 08:59:33

回答

2

您可以使用分析ROW_NUMBER()根據計數分配排名。

更新爲保持行數相同,您需要使用DENSE_RANK

測試用例:

DENSE_RANK

SQL> WITH DATA AS(
    2 SELECT 87555 PHONE_ID, 6 count_phone_id, 567000 manuf_id FROM dual UNION ALL 
    3 SELECT 43342, 2,  567001 FROM dual UNION ALL 
    4 SELECT 58667, 3,  567001 FROM dual UNION ALL 
    5 SELECT 46627, 5,  567002 FROM dual UNION ALL 
    6 SELECT 11243, 3,  567003 FROM dual UNION ALL 
    7 SELECT 87549, 3,  567003 FROM dual UNION ALL 
    8 SELECT 86865, 2,  567005 FROM dual UNION ALL 
    9 SELECT 65267, 4,  567006 FROM dual 
10 ) 
11 SELECT phone_id, 
12 count_phone_id, 
13 manuf_id 
14 FROM 
15 (SELECT t.*, 
16  DENSE_RANK() OVER(PARTITION BY manuf_id ORDER BY count_phone_id DESC) rn 
17 FROM DATA t 
18 ) 
19 WHERE rn = 1; 

    PHONE_ID COUNT_PHONE_ID MANUF_ID 
---------- -------------- ---------- 
    87555    6  567000 
    58667    3  567001 
    46627    5  567002 
    11243    3  567003 
    87549    3  567003 
    86865    2  567005 
    65267    4  567006 

7 rows selected. 

SQL> 

因此,使用DENSE_RANK你有那些每個組中相同的數列。

ROW_NUMBER

SQL> WITH DATA AS(
    2 SELECT 87555 PHONE_ID, 6 count_phone_id, 567000 manuf_id FROM dual UNION ALL 
    3 SELECT 43342, 2,  567001 FROM dual UNION ALL 
    4 SELECT 58667, 3,  567001 FROM dual UNION ALL 
    5 SELECT 46627, 5,  567002 FROM dual UNION ALL 
    6 SELECT 11243, 3,  567003 FROM dual UNION ALL 
    7 SELECT 87549, 3,  567003 FROM dual UNION ALL 
    8 SELECT 86865, 2,  567005 FROM dual UNION ALL 
    9 SELECT 65267, 4,  567006 FROM dual 
10 ) 
11 SELECT phone_id, 
12 count_phone_id, 
13 manuf_id 
14 FROM 
15 (SELECT t.*, 
16  row_number() OVER(PARTITION BY manuf_id ORDER BY count_phone_id DESC) rn 
17 FROM DATA t 
18 ) 
19 WHERE rn = 1; 

    PHONE_ID COUNT_PHONE_ID MANUF_ID 
---------- -------------- ---------- 
    87555    6  567000 
    58667    3  567001 
    46627    5  567002 
    11243    3  567003 
    86865    2  567005 
    65267    4  567006 

6 rows selected. 

SQL> 

所以,內部查詢使用ROW_NUMBER()函數首先分配秩基於該計數的行中降序,即得在的每個組manuf_id。因此,每個組中的最高計數將具有等級1.最後,我們在外部查詢中過濾所需的行。

0

我相信這與Lalit的回答基本相同 - 基本上,策略是按照降序計數排序(或row_number)您的原始分組查詢,然後篩選出每個排名最高的手機制造商:這裏

SELECT CC.phone_ID, 
     COUNT(CC.phone_id) "Count", 
     PR.manuf_id 
FROM CONTRACT_CELLPHONE CC 
INNER JOIN product PR ON CC.phone_id = PR.product_id 
GROUP BY CC.phone_id, 
    PR.manuf_id 
ORDER BY 3; 

兩件事情,一是,Y:

WITH ManufacturerPhones As 
(
    -- Your original grouped query 
    SELECT CC.phone_ID, COUNT(CC.phone_id) "Count", PR.manuf_id 
    FROM CONTRACT_CELLPHONE CC 
    INNER JOIN product PR ON CC.phone_id = PR.product_id 
    GROUP BY CC.phone_id, PR.manuf_id 
), 
RankedManufacturerPhones AS 
(
    -- Ranked per Manuf_id 
    SELECT mp.*, RANK() OVER(PARTITION BY manuf_id ORDER BY "Count" DESC) AS Ranked 
    FROM ManufacturerPhones mp 
) 
-- Filtered for just top ranked phone per manuf_id 
SELECT * 
FROM RankedManufacturerPhones 
WHERE Ranked = 1 
ORDER BY Manuf_ID ASC; 

SqlFiddle here

+0

我相信** DENSE_RANK **更適合。 Rank或row_number將跳過具有相似計數的行。我剛剛意識到OP也需要這些行。相應地編輯我的答案。 – 2015-04-04 09:00:31

+0

@Lalit Kumar B:當您查找最高/最低值時,** DENSE_RANK **和** RANK **將完全相同。 @StuartLC:不需要兩個CTE,因爲分析函數是在**聚合之後計算的**,您可以執行'RANK()(通過manuf_id ORDER BY COUNT(*)DESC)' – dnoeth 2015-04-04 09:30:23

+0

@dnoeth,正確。這是一個錯字,我的意思是隻有row_number()。我讀的速度太快了:rank(或row_number)':-)在這裏,rank或dense_rank是否無關緊要,因爲我們只需要最高的計數,休息就會被過濾掉。 – 2015-04-04 09:33:36

0

您的原始查詢如下你可以使用COUNT(*)(除非phone_id可以是NULL,我懷疑它可以,因爲你正在對它進行分組。二,你可以簡單地添加的解析函數來此查詢,然後使它的子查詢:

SELECT phone_id, manuf_id, phone_id_cnt AS "Count" FROM (
    SELECT cc.phone_id, pr.manuf_id, COUNT(*) AS phone_id_cnt 
     , RANK() OVER (PARTITION BY manuf_id ORDER BY COUNT(*) DESC) AS rn 
     FROM contract_cellphone cc INNER JOIN product pr 
     ON cc.phone_id = pr.product_id 
    GROUP BY cc.phone_id, pr.manuf_id 
) WHERE rn = 1 
ORDER BY manuf_id;