Oracle11g - 获取Group By和Order By的最大值

时间:2015-04-04 08:26:23

标签: sql oracle join oracle11g max

我有以下查询:

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_idcount次最高的手机manufacturer。像这样:

  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,但它给了我一个错误。

有人可以帮忙吗?

3 个答案:

答案 0 :(得分: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()函数的内部查询首先根据降序中的计数为行分配排名,每个组< / strong> manuf_id。因此,每个组中的最高计数将具有等级1.最后,我们在外部查询中过滤所需的行。

答案 1 :(得分:0)

我认为这或多或少与Lalit的答案相同 - 基本上,策略是对原始分组查询进行排名(或row_number),按降序排序,然后筛选出排名靠前的排名每个制造商的电话:

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

答案 2 :(得分:0)

您的原始查询如下:

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;

在这里结合一件事,一件事,你可以使用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;