2017-02-28 70 views
0

我有一個表EMPLOYEE爲在其下是常見的刪除特定數據:從表中基於某些字段

Enroll Date STS EMP_ID EMP_Name DEPT Rank OST BLOCK 
12-Jan-17 Q 123  ABC  ABC123 12 Y 1000  
14-Jan-17 Q 123  ABC  DEF123 12 Y 1000  
15-Jan-17 R 123  ABC  DEF123 12 Y 100 
15-Jan-17 R 123  ABC  DEF123 12 Y 200 
15-Jan-17 R 123  ABC  DEF123 12 Y 300 
20-Jan-17 R 123  ABC  DEF123 10 Y 300 
26-Jan-17 R 456  RST  DEF456 8 N 200 
26-Jan-17 R 456  RST  DEF456 8 N 300 
2-Feb-17  Q 123  ABC  ABC123 12 Y 300 

現在我需要刪除對每個EMP_ID的重複行(重複如果EMP_NAME,DEPT,OST和排名相同)。如果2行有這4個值相同和enroll_date不同,那麼我不需要刪除該行。如果2行具有相同的登記日期並且4個字段(OST,EMP_Name,DEPT和等級)相同,那麼我需要保留具有最高塊的1000行(其次是300,然後是200,依此類推) 因此刪除之後數據我的表應該有這些行:

Enroll Date STS EMP_ID EMP_Name DEPT Rank OST BLOCK 
12-Jan-17 Q 123  ABC  ABC123 12  Y 1000  
14-Jan-17 Q 123  ABC  DEF123 12  Y 1000  
15-Jan-17 R 123  ABC  DEF123 12  Y 100 
2-Feb-17  Q 123  ABC  ABC123 12  Y 300 
20-Jan-17 R 123  ABC  DEF123 10  Y 300 
26-Jan-17 R 456  RST  DEF456 8  N 200 
26-Jan-17 R 456  RST  DEF456 8  N 300 

我嘗試使用下面的查詢,並會刪除已氡> 1

SELECT enroll_date,STS,BLOCK,EMP_ID,EMP_NAME,DEPT,RANK,OST行, row_number()over(分區BY emp_id,enroll_date,emp_name,dept,ost,rank ORDER BY enroll_date ASC,block DESC)FROM employee

但我每次只得到1。

有人可以檢查這裏的問題或建議一些其他方式來這樣做嗎?

+0

三行與15月都得到氡爲1?這些日期值是否都是午夜時分 - 對於那些(或全部)行,'to_char(enroll_date,'SYYYY-MM-DD HH24:MI:SS')'顯示時間還是oart?如果他們不是午夜的話,他們應該是嗎? –

+0

請詳細解釋:「if ** 2 rows ** have .... then I need not delete ** that row **」。當你有兩行時,哪一行是「那行」? – mathguy

+0

@ Mathguy- 「如果2行的這4個值相同,並且enroll_date不同,那麼我不需要刪除那一行」 這意味着如果表中的任何2行具有完全相同的值(所有4列應具有相同的值)列OST,EMP_Name,DEPT和等級,那麼需要刪除行。但是在相同的情況下,如果對於OST,EMP_Name,DEPT和rank具有完全相同值的任何2行,enroll_date不同,那麼我們需要保留兩行。 – Mishti

回答

0

它看起來像你的enroll_date值有非午夜時間,所以劃分這些也使得這些組合是獨特的(即使他們只看到日期部分時看不到它)。

我最初的想法是,你的分析row_number()被太多列分隔了,而且你不應該包含你想要排序的日期值 - 它並沒有真正意義上的分割和排序同樣的事情,因爲它是獨一無二的。減少你真的想檢查對列,也許是爲了:

row_number() over (partition BY emp_id, emp_name, dept, ost, rank 
    ORDER BY enroll_date ASC, block DESC) 

會產生不同的等級,而不是全部爲1,但我不認爲這是正確的;這可能會使您的輔助塊排序有點多餘,因爲對於一個ID,您可能不會有兩行完全相同的時間。也許不太可能,但不是不可能的。

