0

I have the following query:

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')

I want to show all changes in a project between certain dates. This works fine. However, I have a lot of duplicates (such as if someone changed the same attribute on the same project 50 times). I want to filter those out and only show the most recent time a certain attribute was changed on the project. I can do something like this:

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

However, now I can't JOIN anything in. For example, if I try:

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

I'll get the error:

ORA-00979: not a GROUP BY expression

Is there a better way to filter out duplicate changes to the same project?

4

3 に答える 3

2

You can also use analytic functions:

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
于 2012-07-25T22:15:33.740 に答える
1

The HAVING should be the last line on your query:

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')
于 2012-07-25T22:08:13.537 に答える
0

The fundamental rule of SQL query composition is the following. Wrap your working SQl query in parenthesis, and inline it as a view:

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

Regarding the syntax of your last query, group by list is expected to accommodate more columns, than your select clause, not less (excluding the aggregates, of course).

于 2012-07-25T22:17:14.677 に答える