2017-02-10 391 views
1

我正在使用Oracle(SQL Developer)。请找到实例并希望得到的结果如下(的选择目的是要找出谁提交的项目A和有没有做过B工程的任何活动但人):ORACLE MAX GROUP BY

数据表:

CREATE TABLE "XXX"."TABLE1" 
    ( "STATUS" VARCHAR2(20 BYTE), 
     "PROJECT_NAME" VARCHAR2(20 BYTE), 
    "VERSION_NUMBER" NUMBER, 
    "PERSON" VARCHAR2(20 BYTE) 
    ); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('SUBMITTED','A','0','PETER'); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('SUBMITTED','A','0','JOHN'); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('SUBMITTED','A','1','JOHN'); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('NEW','A','2','JOHN'); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('SUBMITTED','A','0','MARY'); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('SUBMITTED','B','0','PETER'); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('NEW','B','1','PETER'); 
Insert into XXX.TABLE1 (STATUS,PROJECT_NAME,VERSION_NUMBER,PERSON) values ('SUBMITTED','B','0','JOHN'); 

创建的表应该是这样的:

TABLE1: 
TABLE1.STATUS TABLE1.PROJECT_NAME TABLE1.VERSION_NUMBER TABLE1.PERSON 
SUBMITTED  A     0      PETER 
SUBMITTED  A     0      JOHN 
SUBMITTED  A     1      JOHN 
NEW    A     2      JOHN 
SUBMITTED  A     0      MARY 
SUBMITTED  B     0      PETER 
NEW    B     1      PETER 
SUBMITTED  B     0      JOHN 

结果我想要得到的是这样的:

STATUS  PROJECT_NAME VERSION_NUMBER PERSON STATUS_1 PROJECT_NAME_1 VERSION_NUMBER_1 PERSON_1 
SUBMITTED A    0    PETER NEW   B    1     PETER 
SUBMITTED A    1    JOHN SUBMITTED B    0     JOHN 
SUBMITTED A    0    MARY     

选择,我现在用的是:

select t.*,v.* 
from TABLE1 t 
left outer join (select u.* 
    from TABLE1 u 
where exists (select max(z.VERSION_NUMBER) 
,z.PERSON 
,z.PROJECT_NAME 
    from TABLE1 z 
    where z.PROJECT_NAME = 'B' 
    and u.PROJECT_NAME = z.PROJECT_NAME 
    and u.PERSON = z.PERSON 
group by z.PERSON, z.PROJECT_NAME 
having u.VERSION_NUMBER = max(z.VERSION_NUMBER))) v 
on t.PERSON = v.PERSON 
where exists (select max (w.VERSION_NUMBER) 
,w.PERSON 
,w.PROJECT_NAME 
from TABLE1 w 
where w.PROJECT_NAME = 'A' 
and w.STATUS = 'SUBMITTED' 
and t.PROJECT_NAME = w.PROJECT_NAME 
and t.PERSON = w.PERSON 
group by w.PERSON, w.PROJECT_NAME 
having t.VERSION_NUMBER = max (w.VERSION_NUMBER)) 

问题:什么是最好的(右)的方式来写这样的选择(最佳实践),我应该更好地利用分析功能,或者使用别的东西,而不是存在?

回答

1

我想你已经过于复杂这...的选择

WITH 
project_status (status, project_name, version_number, person) 
AS 
(SELECT 'SUBMITTED','A','0','PETER' FROM dual UNION ALL 
    SELECT 'SUBMITTED','A','0','JOHN' FROM dual UNION ALL 
    SELECT 'SUBMITTED','A','1','JOHN' FROM dual UNION ALL 
    SELECT 'NEW','A','2','JOHN' FROM dual UNION ALL 
    SELECT 'SUBMITTED','A','0','MARY' FROM dual UNION ALL 
    SELECT 'SUBMITTED','B','0','PETER' FROM dual UNION ALL 
    SELECT 'NEW','B','1','PETER' FROM dual UNION ALL 
    SELECT 'SUBMITTED','B','0','JOHN' FROM dual 
) 
SELECT DISTINCT 
ps.person 
,ps.project_name 
,ps.status 
FROM 
project_status ps 
WHERE 1=1 
AND ps.project_name = 'A' 
AND ps.status = 'SUBMITTED' 
AND NOT EXISTS 
(SELECT 1 
    FROM project_status ps2 
    WHERE ps2.person = ps.person 
    AND ps2.project_name = 'B' 
) 
; 
0

目的是要找出谁提交的项目A和 没有做过B工程的任何活动,但

如果您的目的只是为了获得,那么您不需要完整的行。要回答这个问题的方法之一是使用group byhaving:如果您需要完整的行

select t1.person 
from "XXX"."TABLE1" t1 
group by t1.person 
having sum(case when project_name = 'A' and status = 'New' then 1 else 0 end) > 0 and 
     sum(case when project_name = 'B' then 1 else 0 end) = 0; 

,那么基督教有一个合理的解决方案。