从最小最小聚合函数中获取两个或更多值

时间:2014-11-28 11:13:08

标签: sql oracle aggregate-functions

假设我有桌子销售

+------------+---------+------------------------------+-------------+
| SaleAmount | OrderID | CompanyName                  | ShippedDate |
+------------+---------+------------------------------+-------------+
|       3302 |   10393 | Save-a-lot Markets           | 1997-01-03  |
|       2736 |   10398 | Save-a-lot Markets           | 1997-01-09  |
|       3063 |   10400 | Eastern Connection           | 1997-01-16  |

如果我使用聚合函数查询

    select max(saleamount),shippeddate from sales where shippeddate = '1997-01-16'
            group by shippeddate 

它将显示特定日期的最大销售额。这里 我想显示特定日期的前n个最大值。 我可以通过使用子查询或存储在下面的表格中来实现相同的目标

select * from 
 (select * from sales h order by shippeddate, saleamout) where shippeddate = '1997-01-16' and rownum <= 2

还有其他方法可以显示前n(最大,最小)值或任何编写多行函数的方法。

修改

这里我不想使用缓冲区大小太小的子查询,并且执行时间花费的时间更长。我的数据库是oracle 11g

3 个答案:

答案 0 :(得分:2)

您可以使用分析函数:

select * from
(
    select s.*,
           row_number() over(partition by shippeddate order by saleamout desc) max_rw, 
           row_number() over(partition by shippeddate order by saleamout asc) min_rw
    from sales s
) 
-- where max_rw <= N -- max N
-- where min_rw <= N -- min N

partition by定义了一个组(在这种情况下,所有行都具有相同的shippeddate
order by对组内的行进行排序 row_number()根据ORDER BY

为组中的每一行分配行号

答案 1 :(得分:0)

下面的例子中有一个会有所帮助吗?

-- one row two columns
SELECT MAX (saleamount), MIN (saleamount) FROM sales WHERE shippeddate = '1997-01-16';

-- two rows one column
SELECT MAX (saleamount) FROM sales WHERE shippeddate = '1997-01-16'
UNION SELECT MIN (saleamount) FROM sales WHERE shippeddate = '1997-01-16';

答案 2 :(得分:0)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE sales
    ("SaleAmount" int, 
     "OrderID" int primary key, 
     "CompanyName" varchar2(18), 
     "ShippedDate" varchar2(10))
;


CREATE INDEX sales_amount ON sales ("SaleAmount");
CREATE INDEX sales_date ON sales ("ShippedDate");

INSERT ALL 
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (3302, 10393, 'Save-a-lot Markets', '1997-01-03')
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (2736, 10398, 'Save-a-lot Markets', '1997-01-09')
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (7063, 10401, 'Save-a-lot Markets', '1997-01-16')
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (3063, 10400, 'Eastern Connection', '1997-01-16')
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (4063, 10402, 'Save-a-lot Markets', '1997-01-16')
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (5063, 10404, 'Eastern Connection', '1997-01-16')
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (7763, 10406, 'Save-a-lot Markets', '1997-01-16')
    INTO sales ("SaleAmount", "OrderID", "CompanyName", "ShippedDate")
         VALUES (4763, 10408, 'Save-a-lot Markets', '1997-01-16')
SELECT * FROM dual
;

查询1

SELECT /*+ INDEX(sales sales_amount) */ "SaleAmount"
FROM sales 
WHERE "ShippedDate" = '1997-01-16' AND "SaleAmount" <> 0 AND rownum <= 2
UNION ALL
(
SELECT /*+ INDEX(sales sales_amount) */ "SaleAmount"
FROM sales 
WHERE "ShippedDate" = '1997-01-16' AND "SaleAmount" <> 0 AND 
    rownum <= (SELECT COUNT(*) FROM sales WHERE "ShippedDate" = '1997-01-16')
MINUS
SELECT /*+ INDEX(sales sales_amount) */ "SaleAmount"
FROM sales 
WHERE "ShippedDate" = '1997-01-16' AND "SaleAmount" <> 0 AND 
    rownum <= (SELECT COUNT(*)-2 FROM sales WHERE "ShippedDate" = '1997-01-16')
)

<强> Results

| SALEAMOUNT |
|------------|
|       3063 |
|       4063 |
|       7063 |
|       7763 |



-- AND rownum <= N -- min N
-- SELECT COUNT(*)-N -- max N