重新讀你的措辭我不認爲你想按enroll_date在所有的訂購,而你想要日期而不是分區;但是,因爲它包含您顯然是想忽略這個練習非午夜時間,分區必須是對截斷日期(頭尾時間倒流到午夜,默認爲:

row_number() over (partition BY trunc(enroll_date), emp_id, emp_name, dept, ost, rank 
    ORDER BY block DESC) 

隨着您的樣本數據作爲CTE,包括每一天中不同的時間內,和一個額外的行把一切都相同的,但到目前爲止,這說明你的原始rn和我的兩個計算值:

with employee (enroll_date, sts, emp_id, emp_name, dept, rank, ost, block) as (
    select to_date('12-Jan-17 00:00:00', 'DD-Mon-RR HH24:MI:SS'), 'Q', 123, 'ABC', 'ABC123', 12, 'Y', 1000 from dual 
    union all select to_date('14-Jan-17 00:00:00', 'DD-Mon-RR HH24:MI:SS'), 'Q', 123, 'ABC', 'DEF123', 12, 'Y', 1000 from dual 
    union all select to_date('15-Jan-17 00:00:01', 'DD-Mon-RR HH24:MI:SS'), 'R', 123, 'ABC', 'DEF123', 12, 'Y', 100 from dual 
    union all select to_date('15-Jan-17 00:00:02', 'DD-Mon-RR HH24:MI:SS'), 'R', 123, 'ABC', 'DEF123', 12, 'Y', 200 from dual 
    union all select to_date('15-Jan-17 00:00:03', 'DD-Mon-RR HH24:MI:SS'), 'R', 123, 'ABC', 'DEF123', 12, 'Y', 300 from dual 
    union all select to_date('20-Jan-17 00:00:00', 'DD-Mon-RR HH24:MI:SS'), 'R', 123, 'ABC', 'DEF123', 10, 'Y', 300 from dual 
    union all select to_date('26-Jan-17 00:00:00', 'DD-Mon-RR HH24:MI:SS'), 'R', 456, 'RST', 'DEF456', 8, 'N', 200 from dual 
    union all select to_date('26-Jan-17 00:00:01', 'DD-Mon-RR HH24:MI:SS'), 'R', 456, 'RST', 'DEF456', 8, 'N', 300 from dual 
    union all select to_date('2-Feb-17 00:00:00', 'DD-Mon-RR HH24:MI:SS'), 'Q', 123, 'ABC', 'ABC123', 12, 'Y', 300 from dual 
    union all select to_date('3-Feb-17 00:00:00', 'DD-Mon-RR HH24:MI:SS'), 'Q', 123, 'ABC', 'ABC123', 12, 'Y', 300 from dual 
) 
SELECT to_char(enroll_date, 'DD-Mon-RR') as date_only, 
    enroll_date, sts, block, emp_id, emp_name, dept, rank, ost, 
    row_number() over (partition BY emp_id, enroll_date, emp_name, dept, ost, rank 
    ORDER BY enroll_date ASC, block DESC) your_rn, 
    row_number() over (partition BY emp_id, emp_name, dept, ost, rank 
    ORDER BY enroll_date ASC, block DESC) my_rn_1, 
    row_number() over (partition BY trunc(enroll_date), emp_id, emp_name, dept, ost, rank 
    ORDER BY block DESC) as my_rn_2 
FROM employee 
ORDER BY enroll_date; 

DATE_ONLY ENROLL_DATE   S BLOCK EMP_ID EMP DEPT RANK O YOUR_RN MY_RN_1 MY_RN_2 
--------- ------------------- - ----- ------ --- ------ ---- - ------- ------- ------- 
12-Jan-17 2017-01-12 00:00:00 Q 1000 123 ABC ABC123 12 Y  1  1  1 
14-Jan-17 2017-01-14 00:00:00 Q 1000 123 ABC DEF123 12 Y  1  1  1 
15-Jan-17 2017-01-15 00:00:01 R 100 123 ABC DEF123 12 Y  1  2  3 
15-Jan-17 2017-01-15 00:00:02 R 200 123 ABC DEF123 12 Y  1  3  2 
15-Jan-17 2017-01-15 00:00:03 R 300 123 ABC DEF123 12 Y  1  4  1 
20-Jan-17 2017-01-20 00:00:00 R 300 123 ABC DEF123 10 Y  1  1  1 
26-Jan-17 2017-01-26 00:00:00 R 200 456 RST DEF456 8 N  1  1  2 
26-Jan-17 2017-01-26 00:00:01 R 300 456 RST DEF456 8 N  1  2  1 
02-Feb-17 2017-02-02 00:00:00 Q 300 123 ABC ABC123 12 Y  1  2  1 
03-Feb-17 2017-02-03 00:00:00 Q 300 123 ABC ABC123 12 Y  1  3  1 

要確定的行刪除你可以使用子查詢:

SELECT enroll_date, sts, block, emp_id, emp_name, dept, rank, ost 
FROM (
    SELECT enroll_date, sts, block, emp_id, emp_name, dept, rank, ost, 
    row_number() over (partition BY trunc(enroll_date), emp_id, emp_name, dept, ost, rank 
     ORDER BY block DESC) as my_rn_2 
    FROM employee 
) 
WHERE my_rn_2 > 1 
ORDER BY enroll_date; 

ENROLL_DATE   S BLOCK EMP_ID EMP DEPT RANK O 
------------------- - ----- ------ --- ------ ---- - 
2017-01-15 00:00:01 R 100 123 ABC DEF123 12 Y 
2017-01-15 00:00:02 R 200 123 ABC DEF123 12 Y 
2017-01-26 00:00:00 R 200 456 RST DEF456 8 N 

雖然您需要決定實際上對您的數據和要求有意義的內容。

+0

我認爲你是正確的,編輯查詢並張貼與之相關的信息。它現在通過使用trunc函數更改enroll_date來工作。 – Mishti

+0

是否確定要在某一天使用具有最高塊的行,即使是那一天有其他行的其他行也是如此?你忽略了時代 - 這可能實際上就是你想要的,但我會在刪除任何東西之前檢查它是否正確。不知道代表什麼區塊,這聽起來有點奇怪。 –

0

我創建一個臨時表,將所有非重複值:

create table employee_temp as 
with duplicates as (
SELECT enroll_date, STS, BLOCK, EMP_ID, EMP_NAME, DEPT,RANK, OST, row_number()  over (partition BY emp_id, trunc(enroll_date),emp_name, dept, ost, rank ORDER BY enroll_date ASC, block DESC)rn FROM employee) 
SELECT enroll_date, STS, BLOCK, EMP_ID, EMP_NAME, DEPT,RANK, OST from duplicates where rn =1;