2008-10-08 81 views
4

我知道計算器會幫助我除了知道什麼是「最喜歡的編程動畫片」:P甲骨文加入(左外,右等:S)

這是公認的答案是: Bill Karwin

感謝所有的幫助(我想你加倍投全部)

我查詢弄成這個樣子(這是真實的)

SELECT 
    accepted.folio, 
    COALESCE(inprog.activityin, accepted.activityin) as activityin, 
    inprog.participantin, 
    accepted.completiondate 
FROM performance accepted 
    LEFT OUTER JOIN performance inprog 
     ON(accepted.folio = inprog.folio 
      AND inprog.ACTIVITYIN 
      IN (4, 435)     -- both are ids for inprogress 
      AND inprog.PARTICIPANTIN != 1 ) -- Ignore the "bot" participant 
    LEFT OUTER JOIN performance closed 
     ON(accepted.folio = closed.folio 
      AND closed.ACTIVITYIN IN (10,436, 4, 430 )) -- all these are closed or cancelled 
WHERE accepted.ACTIVITYIN IN (3, 429)  --- both are id for new 
AND accepted.folio IS NOT NULL 
AND closed.folio IS NULL; 

現在我只需要與其他表格一起閱讀一份可讀的報告。


原帖

你好。

我掙扎了6個小時左右。現在有一個DB查詢(我很長一段時間的剋星)

我有像一些字段的數據表:

table performance( 
    identifier varchar, 
    activity number, 
    participant number, 
    closedate date, 
) 

它是用來保持門票

歷史

標識符的軌道:是客戶ID喜歡(NAF0000001)

活動:是這裏的門票是FK(新,IN_PROGRESS,拒絕,關閉等)

參與者:是誰在這一點上票

參加closedate的FK:是當活動結束的日期。

編輯:我應該說「completiondate」而不是closedate。這是活動完成的日期,當票證關閉時不需要。

例如一個典型的歷史可以是這樣的:

 
identifier|activity|participant|closedate 
------------------------------------------- 
NA00000001|  1|   1|2008/10/08 15:00| 
------------------------------------------- 
NA00000001|  2|   2|2008/10/08 15:20| 
------------------------------------------- 
NA00000001|  3|   2|2008/10/08 15:40| 
------------------------------------------- 
NA00000001|  4|   4|2008/10/08 17:05| 
------------------------------------------- 

而參與者1 = jonh,2 =斯科特,3 =麥克風,4 =搶

和工作之外的活動1 =新,2 =進展中,3 =等待批准,4 =關閉

等等數十個其他無關信息。

那麼我的問題是以下。

我已經成功地創建一個查詢,其中,當車票被打開了,我可以知道和關閉

它是這樣的:

select 
    a.identifier, 
    a.participant, 
    a.closedate as start, 
    b.closedate as finish  
from 
    performance a, 
    performance b 
where 
    a.activity = 1 -- new 
    and b.activity = 4 -- closed 
    and a.identifier = b.identifier 

但我不知道票是什麼關閉,誰在參加。

到目前爲止,我有這樣的事情:

select 
    a.identifier, 
    a.participant, 
    a.closedate as start 
from 
    performance a   
where 
    a.activity = 1 -- new 
    and a.identifier not in (select identifier from performance where activity = 4) --closed 

這是給我的一切誰都有一個開始(新= 1),但不關閉(閉合= 4)

但對那些這裏最大的問題是打印開票的參與者,但我需要參與者。所以我將「進行中」活動添加到查詢中。

select 
    a.identifier, 
    a.participant, 
    a.closedate as start 
from 
    performance a, 
    performance b   
where 
    a.activity = 1 -- new   
    and a.identifier not in (select identifier from performance where activity = 4) --closed 
    and b.identifier = a.identifier 
    and b.activity = 2 -- inprogress.. 

但並不是所有的都是「新」的行是「INPROGRESS」,並與該查詢我放下所有的人。

我需要的是顯示所有「進行中」參與者,如果票證不是「進行中」,它將顯示爲空。

財產以後像

 
    identifier|activity|participant|closedate 
