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

Oracle11g - Getting Maximum values for Group By and Order 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.

我想获得每个 manufacturer 中具有最高 count 的 phone 的 phone_id。像这样:

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

有人可以帮忙吗?

您可以使用分析 ROW_NUMBER() 根据计数分配排名。

Update 为了保持行数相同,你需要使用 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() 函数的内部查询首先根据 降序 [=36] 中的计数为行分配排名=],在 manuf_id 每个组 中也是如此。因此,每个组中的最高计数将具有排名 1。最后,我们在外部查询中过滤所需的行。

我相信这或多或少与 Lalit 的回答相同 - 基本上,策略是对您的原始分组查询进行排名(或 row_number),按计数降序排序,然后仅过滤掉每个制造商排名最高 phone:

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

您的原查询如下:

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;