Oracle PL / SQL查询

时间:2011-10-14 03:54:39

标签: sql oracle plsql oracle10g

代码正在运行但顶部(X)TOP PRICE没有相应提取。如何在我的代码中使用Ties?
  一些顶部(x)被忽略。

这是我的表

    STAFF_NUMBER STAFF_NAME                     PRICE
    ------------ ----------------------------------------- ----------
          36 Helen Hilfg                   330066
          52 Octavia Chan                  356885
          36 Helen Hilfg                   176088
          4 Heidi Lee                      231046
          6 Jill Murphy                    469844
          32 Lily Roy                      247549
          58 John Roy                      309299

这就是我得到的

   SQL> SQL> SQL> exec p4(3)
    PERSON#    NAME
     36 Helen Hilfg
     52 Octavia Chan
     4 Heidi Lee

这是我想要的

    SQL> exec p4(3);
    PERSON#  NAME
     --------------------
    36       Helen Hilfg
    6        Jill Murphy
    52       Octavia Chan

这是我的程序

CREATE OR REPLACE PROCEDURE p3( X NUMBER ) 
AS
  staff_number  NUMBER ;
  staff_name VARCHAR2(30) ;

  CURSOR c1 IS
    SELECT staff_number, 
           staff_name  
     FROM (SELECT P.peid staff_number, 
                  P.firstname || ' ' || P.lastname  staff_name , 
                  D.price  PRICE
             FROM Contact C, 
                  Deal D, 
                  Person P, 
                  Staff S
            WHERE S.peid = C.peid 
              AND C.pno = D.pno 
              AND P.peid = C.peid 
              AND (SYSDATE - D.day < 365))
    WHERE ROWNUM  <= X
 GROUP BY staff_name , staff_number
 ORDER BY SUM( price ) DESC ; 

BEGIN

   dbms_output.put_line( ' PERSON# ' ||'  '||' NAME ' );
   FOR R IN c1
   LOOP
     staff_number := R.staff_number ;
     staff_name := R.staff_name ;
     dbms_output.put_line( staff_number ||' '||  staff_name ) ;  
   END LOOP ;
END;
/

代码正在运行但顶部(X)TOP PRICE没有相应提取。如何在我的代码中使用Ties?
  一些顶部(x)被忽略。

3 个答案:

答案 0 :(得分:1)

当您说“没有输出”时,您是如何运行该程序的?你启用了dbms_output吗?例如,如果您在SQL * Plus中运行它,那么SET SERVEROUTPUT ON了吗?假设程序没有编译错误,你应该至少得到标题行。

查询本身是否在SQL * Plus中的过程之外运行?

答案 1 :(得分:1)

首先,如DCookie所建议,确保您已启用输出

 set serveroutput on

如果您没有得到预期的结果,请尝试分解查询,直到找到数据丢失的位置,例如:如果去年没有交易,你不会得到任何回报,所以只选择一个符合标准的交易记录,然后检查其他表格是否匹配记录。同时确认每个表中都有数据,好像它们中的任何一个都是空的,结果集也是空的。

e.g。

select pno  from deal where (sysdate - day) < 365;

(假设day是日期字段),然后从联系表

中选择此pno
select peid from contact where pno=&pno;

从人员表中选择此peid,如果其中任何一个选项变为空,请检查该字段的示例值以确认ID号在表之间实际匹配,例如。

select count(*) 
  from deal d 
 where exists (select 1 from contact c where c.pno=d.pno)

select count(*) 
  from contact c 
  where exists (select 1 from person p where p.peid=c.peid)

您正在加入STAFF表,但STAFF和CONTACT都具有相同的peid字段,您不能从STAFF表中选择任何列,但您可以从person表中获取firstname,lastname和staff number。

人员表中是否还有其他可能是交易联系但不是员工的人(意味着加入员工是为了验证类型)?如果没有那么也许员工表在这里是多余的。

当你有一个复杂的查询(并且它们可能变得非常复杂,比如打印出A4的几页)时,你必须有一种方法将查询细分为更简单的查询,你可以验证每一步,这导致你到错误发生的地方。

希望有所帮助。


可能你应该使用分析函数,所以查询类似

       select staff_number, staff_name from (
       SELECT P.peid staff_number, 
              P.firstname || ' ' || P.lastname  staff_name , 
              D.price  PRICE
              RANK() OVER (ORDER BY d.price) AS position
         FROM Contact C, 
              Deal D, 
              Person P, 
              Staff S
        WHERE S.peid = C.peid 
          AND C.pno = D.pno 
          AND P.peid = C.peid 
          AND (SYSDATE - D.day < 365)
 ) where position < x

如果你想跳过几个有平局位置的人的位置,可以使用rank(),或者在有多个同一位置的记录的情况下使用dense_rank()。


只是看到你需要它来为同一个人总结交易所以可能更像这样(未经测试)

   select staff_number, staff_name from (
       SELECT P.peid staff_number, 
              P.firstname || ' ' || P.lastname  staff_name , 
              sum(D.price)  PRICE
              RANK() OVER (ORDER BY sum(d.price)) AS position
         FROM Contact C, 
              Deal D, 
              Person P, 
              Staff S
        WHERE S.peid = C.peid 
          AND C.pno = D.pno 
          AND P.peid = C.peid 
          AND (SYSDATE - D.day < 365)
         group by p.peid, p.first_name|' '||p.lastname
 ) where position < x

肯定看一下分析函数,因为rownum只返回查询中的第一行,它不返回完整的结果集,然后给你前N条记录。您可能需要使用分区子句但尝试一下并在此处查看排名示例。

http://psoug.org/reference/analytic_functions.html

答案 2 :(得分:1)

请查看您的查询并尝试了解它正在做什么。

您有一个内部查询,可以过滤某些条件。您还没有向我们提供数据,因此我们无法预测结果会是什么样子。让我们假设它返回你认为它将要发生的记录。

然后在您的外部查询中,您有一个WHERE子句,它在ROWNUM <= X上进行过滤。这意味着查询将返回三行,基本上是随机的,然后将根据SUM(PRICE)对其进行分组和排序。

这显然不是你所期待的。但那是因为您不了解ROWNUM的工作原理。它很容易修复:您只需要将ROWNUM过滤器应用于分组和排序的结果。像这样:

SELECT * FROM (
    SELECT staff_number, 
           staff_name  
     FROM (SELECT P.peid staff_number, 
                  P.firstname || ' ' || P.lastname  staff_name , 
                  D.price  PRICE
             FROM Contact C, 
                  Deal D, 
                  Person P, 
                  Staff S
            WHERE S.peid = C.peid 
              AND C.pno = D.pno 
              AND P.peid = C.peid 
              AND (SYSDATE - D.day < 365)
              )
 GROUP BY staff_name , staff_number
 ORDER BY SUM( price ) DESC
)
WHERE ROWNUM  <= X
;