------------------------------------------- 
NA00000002|  1|   |2008/10/08 15:00| 
------------------------------------------- 
NA00000003|  1|   |2008/10/08 15:20| 
------------------------------------------- 
NA00000004|  1|   |2008/10/08 15:40| 
------------------------------------------- 
NA00000005|  2|   4|2008/10/08 15:40| 
------------------------------------------- 
NA00000006|  2|   4|2008/10/08 15:40| 

在這種情況下

NA002,NA003和NA004是 「新」,所以沒有參與者被示

雖然

NA005和NA006是被「參加者(act = 2)」,他們正在參加搶劫(參與者4)

所以我記得有這個東西叫左外連接或類似的東西,但我永遠不會理解它。我想知道的是,如何獲取「進行中」和「新建」且未關閉的標識符。

大概休息一下可能會幫助我清除自己的想法。如果有人知道如何去做,我會很感激。

通過我嘗試過的方式:

select 
    a.identifier, 
    a.participant, 
    a.closedate as start 
from 
    performance a 
    left outer join 
    performance b 
    on  
    b.identifier = a.identifier 
where 
    a.activity = 1 -- new   
    and a.identifier not in (select identifier from performance where activity = 4) --closed 
    and b.activity = 2 -- inprogress.. 

但給了我同樣的結果與以前(刪除僅在「新」記錄)

回答

3

嘗試類似這(我沒有測試過):

SELECT p_new.identifier, COALESCE(p_inprog.activity, p_new.activity) AS activity, 
    p_inprog.participant, COALESCE(p_inprog.closedate, p_new.closedate) AS closedate 
FROM performance p_new 
    LEFT OUTER JOIN performance p_inprog 
    ON (p_new.identifier = p_inprog.identifier AND p_inprog.activity = 2) 
    LEFT OUTER JOIN performance p_closed 
    ON (p_new.identifier = p_closed.identifier AND p_closed.activity = 4) 
WHERE p_new.activity = 1 
    AND p_closed.identifier IS NULL; 

我認爲,人們相信外連接難度比他們真的是。例如:

A LEFT OUTER JOIN B ON (...condition...) 

這將返回從A中的所有行,不論是否有任何匹配的行中B.如果B匹配任何行,把所有列B. *爲NULL的結果中該行設置A.連接條件可以是B中的行必須滿足的表達式,否則它不包含在連接中。所以,A中的更多行將是獨奏。

3

通常情況下,更好的方式來寫這些是與EXISTS。第一個是:

select * from performance p1 
where not exists 
    (select * from performance p2 
     where p2.identifier = p1.identifier and p2.activity = 4) 

這種方式可以讓你做一鍵查找上performance.identifier,而不是潛在不必建立在(select identifier from performance where activity=4)標識符的龐大名單。

+0

如何在狀態2下顯示「參與者」,如果在其他狀態下沒有任何內容?我認爲這與左側外部事物有關..我是錯了嗎?... – OscarRyz 2008-10-08 23:44:12

+0

非常有幫助btw – OscarRyz 2008-10-09 19:08:00

0

首先,如果您可以讓一個客戶同時打開多個票據,您可能會遇到設計問題。理想情況下,您應該擁有ticket_id,然後您可以使用ticket_id而不是標識符執行Andy的查詢。

+0

那麼標識符就是「ticket_id」,這不是一個使用ticket_id的查詢,而是一個按周,日,小時等顯示生產力的報告。設計來自第三方產品。你有什麼想法我怎麼能做到這一點? – OscarRyz 2008-10-08 23:53:30

2

我認爲這應該做到這一點。

第一部分獲取所有新的記錄,未關閉且未進行。第二部分獲取所有進展記錄。然後我們將它們加入到一起,我們還可以通過在此查詢周圍包裝'SELECT * FROM'來對標識符進行排序。

select 
    a.identifier, 
    a.participant, 
    a.closedate as start 
from 
    performance a 
where 
    a.activity = 1 
    and not exists (select identifier 
        from performance b 
        where b.activity = 4 
        and b.identifier = a.identifier) 
    and not exists (select identifier 
        from performance c 
        where c.activity = 2 
        and c.identifier = a.identifier) 
UNION ALL 
select 
    a.identifier, 
    a.participant, 
    a.closedate as start 
from 
    performance a 
where 
    a.activity = 2 
    and not exists (select identifier 
        from performance b 
        where b.activity = 4 
        and b.identifier = a.identifier); 
