Discussions
Categories
- 385.5K All Categories
- 4.9K Data
- 2.5K Big Data Appliance
- 2.4K Data Science
- 453.4K Databases
- 223.2K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 47 Multilingual Engine
- 606 MySQL Community Space
- 486 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3.2K ORDS, SODA & JSON in the Database
- 585 SQLcl
- 4K SQL Developer Data Modeler
- 188K SQL & PL/SQL
- 21.5K SQL Developer
- 46 Data Integration
- 46 GoldenGate
- 298.4K Development
- 4 Application Development
- 20 Developer Projects
- 166 Programming Languages
- 295K Development Tools
- 150 DevOps
- 3.1K QA/Testing
- 646.7K Java
- 37 Java Learning Subscription
- 37.1K Database Connectivity
- 201 Java Community Process
- 108 Java 25
- 22.2K Java APIs
- 138.3K Java Development Tools
- 165.4K Java EE (Java Enterprise Edition)
- 22 Java Essentials
- 176 Java 8 Questions
- 86K Java Programming
- 82 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 208 Java User Groups
- 25 JavaScript - Nashorn
- Programs
- 667 LiveLabs
- 41 Workshops
- 10.3K Software
- 6.7K Berkeley DB Family
- 3.6K JHeadstart
- 6K Other Languages
- 2.3K Chinese
- 207 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 474 Portuguese
Need to alter existing query to fetch correct data.

