2017-03-12 7 views
2

特定の日付範囲に対して、フィールド値が変更されたすべての行(FROMおよびTO日付)を返す必要があります。変更されたフィールド値は、画面上に別の色で表示されます。Oracle SQL - 複数の行からデータを選択して結合する方法

特定の期間に変更が発生したすべての従業員レコードを返すことができます。ただし、従業員の記録が選択した期間内に複数回変更された場合は、異なるX_FLAG列ごとに1つの従業員レコードを組み合わせた値で返す必要があります。 1は変更が発生したことを示し、0は変更がないことを示します。

表DDLは次のとおりです。

CREATE TABLE "EMPLOYEE_DATA" 
    ( "EMPLOYEE_ID" NUMBER(20,0), 
    "EMPLOYEE_NAME" VARCHAR2(100 BYTE), 
    "EMPLOYEE_NAME_FLAG" NUMBER(1,0), 
    "EMPLOYEE_ROLE" VARCHAR2(100 BYTE), 
    "EMPLOYEE_ROLE_FLAG" NUMBER(1,0), 
    "EMPLOYEE_SALARY" VARCHAR2(100 BYTE), 
    "EMPLOYEE_SALARY_FLAG" NUMBER(1,0), 
    "DATE_VALID_FROM" DATE, 
    "DATE_VALID_TO" DATE, 
    "HAS_RECORD_CHANGED" NUMBER(1,0), 
    "CURRENT_ROW_IND" NUMBER(1,0) 
    ); 

モックデータは次のとおりです。

Insert into EMPLOYEE_DATA (EMPLOYEE_ID,EMPLOYEE_NAME,EMPLOYEE_NAME_FLAG,EMPLOYEE_ROLE,EMPLOYEE_ROLE_FLAG,EMPLOYEE_SALARY,EMPLOYEE_SALARY_FLAG, DATE_VALID_FROM,DATE_VALID_TO,HAS_RECORD_CHANGED,CURRENT_ROW_IND) values (1,'John Smith',0,'Associate',0,'1',0,to_date('01-FEB-17','DD-MON-RR'),to_date('28-FEB-17','DD-MON-RR'),0,0); 
Insert into EMPLOYEE_DATA (EMPLOYEE_ID,EMPLOYEE_NAME,EMPLOYEE_NAME_FLAG,EMPLOYEE_ROLE,EMPLOYEE_ROLE_FLAG,EMPLOYEE_SALARY,EMPLOYEE_SALARY_FLAG, DATE_VALID_FROM,DATE_VALID_TO,HAS_RECORD_CHANGED,CURRENT_ROW_IND) values (2,'Katy Brown',0,'Team Leader',0,'7',0, to_date('01-FEB-17','DD-MON-RR'),to_date('28-FEB-17','DD-MON-RR'),0,0); 
Insert into EMPLOYEE_DATA (EMPLOYEE_ID,EMPLOYEE_NAME,EMPLOYEE_NAME_FLAG,EMPLOYEE_ROLE,EMPLOYEE_ROLE_FLAG,EMPLOYEE_SALARY,EMPLOYEE_SALARY_FLAG, DATE_VALID_FROM,DATE_VALID_TO,HAS_RECORD_CHANGED,CURRENT_ROW_IND) values (2,'Katy Brown',0,'Team Leader',0,'7',0, to_date('01-APR-17','DD-MON-RR'),to_date('31-DEC-99','DD-MON-RR'),1,1); 
Insert into EMPLOYEE_DATA (EMPLOYEE_ID,EMPLOYEE_NAME,EMPLOYEE_NAME_FLAG,EMPLOYEE_ROLE,EMPLOYEE_ROLE_FLAG,EMPLOYEE_SALARY,EMPLOYEE_SALARY_FLAG, DATE_VALID_FROM,DATE_VALID_TO,HAS_RECORD_CHANGED,CURRENT_ROW_IND) values (3,'Ian Jones',1,'Delivery Manager',1,'3',1, to_date('01-MAR-17','DD-MON-RR'),to_date('31-DEC-99','DD-MON-RR'),1,1); 
Insert into EMPLOYEE_DATA (EMPLOYEE_ID,EMPLOYEE_NAME,EMPLOYEE_NAME_FLAG,EMPLOYEE_ROLE,EMPLOYEE_ROLE_FLAG,EMPLOYEE_SALARY,EMPLOYEE_SALARY_FLAG, DATE_VALID_FROM,DATE_VALID_TO,HAS_RECORD_CHANGED,CURRENT_ROW_IND) values (1,'John Smith',0,'Analyst',1,'1',0, to_date('01-MAR-17','DD-MON-RR'),to_date('31-MAR-17','DD-MON-RR'),1,0); 
Insert into EMPLOYEE_DATA (EMPLOYEE_ID,EMPLOYEE_NAME,EMPLOYEE_NAME_FLAG,EMPLOYEE_ROLE,EMPLOYEE_ROLE_FLAG,EMPLOYEE_SALARY,EMPLOYEE_SALARY_FLAG, DATE_VALID_FROM,DATE_VALID_TO,HAS_RECORD_CHANGED,CURRENT_ROW_IND) values (1,'John Smith',0,'Analyst',0,'2',1, to_date('01-APR-17','DD-MON-RR'),to_date('31-DEC-99','DD-MON-RR'),1,1); 

