2012-07-25 28 views
0

我有以下查詢:甲骨文 - 如何過濾掉重複的行,而無需使用GROUP BY

select 
    C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID, C.MODIFIEDDATE, V.NAME 
from TPM_PROJECTCHANGES C 
inner join TPM_PROJECTVERSION V ON C.PROJECTID = V.PROJECTID AND C.VERSIONID = V.VERSIONID 
where C.MODIFIEDDATE BETWEEN TO_DATE('07/18/12', 'MM/DD/YY') and TO_DATE('07/25/12', 'MM/DD/YY') 

我想表明在某些日期之間的項目的所有更改。這工作正常。但是,我有很多重複項目(例如,如果某人在同一個項目上更改了同一個屬性50次)。我想將它們過濾出來,只顯示項目中某個屬性發生更改的最近時間。我可以做這樣的事情:

select 
    C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID, MAX(C.MODIFIEDDATE) 
from TPM_PROJECTCHANGES C 
having MAX(C.MODIFIEDDATE) BETWEEN TO_DATE('07/18/12', 'MM/DD/YY') and TO_DATE('07/25/12', 'MM/DD/YY') 
group by C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID 

不過,現在我不能在JOIN什麼。例如,如果我嘗試:

select 
    C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID, MAX(C.MODIFIEDDATE), V.NAME 
from TPM_PROJECTCHANGES C 
inner join TPM_PROJECTVERSION V ON C.PROJECTID = V.PROJECTID AND C.VERSIONID = V.VERSIONID 
having MAX(C.MODIFIEDDATE) BETWEEN TO_DATE('07/18/12', 'MM/DD/YY') and TO_DATE('07/25/12', 'MM/DD/YY') 
group by C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID 

我會得到錯誤:

ORA-00979: not a GROUP BY expression

有沒有更好的方法來濾除對同一項目的重複更改?

+1

嘗試在'group_by'之後移動'having' – rogal111 2012-07-25 22:08:13

+0

@ rogal111 - 'HAVING'的位置沒有區別。看起來Oracle(或SQL)不支持這一點,儘管它在邏輯上是有道理的。 – 2012-07-25 22:28:22

回答

2

您還可以使用分析功能:

select PROJECTID, VERSIONID, MODIFIEDATTRIBUTEID, MODIFIEDDATE, Name 
from (select C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID, C.MODIFIEDDATE, V.NAME, 
      row_number() over (partition by C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID, V.NAME 
           order by C.MODIFIEDDATE desc) as seqnum 
     from TPM_PROJECTCHANGES C inner join 
      TPM_PROJECTVERSION V ON C.PROJECTID = V.PROJECTID AND C.VERSIONID = V.VERSIONID 
     where C.MODIFIEDDATE BETWEEN TO_DATE('07/18/12', 'MM/DD/YY') and 
            TO_DATE('07/25/12', 'MM/DD/YY') 
    ) t 
where seqnum = 1 
+0

'+ 1'作爲目前唯一可行的答案,但是看起來這將會非常迅速地變得非常複雜,因爲我添加了更多列。我也擔心perf。如果沒有更好的答案發布,我會接受。 – 2012-07-25 22:34:22

1

HAVING應該在你查詢的最後一行:

select 
    C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID, MAX(C.MODIFIEDDATE), V.NAME 
from TPM_PROJECTCHANGES C 
inner join TPM_PROJECTVERSION V 
ON C.PROJECTID = V.PROJECTID AND C.VERSIONID = V.VERSIONID 
group by C.PROJECTID, C.VERSIONID, C.MODIFIEDATTRIBUTEID, V.NAME 
having MAX(C.MODIFIEDDATE) BETWEEN TO_DATE('07/18/12', 'MM/DD/YY') and TO_DATE('07/25/12', 'MM/DD/YY') 
+0

無所謂。除非我從'SELECT'列表中刪除'V.NAME',否則我不會得到'GROUP BY表達式'。 – 2012-07-25 22:15:35

+0

@MikeChristensen在答案中添加了V.NAME – Lamak 2012-07-25 22:37:02

+0

爲什麼「獨特」不適合你? – 2012-07-25 22:45:12

0

SQL查詢組成的基本規則如下。裹在括號中你的工作的SQL查詢和內聯作爲一個觀點:

select 
    V.NAME, IC.* 
from (/*working query against TPM_PROJECTCHANGES here*/) IC 
inner join TPM_PROJECTVERSION V ... 

關於你的最後一個查詢的語法,通過列表組預計可容納更多的列,比你的SELECT子句,不低於(不含當然是聚合)。

+0

你說你*不能*在JOIN表中包含值,除非這些列也在你的'GROUP BY'列表中?這就是爲什麼我要避免使用GROUP BY的原因:因爲我加入了大約5個表格,並且包含來自這些表格的*噸*列。 – 2012-07-25 22:24:37

+0

如果你不關心聚合,爲什麼不會DISTINCT足夠? – 2012-07-26 00:04:36

+0

選擇不同C.PROJECTID,C.VERSIONID,C.MODIFIEDATTRIBUTEID,C.MODIFIEDDATE,V.NAME 從TPM_PROJECTCHANGES℃的內部加入 TPM_PROJECTVERSION V ON C.PROJECTID = V.PROJECTID AND C.VERSIONID = V.VERSIONID 其中C TO_DATE('07/18/12','MM/DD/YY')和 TO_DATE('07/25/12','MM/DD/YY') – 2012-07-26 00:55:34