【问题标题】:Cannot select top row from the column sql from nested select无法从嵌套选择的列 sql 中选择顶行
【发布时间】:2017-10-21 06:12:19
【问题描述】:

我有两张桌子

产品

PID  NAME                ORIGINAL_PRICE    DISCNT_RATE
---- -----------         --------------    -----------
p001 stapler                      9.99          .1
p002 TV                           249           .15
p003 camera                       148           .2

购买

  PUR# EID PID  CID         QTY PTIME     TOTAL_PRICE
------ --- ---- ---- ---------- --------- -----------
100001 e01 p002 c001          1 12-AUG-17      211.65
100002 e01 p003 c001          1 20-SEP-17       118.4
100003 e02 p004 c002          5 08-OCT-17        4.95
100005 e04 p007 c004          1 15-OCT-17       119.2
100006 e03 p008 c001          1 12-OCT-17       349.3

根据总数量查找销量最多的每种产品的 pid 和名称。显示相应的总数量(标题:“总销售量”)。使用列格式将标题更改为“销售总量”。

溶胶:

到目前为止我所做的是

 SELECT Max("Total") AS "HS", pid 
 from (Select pid, sum(qty) as "Total"
 from purchases group by pid);

如果可以提供任何帮助,我将无法按预期处理信息..

P.S: 这不是作业

【问题讨论】:

  • 你能分享一下你用来生成数据的sql吗?

标签: sql oracle join group-by


【解决方案1】:

您可以使用 Sum 和 group by 来获取总值,并在排序结果上使用 TOP 1 来获取最大值

在 SQL 服务器中

  select TOP 1 a.PID, sum(b.QTY) as "total quantity sold"
  FROM Products AS a
  INNER JOIN Purchases AS b on a.PID  = b.PID
  GROUP BY a.pID
  ORDER BY sum(b.QTY) DESC 

像您所做的那样使用子选择中的最大值(不使用 group by 仅获取一行).. 可能会产生错误的结果,因为在大多数数据库中这是不允许的,或者可以显示为子选择的结果集..

如果您不想使用 TOP(行限制),则应在子选择的适当位置使用过滤器的最大值并获得正确的耦合 PID、MAX tital

【讨论】:

    【解决方案2】:

    对于销量最大的产品的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 |
    

    【讨论】:

    • 您的问题现在解决了吗?你对这个答案还有疑问吗?要接受并回答“Click the Tick”以获取更多信息,请参阅help/accepting
    猜你喜欢
    • 1970-01-01
    • 2020-12-07
    • 2010-10-04
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 2019-05-06
    相关资源
    最近更新 更多