私のクエリは次のとおりです。私の最後のクエリで

SELECT * 
FROM EMPLOYEE_DATA 
WHERE DATE_VALID_FROM <= TO_DATE('01/04/2017', 'dd/mm/yyyy') 
    AND DATE_VALID_TO >= TO_DATE('01/01/2017', 'dd/mm/yyyy') 
    AND HAS_RECORD_CHANGED = '1' 
ORDER BY EMPLOYEE_ID ASC, DATE_VALID_FROM ASC; 

、私は戻すために、次の行を追加します現在のレコードAND CURRENT_ROW_IND = '1'。ジョンスミスのデータを結合して、前と現在のレコード(John Smithの場合)のEMPLOYEE_ROLE_FLAGとを結合する必要があることを示すために、これを残しました。

EDIT - オリジナルとターゲットの結果を追加しました。可能であれば、一意の従業員ごとにX_FLAG列の最大値を得るために集計する必要があります。

オリジナル

EMPLOYEE_ID EMPLOYEE_NAME EMPLOYEE_NAME_FLAG EMPLOYEE_ROLE EMPLOYEE_ROLE_FLAG EMPLOYEE_SALARY EMPLOYEE_SALARY_FLAG DATE_VALID_FROM DATE_VALID_TO HAS_RECORD_CHANGED CURRENT_ROW_IND 
1    John Smith  0     Associate    0     1    0     01-Feb-17   28-Feb-17  0     0 
2    Katy Brown  0     Team Leader    0     7    0     01-Feb-17   28-Feb-17  0     0 
2    Katy Brown  0     Team Leader    0     7    0     01-Apr-17   31-Dec-99  1     1 
3    Ian Jones  1     Delivery Manager  1     3    1     01-Mar-17   31-Dec-99  1     1 
1    John Smith  0     Analyst     1     0    0     01-Mar-17   31-Mar-17  1     0 
1    John Smith  0     Analyst     0     1    1     01-Apr-17   31-Dec-99  1     1 

ターゲット

EMPLOYEE_ID EMPLOYEE_NAME EMPLOYEE_NAME_FLAG EMPLOYEE_ROLE EMPLOYEE_ROLE_FLAG EMPLOYEE_SALARY EMPLOYEE_SALARY_FLAG DATE_VALID_FROM DATE_VALID_TO HAS_RECORD_CHANGED CURRENT_ROW_IND 
1   John Smith  0     Analyst      1     1    1    01-Apr-17 31-Dec-99  1     1 
2   Katy Brown  0     Team Leader     0     7    0    01-Apr-17 31-Dec-99  1     1 
3   Ian Jones  1     Delivery Manager   1     3    1    01-Mar-17 31-Dec-99  1     1 
+0

