选择前10行,然后确定要包含哪些行

时间:2011-05-09 15:30:46

标签: sql oracle greatest-n-per-group

我在表格中有2列。第1列代表不同公司的名称,第2列显示产品数量。

COL 1         COL 2
CompA         2323
CompB         2320
CompC         1999
CompD         1598
CompE         1400...so on

我想要做的是显示前10行,显示前10个公司名称及其在desc顺序中的计数。 然后我想比较第10个公司数和第11个公司数。如果匹配,则显示第11个公司名称及其计数。如果第10个公司计数与第11个公司计数不匹配,则仅显示前10个记录。

我只读访问权限,因此无法在表格中更新或插入新记录。

如何做到这一点?

4 个答案:

答案 0 :(得分:7)

如果你想要做的是显示前十个计数,包括领带。使用ANALYTIC函数(例如RANK()DENSE_RANK() ...

)可以很容易地解决这个问题
SQL> select * from
  2      ( select
  3          ename
  4             , sal
  5             , rank() over (order by sal desc) sal_rank
  6      from emp
  7      )
  8  where sal_rank <= 10
  9  /

ENAME             SAL   SAL_RANK
---------- ---------- ----------
QUASSNOI         6500          1
SCHNEIDER        5000          2
FEUERSTEIN       4500          3
VERREYNNE        4000          4
LIRA             3750          5
PODER            3750          5
KESTELYN         3500          7
TRICHLER         3500          7
GASPAROTTO       3000          9
ROBERTSON        2990         10
RIGBY            2990         10

11 rows selected.

SQL>

请注意,如果RIGBY的工资与GASPAROTTO相同,那么他们的SAL_RANK将 9 ,ROBERTSON将 11 ,结果集将包含10行。

DENSE_RANK()RANK()的不同之处在于它总是会返回前十位的粉丝,而不是跳过关系......

SQL> select * from
  2      ( select
  3          ename
  4             , sal
  5             , dense_rank() over (order by sal desc) sal_rank
  6      from emp
  7      )
  8  where sal_rank <= 10
  9  /

ENAME             SAL   SAL_RANK
---------- ---------- ----------
                               1
SCHNEIDER        5000          2
FEUERSTEIN       4500          3
VERREYNNE        4000          4
LIRA             3750          5
PODER            3750          5
KESTELYN         3500          6
TRICHLER         3500          6
GASPAROTTO       3000          7
ROBERTSON        2990          8
RIGBY            2990          8
SPENCER          2850          9
BOEHMER          2450         10

13 rows selected.

SQL>

答案 1 :(得分:0)

试试这个:

SELECT col1, col2
FROM (
   SELECT col1, col2
     FROM Table
     WHERE col2 >= (SELECT col2
                      FROM (SELECT col2 FROM Table ORDER BY col2 DESC) t1
                     WHERE t1.ROWNUM = 10)
     ORDER BY col2 DESC) t2
WHERE t2.ROWNUM <= 11

答案 2 :(得分:0)

我认为您所说的可以通过编写top-n查询的pl / sql代码块来完成。 这样的事情会有所帮助

decalre
    v_col_1    companies.col_1%TYPE;
    v_col_2    companies.col_2%TYPE;
    count number;    
    col_2_all number;
    CURSOR companies is SELECT *
        FROM (select * from companies ORDER BY col_2) 
        WHERE rownum <= 10
        ORDER BY rownum;

begin

    loop 
      fetch companies into v_cal_1,v_col_2;
      count++;
      if count =10 then
        col_2_all=v_col_2
        dbms_output.put_line('company name'||v_cal_1||'company count'||v_cal_2);
      elsif count =11 then
        if col_2_all=v_col_2 then
          dbms_output.put_line('company name'||v_cal_1||'company count'||v_cal_2);
        end if;
      end if;
    EXIT WHEN count>11;

end;

我不确定语法,但必须是这样的:)

答案 3 :(得分:0)

With Top10Co As
    (
    Select Col1 As CompanyName, Col2 As Cnt
        , Row_Number() Over ( Order By Col2 Desc ) As Num
    From MyTable
    )
Select CompanyName, Cnt
From Top10Co
Where Num <= 10
Union All
Select Col1, Col2
From MyTable
Where Exists    (
                Select 1
                From Top10Co As T2
                Where T2.Num = 10
                    And T2.CompanyName <> MyTable.Col1
                    And T2.Cnt = MyTable.Col2
                )