2017-02-10 321 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; 

,那麼基督教有一個合理的解決方案。