2011-10-14 112 views
0

代码正在运行,但顶级(X)TOP PRICE未被相应提取。我如何在代码中使用Ties?
某些top(x)被忽略。Oracle PL/SQL查询

这是我的表

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?
某些top(x)被忽略。

+0

什么版本的Oracle? 9i +支持分析(IE:ROW_NUMBER),尽管技术上它们可用于8i –

+0

Oracle数据库10 – shakur007

+0

从调试游标查询开始 - 正在为初学者正确使用“ROWNUM”。 –

回答

1

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

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

+0

是的,我做到了。 – shakur007

+0

你有没有得到你的标题行,或什么都没有? – DCookie

+0

你可能想用那条信息来更新你的问题,这很重要;-) – DCookie

1

首先为DCookie建议,确保已启用输出

set serveroutput on 

如果你没有得到你所期待的结果,尝试打破查询,直到找到其中数据丢失例如如果去年没有交易,您不会收回任何东西,因此请选择符合标准的一笔交易记录,然后查看其他表以查找匹配记录。还要确认每个表中都有数据,就好像它们中的任何一个都是空的一样,结果集也是空的。

例如

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

(假设是这一天是日期字段),然后从通讯录

select peid from contact where pno=&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表,但工作人员和联系有相同PEID字段,你的arent从STAFF表中选择任何列,但你从人表名字,姓氏和员工数量。

对于可能成为交易联系人但不是员工的人员​​,人员表中是否还有其他行(表示与员工的联接是为了验证类型)?如果不是,那么也许这里的员工表是多余的。

当你有一个复杂的查询(他们可以变得非常复杂,就像打印出几页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 

使用秩(),如果你想跳过那里有几个人一道排在并列位置或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

+0

我的代码运行良好,但我想打破关系,我不知道该怎么做....这是我的问题, – shakur007

+0

不知道你的意思是打破关系吗? –

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 
;