+0

Uuhhhgg ..。幾乎。事實證明,2中的所有人都已經在1.因爲這是歷史,而不是狀態。但是......在你的建議下我非常接近。我會發布由此產生的怪物...... :) – OscarRyz 2008-10-09 00:25:01

+0

好消息!我很高興我終於在這裏幫助別人:D – abarax 2008-10-09 00:32:28

+0

;)Abarax,你的文章絕對改變了我對我想要的東西的理解,非常感謝。不幸的是,當我只需要一個記錄時,它會複製記錄(N001 1和N002 2)。 我嘗試下面的Bill Karwin發佈的解決方案並且效果很好。無論如何感謝+1給你。 – OscarRyz 2008-10-09 17:22:28

0

什麼票都沒有關閉:正在出席

select identifier as closed_identifier 
    from performance where identifier not exists 
    (select identifier from performance where activity=4) 

門票:

select identifier as inprogress_identifier, participant performance 
    from performance where activity=2 

未關閉的門票,與正在被出席的參與者:

select * from 
    (select identifier as notclosed_identifier 
    from performance where identifier not exists 
    (select identifier from performance where activity=4)) closed 
left join 
    (select identifier as inprogress_identifier, participant performance 
    from performance where activity=2) attended 
on notclosed_identifier=inprogress_identifier 
1

我會建議你想要的是最早的記錄(可能,但不一定是活動= 1的記錄)和最近的記錄(不管活動編號)。如果最近的記錄的活動是4,那麼票證是關閉的。否則,參與者是當前票證的持有人。如果可以重新打開票證,則僅通過在活動= 4時進行匹配即可引入潛在的錯誤。

其實,根據你的例子,你可能甚至不需要最早的記錄。如何處理以下內容:

SELECT 
     identifier, 
     activity, 
     participant, 
     closedate 
    FROM 
     performance a 
    WHERE 
     (a.identifier, a.closedate) in 
      (select b.identifier, max(b.closedate) 
       from performance b 
       group by b.identifier 
      ) 
; 
0

可能您可以使用這種查詢作爲起點。

select x.identifier, 
     max(x.p_1) as new_participant, max(x.c_1) as new_date, 
     max(x.p_2) as inprogress_participant, max(x.c_2) as inprogress_date, 
     max(x.p_3) as approval_participant, max(x.c_3) as approval_date, 
     max(x.p_4) as closing_participant, max(x.c_4) as closing_date 
    from (
     select a.identifier, 
       decode (activity, 1, participant, null) as p_1, decode (activity, 1, closedate, null) as c_1, 
       decode (activity, 2, participant, null) as p_2, decode (activity, 2, closedate, null) as c_2, 
       decode (activity, 3, participant, null) as p_3, decode (activity, 3, closedate, null) as c_3, 
       decode (activity, 4, participant, null) as p_4, decode (activity, 4, closedate, null) as c_4 
      from performance a 
     ) x 
group by x.identifier 

這個想法是將你的表從行放入字段,並基於它創建一個視圖。 您可以根據此視圖創建報告。

問候,

0

只是,別人可能會建立在一個快速的想法(未經測試,但我希望這個想法遇到):

首先,選擇所有尚未閉合的活動(如他人發佈):

select id, 
(select participant 
    from performance p3 
    where p3.activity=3 and p1.id=p2.id) 
from performance p1 where identifier not exists 
    (select * from performance p2 where activity=4 and p1.id=p2.id) 

select id 
from performance p1 where identifier not exists 
    (select * from performance p2 where activity=4 and p1.id=p2.id) 

然後,您可以通過在SELECT子句中增加一個子查詢中添加參加活動的人

如果沒有活動記錄這個id,子查詢返回null,這正是我們需要的。

希望這有助於 - 請在必要時展開。

1

如何:

SELECT * FROM (
    SELECT identifier, 
     MAX(activity) activity, 
     MAX(participant) KEEP (DENSE_RANK LAST ORDER BY activity) 
    FROM performance 
    GROUP BY identifier 
) 
WHERE activity in (1,2) 

內查詢都給出了每張票及其對應的參與者最新的活動。外部查詢將其過濾爲活動爲「新」或「正在進行」的活動。

我喜歡DENSE_RANK函數。