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;
您的原查询如下:
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;
我有以下查询:
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;
您的原查询如下:
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;