Hi All,
Below is my query
WITH parameters AS
(
SELECT TO_DATE ('01-JUN-2019', 'DD-MON-YYYY') AS startdt -- Always use 4 digits for years
, TO_DATE ('30-JUN-2019', 'DD-MON-YYYY') AS enddt
, 'CWR' AS per_org
FROM dual
)
, got_business_unit AS
(
SELECT p.startdt, p.enddt
, d1.emplid, d1.per_org, d1.effdt
, CASE
WHEN b.business_unit IS NULL
THEN 'I'
ELSE d1.hr_status
END AS hr_status
, b.business_unit
FROM parameters p
JOIN ps_cts_job_dtl1 d1 ON d1.per_org = p.per_org
AND d1.effdt <= p.enddt
OUTER APPLY (
SELECT MAX (b.business_unit) AS business_unit
FROM ps_cts_job_dtl d
JOIN ps_cts_iqn_bu b ON b.business_unit = d.business_unit
WHERE d.emplid = d1.emplid
AND d.effdt = d1.effdt
) b
)
SELECT g.emplid
, GREATEST ( g.effdt
, g.startdt
) AS startdt
, LEAST ( e.enddt
, g.enddt
) AS enddt
, g.per_org
, g.hr_status
, 'Employee is active as CWR and BU is in IQN_BU setup table'
AS reason
FROM got_business_unit g
OUTER APPLY (
SELECT NVL ( MIN (gs.effdt) - 1
, DATE '9999-12-31'
) AS enddt
FROM got_business_unit gs
WHERE gs.emplid = g.emplid
AND gs.effdt > g.effdt
AND gs.hr_status = 'I'
) e
WHERE hr_status = 'A'
AND e.enddt > g.startdt
ORDER BY emplid
, startdt
;
Out Put from the query is
Need only one row for employee 733930 from 01-Jun-2019 to 03-Jun-2019.
need only one row for employee 733931 from 26-Jun-2019 to 30-Jun-2019.
I want out put like below based on below tables and data.
Required output:
Note : Reason column for understanding, no need to display reason column
While fetching below out put Please map EMPLID,EMPL_RCD,EFFDT,EFFSEQ Key fields in both JOB_DTL and JOB_DTL1 ( Map Key fields is very important )
- Employee 733930 is active CWR in between '01-Jun-2019' to '03-Jun-2019' and employee have only one row with HR_STATUS ='A' ( employee have more than one row with HR_STATUS = 'A' ) and Business_unit value present in PS_CTS_IQN_BU table.
- Employee 733930 is active CWR in between '15-Jun-2019' to '18-Jun-2019' and employee have only one row with HR_STATUS ='A' and Business_unit value present in PS_CTS_IQN_BU table.
- Employee 733930 is active as CWR in between '19-JUN-2019' to '25-JUN-2019' in different BU which not in IQN_BU setup table, so i want to exclude that information.
- Employee 733930 is active CWR from '26-Jun-2019' with HR_STATUS ='A' and Business_unit value present in PS_CTS_IQN_BU table.
- Employee 733931 is active CWR from '06-Jun-2019' to '09-Jun-2019' and, employee have only one row with HR_STATUS ='A' and Business_unit value present in PS_CTS_IQN_BU table.
- Employee 733931 is active CWR from '26-Jun-2019' to '30-Jun-2019' and he is having more than one row with HR_STATUS = 'A' and Business_unit value present in PS_CTS_IQN_BU table.
EMPLID | FROM_DATE | To_DATE | PER_ORG | HR_STATUS | Reason |
733930 | 01-Jun-2019 | 03-Jun-2019 | CWR | A | Employee is active as CWR and BU is in IQN_BU setup table |
733930 | 15-Jun-2019 | 18-Jun-2019 | CWR | A | Employee is active as CWR and BU is in IQN_BU setup table |
733930 | 26-Jun-2019 | 30-Jun-2019 | CWR | A | Employee is active as CWR and BU is in IQN_BU setup table |
733931 | 06-Jun-2019 | 09-Jun-2019 | CWR | A | Employee is active as CWR and BU is in IQN_BU setup table |
733931 | 26-Jun-19 | 30-JUN-2019 | CWR | A | Employee is active as CWR and BU is in IQN_BU setup table |
Below is the requirement details.
- I want to fetch the contract employee information with HR_Status = 'A'. ( per_org = 'CWR' in PS_CTS_JOB_DTL1 table ).
- And active contract employee Business_Unit value of 'PS_CTS_JOB_DTL' table should be present in PS_CTS_IQN_BU table.
- there is a chance to have an employee multiple consecutive rows with hr_status='A'
DBA Version : Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
Below is my "PS_CTS_JOB_DTL" table structure and data. in this table (EMPLID,EMPL_RCD,EFFDT,EFFSEQ) are key fields.
EMPL_RCD : when ever employee converted from contract to full time and from full time to contract this value will increase. (0,1,2,...)
EFFDT : this filed use to track when change happens.
EFFSEQ : this field will increase from 0 to 1,2 .. when there is more than one transaction in same date.( with same effdt )
ACTION : Will determine which action they taken on employee ( please don't consider action field to achieve output as below. because action codes may different in each time)
Note : Data Volume of this table is more than 50 million rows
PS_CTS_JOB_DTL Table | |||||
EMPLID | BUSINESS_UNIT | EMPL_RCD | EFFDT | EFFSEQ | ACTION |
733930 | US410 | 0 | 27-May-2019 | 0 | ADD |
733930 | US410 | 0 | 02-Jun-2019 | 0 | DTA |
733930 | US410 | 0 | 04-Jun-2019 | 0 | TER |
733930 | US410 | 1 | 06-Jun-2019 | 0 | HIR |
733930 | US410 | 1 | 15-Jun-2019 | 0 | TER |
733930 | US410 | 2 | 15-Jun-2019 | 1 | ADD |
733930 | US608 | 2 | 19-Jun-2019 | 0 | ASC |
733930 | CN512 | 2 | 26-Jun-2019 | 0 | ASG |
733931 | US410 | 0 | 26-Apr-2019 | 0 | HIR |
733931 | US410 | 0 | 05-Jun-2019 | 0 | TER |
733931 | IN208 | 1 | 06-Jun-2019 | 0 | ADD |
733931 | IN208 | 1 | 10-Jun-2019 | 0 | TER |
733931 | IN208 | 2 | 12-Jun-2019 | 0 | HIR |
733931 | IN408 | 2 | 18-Jun-2019 | 0 | ASC |
733931 | IN408 | 2 | 19-Jun-2019 | 0 | TER |
733931 | IN208 | 3 | 26-Jun-2019 | 0 | ADD |
733931 | IN208 | 3 | 28-Jun-2019 | 0 | DTA |
PS_CTS_JOB_DTL1 Table :
Note : Data Volume of this table is more than 50 million rows
Below is my "PS_CTS_JOB_DTL1" table structure and data. in this table (EMPLID,EMPL_RCD,EFFDT,EFFSEQ) are key fields.
EMPL_RCD : when ever employee converted from contract to full time and from full time to contract this value will increase. (0,1,2,...)
EFFDT : this filed use to track when change happens.
EFFSEQ : this field will increase from 0 to 1,2 .. when there is more than one transaction in same date.( with same effdt )
HR_STATUS : To identify employee status ( A = Active, I = Inactive ).
PER_ORG : to identify employee type ( CWR = Contract, EMP = Employee )
Note : employee may contains more then one row with HR_STATUS = 'A' before he is going to inactive ( HR_STSTUS = 'I' )
EMPL_ID | EMPL_RCD | EFFDT | EFFSEQ | HR_STATUS | PER_ORG |
733930 | 0 | 27-May-2019 | 0 | A | CWR |
733930 | 0 | 02-Jun-2019 | 0 | A | CWR |
733930 | 0 | 04-Jun-2019 | 0 | I | CWR |
733930 | 1 | 06-Jun-2019 | 0 | A | EMP |
733930 | 1 | 15-Jun-2019 | 0 | I | EMP |
733930 | 2 | 15-Jun-2019 | 1 | A | CWR |
733930 | 2 | 19-Jun-2019 | 0 | A | CWR |
733930 | 2 | 26-Jun-2019 | 0 | A | CWR |
733931 | 0 | 26-Apr-2019 | 0 | A | EMP |
733931 | 0 | 05-Jun-2019 | 0 | I | EMP |
733931 | 1 | 06-Jun-2019 | 0 | A | CWR |
733931 | 1 | 10-Jun-2019 | 0 | I | CWR |
733931 | 2 | 12-Jun-2019 | 0 | <td clas
Best Answer
-
Hi,
Here's one way to do it:
WITH parameters AS( SELECT TO_DATE ('01-JUN-2019', 'DD-MON-YYYY') AS pstartdt -- Always use 4 digits for years , TO_DATE ('30-JUN-2019', 'DD-MON-YYYY') AS penddt , 'CWR' AS per_org FROM dual), got_business_unit AS( SELECT p.pstartdt, p.penddt , d1.emplid, d1.per_org, d1.effdt , CASE WHEN b.business_unit IS NULL THEN 'I' ELSE d1.hr_status END AS hr_status , b.business_unit FROM parameters p JOIN ps_cts_job_dtl1 d1 ON d1.per_org = p.per_org AND d1.effdt <= p.penddt OUTER APPLY ( SELECT MAX (b.business_unit) AS business_unit FROM ps_cts_job_dtl d JOIN ps_cts_iqn_bu b ON b.business_unit = d.business_unit WHERE d.emplid = d1.emplid AND d.effdt = d1.effdt ) b WHERE d1.hr_status IN ('A', 'I') -- if necessary)SELECT emplid, GREATEST (sdt, pstartdt) AS startdt, LEAST ( NVL (edt - 1, penddt) , penddt ) AS enddt, per_org, 'A' AS hr_status, 'Employee is active as CWR and BU is in IQN_BU setup table' AS reasonFROM got_business_unitMATCH_RECOGNIZE ( PARTITION BY emplid, pstartdt, penddt, per_org ORDER BY effdt MEASURES MIN (effdt) AS sdt , i.effdt AS edt ONE ROW PER MATCH PATTERN (a+ i?) DEFINE a AS hr_status = 'A' , i AS hr_status = 'I' )WHERE NVL (edt - 1, penddt) > pstartdtORDER BY emplid, sdt;
The sub-queries are almost the same as the corresponding sub-queries you posted.
In parameters, I changed the column names to pstartdt and penddt, to avoid confusing them with startdt and enddt elsewhere.
In got_business_unit, I added a condition "WHERE d1.hr_status IN ('A', 'I')". If hr_status is always 'A' or 'I', then you don't need it.
Answers
-
Hi,
This looks almost identical to reply #12 in your earlier thread: Fetching Contract Employee information by Join the JOB_DTL,JOB_DTL1,IQN_BU Tables.
Please don't post the same question in multiple threads. It's confusing for people trying to answer questions, and it's confusing for you, too, since you have to look in multiple places for answers. Mark one of these threads as "Answered" before we go any farther.
The query you posted meets the requirements you posted.
- It fetches contract employee information with HR_Status = 'A'. ( per_org = 'CWR' in PS_CTS_JOB_DTL1 table ).
- It only returns rows where active contract employee Business_Unit value of 'PS_CTS_JOB_DTL' table is present in PS_CTS_IQN_BU table.
- It handles the case were an employee has multiple consecutive rows with hr_status='A'. (It may not handle them the way you want, but you haven't said what that way is.)
You apparently have other requirements you haven't posted yet.
-
Hi @Frank Kulash,
EMPL_ID EMPL_RCD EFFDT EFFSEQ HR_STATUS PER_ORG 733930 0 27-May-2019 0 A CWR 733930 0 02-Jun-2019 0 A CWR 733930 0 04-Jun-2019 0 I CWR Employee 733930 is active as CWR from 27-May-2019 to 03-Jun-2019. and he is having one extra row with HR_STATUS = 'A' and effdt 02-Jun-2019. (there is a chances employee may have more than one row with HR_STATUS = 'A' between active and inactive.). And for each effdt row employee Business_unit also available in IQN BU setup table.
When i run the query with start date 01-JUN-2019 and end date 30-JUN-2019 Query is fetching two rows. 01-JUN-2019 to 03-JUN-2019 one row and 02-JUN-2019 to 03-JUN-2019 one row.
instead of fetching two rows i want to fetch only one row from 01-JUN-2019 to 03-JUN-2019. Because he is active CWR from 01-JUN-2019 to 03-JUN-2019 .
Note :
- when ever there is more than one row with HR_STATUS = 'A' between start and end dates, we need to check for each row business unit is available or not in the IQN BU table. If business unit is available then we need to skip that row.
in this case 27-MAY-2019 effdt row business unit valu is present in IQN BU table so we are fetching greatest value 01-JUN-2019 as start date.
For 02-JUN-2019 effdt row business unit also available in IQN BU table so we need to skip this row. ( but query is fetching this row )
2. If Business unit value is not available in IQN BU table then we need to treat row as HR_STATUS is inactive. ( This one is working fine in the Query)
similarly for Employee 733931 also it is fetching two rows for below data.
EMPL_ID EMPL_RCD EFFDT EFFSEQ HR_STATUS PER_ORG 733931 3 26-Jun-2019 0 A CWR 733931 3 28-Jun-2019 0 A DTA Query is fetching 26-JUN-2019 to 30-JUN-2019 one row and 28-JUN-2019 to 30-JUN-2019 second row. For 28-JUN-2019 effdt row business unit value is available in IQN BU table so i want to fetch only one from 26-JUN-2019 to 30-JUN-2019.
-
Hi @Frank Kulash , Could you please help me out on this.
-
Hi,
Sorry, I still don't understand why you want the results you posted. The specific examples are good, but I need a general rule, such as "When there are two (or more) consecutive rows (in order by effdt) for the same emplid that all have hr_status='A', then only the first one counts. The second (and later) consecutive 'A' rows can be ignored."
-
Hi @Frank Kulash, Yes correct When there are two (or more) consecutive rows (in order by effdt) for the same emplid that all have hr_status='A', and business unit also should be present in IQN BU table for all consecutive rows then only the first one counts. The second (and later) consecutive 'A' rows can be ignored." { If business unit is not available in IQN BU table for consecutive rows then we need to treat that row as inactive. Currently we are checking this thing we are validating in query }
-
Hi,
Here's one way to do it:
WITH parameters AS( SELECT TO_DATE ('01-JUN-2019', 'DD-MON-YYYY') AS pstartdt -- Always use 4 digits for years , TO_DATE ('30-JUN-2019', 'DD-MON-YYYY') AS penddt , 'CWR' AS per_org FROM dual), got_business_unit AS( SELECT p.pstartdt, p.penddt , d1.emplid, d1.per_org, d1.effdt , CASE WHEN b.business_unit IS NULL THEN 'I' ELSE d1.hr_status END AS hr_status , b.business_unit FROM parameters p JOIN ps_cts_job_dtl1 d1 ON d1.per_org = p.per_org AND d1.effdt <= p.penddt OUTER APPLY ( SELECT MAX (b.business_unit) AS business_unit FROM ps_cts_job_dtl d JOIN ps_cts_iqn_bu b ON b.business_unit = d.business_unit WHERE d.emplid = d1.emplid AND d.effdt = d1.effdt ) b WHERE d1.hr_status IN ('A', 'I') -- if necessary)SELECT emplid, GREATEST (sdt, pstartdt) AS startdt, LEAST ( NVL (edt - 1, penddt) , penddt ) AS enddt, per_org, 'A' AS hr_status, 'Employee is active as CWR and BU is in IQN_BU setup table' AS reasonFROM got_business_unitMATCH_RECOGNIZE ( PARTITION BY emplid, pstartdt, penddt, per_org ORDER BY effdt MEASURES MIN (effdt) AS sdt , i.effdt AS edt ONE ROW PER MATCH PATTERN (a+ i?) DEFINE a AS hr_status = 'A' , i AS hr_status = 'I' )WHERE NVL (edt - 1, penddt) > pstartdtORDER BY emplid, sdt;
The sub-queries are almost the same as the corresponding sub-queries you posted.
In parameters, I changed the column names to pstartdt and penddt, to avoid confusing them with startdt and enddt elsewhere.
In got_business_unit, I added a condition "WHERE d1.hr_status IN ('A', 'I')". If hr_status is always 'A' or 'I', then you don't need it.
-
Hi @Frank Kulash, Thanks for your support, when i execute the above SQL i am getting below error. Please help me on this.
-
HI,
Vemula Muni wrote:Hi Frank Kulash, Thanks for your support, when i execute the above SQL i am getting below error. Please help me on this.
That doesn't look like an Oracle error message.
IN and OUT parameters occur in PL/SQL procedures. Nothing in this thread before this has even mentioned PL/SQL. Are you doing something other than what is posted here?
I don't get any error when I run the query above in SQL*Plus (version 12.2.0.1.0). Do you?
What front end are you using when you get the error you posted? If it's detecting an error on line 1, then maybe that front end doesn't recognize WITH clauses (which have been part of Oracle since version 9.1, released in 2001).
The query you posted in your original message also started with WITH. Did it raise an error?
-
Hi @Frank Kulash, I am using the below version SQL developer . till i executed all your quires in this and it is accepted WITH clauses. And i am not changing the query ( Executing as it is).
-
Hi,
Vemula Muni wrote:Hi Frank Kulash, I am using the below version SQL developer . till i executed all your quires in this and it is accepted WITH clauses. And i am not changing the query ( Executing as it is).
So you're using SQL Developer version 1.5.5? That sounds kind of old.
The query in reply #6 runs (and returns the results you requested) when I try it in SQL Developer 4.1.4.21. It looks like you have a separate problem that involves SQL Developer, not SQL or PL/SQL. Start a new thread in the SQL Developer forum. When posting there, simplify the query as much as possible, so that it still causes the same error. That will also help isolate exactly what couases the problem, which will help if you can't solve the SQL Developer issue and need to find a different way to run the query