对于销量最大的产品的pid和名称:
从 Oracle 12c 开始,fetch 功能将输出限制为一行:
SELECT pu.pid, pr.name, sum(pu.qty) as "total quantity sold"
FROM PURCHASES pu
INNER JOIN PRODUCTS pr on pu.pid = pr.pid
GROUP BY pu.pid, pr.name
ORDER BY sum(pu.qty) DESC
FETCH FIRST 1 ROWS ONLY
;
对于支持 row_number() over() 的早期版本的 Oracle(或对于具有相同功能支持的其他数据库):
SELECT pid, name, "total quantity sold"
FROM (
SELECT pu.pid, pr.name, sum(pu.qty) as "total quantity sold"
, ROW_NUMBER() OVER(ORDER BY sum(pu.qty) DESC) AS RN
FROM PURCHASES pu
INNER JOIN PRODUCTS pr on pu.pid = pr.pid
GROUP BY pu.pid, pr.name
)
WHERE RN = 1
;
但这两种方法都假设只有一行要报告。在一组更大的数据中,可能有不止一行共享最高数量的总和。要返回所有此类行,请改用dense_rank() over(),例如:
SELECT pid, name, "total quantity sold"
FROM (
SELECT pu.pid, pr.name, sum(pu.qty) as "total quantity sold"
, DENSE_RANK() OVER(ORDER BY sum(pu.qty) DESC) AS RNK
FROM PURCHASES pu
INNER JOIN PRODUCTS pr on pu.pid = pr.pid
GROUP BY pu.pid, pr.name
)
WHERE RNK = 1
;
请注意,在提供的示例中,产品表中缺少 PID p004/p007/p008。我认为这只是问题中的一个遗漏。
SQL Fiddle
Oracle 11g R2 架构设置:
CREATE TABLE PURCHASES
(PURno int, EID varchar2(3), PID varchar2(4), CID varchar2(4), QTY int, PTIME timestamp, TOTAL_PRICE numeric)
;
INSERT ALL
INTO PURCHASES (PURno, EID, PID, CID, QTY, PTIME, TOTAL_PRICE)
VALUES (100001, 'e01', 'p002', 'c001', 1, '12-Aug-2017 12:00:00 AM', 211.65)
INTO PURCHASES (PURno, EID, PID, CID, QTY, PTIME, TOTAL_PRICE)
VALUES (100002, 'e01', 'p003', 'c001', 1, '20-Sep-2017 12:00:00 AM', 118.4)
INTO PURCHASES (PURno, EID, PID, CID, QTY, PTIME, TOTAL_PRICE)
VALUES (100003, 'e02', 'p004', 'c002', 5, '08-Oct-2017 12:00:00 AM', 4.95)
INTO PURCHASES (PURno, EID, PID, CID, QTY, PTIME, TOTAL_PRICE)
VALUES (100005, 'e04', 'p007', 'c004', 1, '15-Oct-2017 12:00:00 AM', 119.2)
INTO PURCHASES (PURno, EID, PID, CID, QTY, PTIME, TOTAL_PRICE)
VALUES (100006, 'e03', 'p008', 'c001', 1, '12-Oct-2017 12:00:00 AM', 349.3)
SELECT * FROM dual
;
CREATE TABLE PRODUCTS
(PID varchar2(5), NAME varchar2(70), ORIGINAL_PRICE int, DISCNT_RATE numeric)
;
INSERT ALL
INTO PRODUCTS (PID, NAME, ORIGINAL_PRICE, DISCNT_RATE)
VALUES ('p001', 'stapler', 9.99, .1)
INTO PRODUCTS (PID, NAME, ORIGINAL_PRICE, DISCNT_RATE)
VALUES ('p002', 'TV', 249, .15)
INTO PRODUCTS (PID, NAME, ORIGINAL_PRICE, DISCNT_RATE)
VALUES ('p003', 'camera', 148, .2)
INTO PRODUCTS (PID, NAME, ORIGINAL_PRICE, DISCNT_RATE)
VALUES ('p004', 'p004 missing from sample', 0, 0)
INTO PRODUCTS (PID, NAME, ORIGINAL_PRICE, DISCNT_RATE)
VALUES ('p007', 'p007 missing from sample', 0, 0)
INTO PRODUCTS (PID, NAME, ORIGINAL_PRICE, DISCNT_RATE)
VALUES ('p008', 'p008 missing from sample', 0, 0)
SELECT * FROM dual
;
查询 1:
SELECT PID, NAME, "total quantity sold"
FROM (
SELECT pu.pid, pr.name, sum(pu.qty) as "total quantity sold"
, ROW_NUMBER() OVER(ORDER BY sum(pu.qty) DESC) AS RN
FROM PURCHASES pu
INNER JOIN PRODUCTS pr on pu.pid = pr.pid
GROUP BY pu.pid, pr.name
)
WHERE RN = 1
;
Results:
| PID | NAME | total quantity sold |
|------|--------------------------|---------------------|
| p004 | p004 missing from sample | 5 |
查询 2:
SELECT PID, NAME, "total quantity sold"
FROM (
SELECT pu.pid, pr.name, sum(pu.qty) as "total quantity sold"
, DENSE_RANK() OVER(ORDER BY sum(pu.qty) DESC) AS RNK
FROM PURCHASES pu
INNER JOIN PRODUCTS pr on pu.pid = pr.pid
GROUP BY pu.pid, pr.name
)
WHERE RNK = 1
;
Results:
| PID | NAME | total quantity sold |
|------|--------------------------|---------------------|
| p004 | p004 missing from sample | 5 |