は、あなたが期待される出力を表示することができます? –

+0

@ nsc909私の反応が理にかなっていないかどうか教えてください。その場合はサンプル出力を教えてください – Pons

+0

@vkpサンプル出力を追加しようとしていますが、フォーマットを整理するだけです。 – nsc909

答えて

1

は、ユニットレベルのクエリが最大のフラグを算出し、集計クエリで参加する派生テーブルを検討し、あなたを達成するために、クエリの下に見つけてください:

SELECT emp.*  
FROM 
    (SELECT * 
    FROM EMPLOYEE_DATA 
    WHERE DATE_VALID_FROM BETWEEN TO_DATE('01/01/2017', 'dd/mm/yyyy') 
          AND TO_DATE('01/04/2017', 'dd/mm/yyyy') 
    AND HAS_RECORD_CHANGED = 1 
) AS emp 

INNER JOIN 
    (SELECT EMPLOYEE_ID, MAX(EMPLOYEE_NAME_FLAG) AS MAX_NAME_FLAG, 
      MAX(EMPLOYEE_ROLE_FLAG) AS MAX_ROLE_FLAG, 
      MAX(EMPLOYEE_SALARY_FLAG) AS MAX_SALARY_FLAG 
    FROM EMPLOYEE_DATA 
    WHERE DATE_VALID_FROM BETWEEN TO_DATE('01/01/2017', 'dd/mm/yyyy') 
          AND TO_DATE('01/04/2017', 'dd/mm/yyyy') 
    AND HAS_RECORD_CHANGED = 1 
    GROUP BY EMPLOYEE_ID 
) AS agg 

ON emp.EMPLOYEE_ID = agg.EMPLOYEE_ID 
AND emp.EMPLOYEE_NAME_FLAG = agg.MAX_NAME_FLAG 
AND emp.EMPLOYEE_ROLE_FLAG = agg.MAX_ROLE_FLAG 
AND emp.EMPLOYEE_SALARY_FLAG = agg.MAX_SALARY_FLAG 

ORDER BY emp.EMPLOYEE_ID ASC, emp.DATE_VALID_FROM ASC 
1

可能であれば、私はそれぞれの固有の従業員のX_FLAG列の最大値を取得するために集約する必要があります。

上記の要件のためには、GROUP BYは正しく動作しますか?

ターゲット

SELECT EMPLOYEE_ID 
    , EMPLOYEE_NAME 
    , MIN(EMPLOYEE_NAME_FLAG) EMPLOYEE_NAME_FLAG 
    , EMPLOYEE_ROLE 
    , MAX(EMPLOYEE_ROLE_FLAG) EMPLOYEE_ROLE_FLAG 
    , MIN(EMPLOYEE_SALARY) EMPLOYEE_SALARY 
    , MAX(EMPLOYEE_SALARY_FLAG) EMPLOYEE_SALARY_FLAG 
    , MAX(DATE_VALID_FROM) DATE_VALID_FROM 
    , MAX(DATE_VALID_TO) DATE_VALID_TO 
    , HAS_RECORD_CHANGED 
    , MAX(CURRENT_ROW_IND) CURRENT_ROW_IND 
FROM EMPLOYEE_DATA 
WHERE HAS_RECORD_CHANGED = 1 
    AND DATE_VALID_FROM BETWEEN TO_DATE('01/01/2017', 'dd/mm/yyyy') 
          AND TO_DATE('01/04/2017', 'dd/mm/yyyy') 
GROUP BY EMPLOYEE_ID 
    , EMPLOYEE_NAME 
    , EMPLOYEE_ROLE 
    , HAS_RECORD_CHANGED 
ORDER BY EMPLOYEE_ID ASC 
    , DATE_VALID_FROM ASC;