2011-10-14 143 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 
;