Convert Coldfusion script in Oracle view with CASE and iteration

混江龙づ霸主 提交于 2019-12-11 04:49:23

问题


I created a coldfusion script allowing to get an object "unit" from an array.

My DB has a view about units. For a same unit key "ORG_ID", it can exist several rows (with a difference on a field "origin"). the field "origin" can be "current", "history" or "different".

+---------+---------+------------+------------+----------|
|  ORG_ID |  TITLE  | VALID_FROM | VALID_TO   |  ORIGIN  |
+---------+---------+------------+------------+----------|
| 1234    | A.1     | 01/03/2016 | 31/12/9999 | other    |
| 1234    | A.1     | 01/03/2016 | 31/12/3333 | current  |  
| 1234    | A.1     | 01/03/2016 | 31/12/9999 | history  |  
| 5420    | A.2     | 01/01/2014 | 31/12/3333 | other    |
| 9876    | A.3     | 01/03/2016 | 31/12/3333 | current  |  
| 9876    | B.3     | 01/03/2016 | 31/12/9999 | history  |  
| 5527    | A.1     | 01/03/2016 | 31/12/2199 | current  |
| 5527    | D.2     | 01/01/2010 | 31/12/2015 | history  |  
| 5527    | A.1     | 01/01/2016 | 31/12/2199 | history  |  
| 6699    | E.5     | 01/01/2016 | 31/12/2017 | history  |
| 6699    | A.4     | 01/01/2017 | 31/12/2018 | history  |    
+---------+---------+------------+------------+----------|

In this case for instance here the result that I would like to get:

+---------+---------+------------+------------+----------|--------------|
|  ORG_ID |  TITLE  | VALID_FROM | VALID_TO   |  ORIGIN  | CORRECT_VERS |
+---------+---------+------------+------------+----------|--------------|
| 1234    | A.1     | 01/03/2016 | 31/12/9999 | other    |      0       |    
| 1234    | A.1     | 01/03/2016 | 31/12/3333 | current  |      1       |  
| 1234    | A.1     | 01/03/2016 | 31/12/9999 | history  |      0       |  
| 5420    | A.2     | 01/01/2014 | 31/12/3333 | other    |      1       |
| 9876    | A.3     | 01/03/2016 | 31/12/3333 | current  |      1       |  
| 9876    | B.3     | 01/03/2016 | 31/12/9999 | history  |      0       |  
| 5527    | A.1     | 01/03/2016 | 31/12/2199 | current  |      1       |
| 5527    | D.2     | 01/01/2010 | 31/12/2015 | history  |      0       |  
| 5527    | A.1     | 01/01/2016 | 31/12/2199 | history  |      0       |  
| 6699    | E.5     | 01/01/2016 | 31/12/2017 | history  |      0       |
| 6699    | A.4     | 01/01/2017 | 31/12/2018 | history  |      0       |    
+---------+---------+------------+------------+----------+--------------|

My Coldfusion script: dataUnitArray contains the list of units in an array

<cftry>         

    <cfset hist = 0/>
    <cfset unit = structNew() />    

    <cfloop index="i" from="1" to="#ArrayLen(dataUnitArray)#">  

        <cfif #dataUnitArray[i].ORIGIN# EQ "current">
            <!---  Unit is current  --->
            <cfscript>
                unit.ORG_ID = #dataUnitArray[i].ORG_ID#;        
                unit.TITLE = #dataUnitArray[i].TITLE#;      
                unit.UNIT_VALID_FROM = #dateFormat(dataUnitArray[i].UNIT_VALID_FROM, 'DD/MM/YYYY')#;    
                unit.UNIT_VALID_TO = #dateFormat(dataUnitArray[i].UNIT_VALID_TO, 'DD/MM/YYYY')#;        
                unit.ORIGIN = #dataUnitArray[i].ORIGIN#;        

                return unit;
            </cfscript>     

        <cfelse>
            <cfif #dataUnitArray[i].ORIGIN# EQ "history">
                <!---  Unit is history  --->
                <cfscript>
                    unit.ORG_ID = #dataUnitArray[i].ORG_ID#;        
                    unit.TITLE = #dataUnitArray[i].TITLE#;      
                    unit.UNIT_VALID_FROM = #dateFormat(dataUnitArray[i].UNIT_VALID_FROM, 'DD/MM/YYYY')#;    
                    unit.UNIT_VALID_TO = #dateFormat(dataUnitArray[i].UNIT_VALID_TO, 'DD/MM/YYYY')#;        
                    unit.ORIGIN = #dataUnitArray[i].ORIGIN#;        
                </cfscript>

                <cfset hist++ >

            <cfelse>
            <!---  Unit is different (other) --->
                <cfif hist EQ 0>

                    <cfscript>
                        unit.ORG_ID = #dataUnitArray[i].ORG_ID#;        
                        unit.TITLE = #dataUnitArray[i].TITLE#;      
                        unit.UNIT_VALID_FROM = #dateFormat(dataUnitArray[i].UNIT_VALID_FROM, 'DD/MM/YYYY')#;    
                        unit.UNIT_VALID_TO = #dateFormat(dataUnitArray[i].UNIT_VALID_TO, 'DD/MM/YYYY')#;        
                        unit.ORIGIN = #dataUnitArray[i].ORIGIN#;        
                    </cfscript>
                </cfif>
            </cfif>

        </cfif>     

    </cfloop>

    <cfscript>
        return unit;
    </cfscript>

    <cfcatch type="any">                
        <cfscript>
            .....
        </cfscript>         
    </cfcatch>
</cftry>

My script is correctly working. But I have loading time problem when I used it on a lot of data. That's why I would like to do that directly in ORACLE, with CASE...WHEN as:

CASE
    when ORIGIN = 'current' THEN 1 
    WHEN ORIGIN = 'history' THEN
        CASE  hist = 0 THEN ....

        END
ELSE 
   0   
END  AS "IS_CORRECT_VERSION"   

I would like to add a new column "CORRECT_VERSION" ( value 0 or 1 when the version is correct) in a view in order to retrieve the correct unit version.

But I don't know how to do that, could you please help me with that?

Thanks in advance for your help.

Seb


回答1:


I do not know ColdFusion, but I think I understood the logic. Priority is current > history > different. It is not clear which row is correct when there are two current rows or only different rows, so I mark row with minimum valid_from in such case. If you don't care You can omit this parameter (remove unit_valid_from from row_number's order by clause):

select units.*, 
       case when 1 = 
           row_number() over (
               partition by org_id 
               order by case origin when 'current' then 1 when 'history' then 2 else 3 end, 
                        unit_valid_from ) then 1 else 0 end as is_correct_version
  from units

dbfiddle demo




回答2:


I assume that there are no two rows having the same origin for the same org_id and even if duplicates exist, there must be only one record has VALID_FROM < SYSDATE < VALID_TO.

Following is the solution based on sample data. Please change the logic if required.

SELECT
    UNITS.*,
    CASE
        WHEN DENSE_RANK() OVER(
            PARTITION BY ORG_ID
            ORDER BY
                CASE ORIGIN
                    WHEN 'current'   THEN 1
                    WHEN 'history'   THEN 2
                    ELSE 3
                END
        ) = 1
             AND TRUNC(SYSDATE) BETWEEN VALID_FROM AND VALID_TO THEN 1
        ELSE 0
    END AS IS_CORRECT_VERSION
FROM
    UNITS;

Cheers!!



来源:https://stackoverflow.com/questions/57460093/convert-coldfusion-script-in-oracle-view-with-case-and-iteration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!