Search code examples
sqloracle-databaserefactoringsubqueryanalytic-functions

Oracle - Refactor subquery with max()


I have the query below. SOFTWARE_DEVELOPMENT_CYCLE has multiple rows, but I'm interested in the latest.

I would like to rewrite the query so that I don't use a subquery. I have attempted it with DENSE_RANK LAST ORDERY BY, but to no avail.

Could somebody advise? Thank you.

SELECT SOF.VENDOR, 
       SOF.NAME, 
       LAN.LANGUAGE, 
       SOF.VERSION, 
       SDC.STATUS, 
       SDC.SOF_DC_ID
  FROM SOFTWARE SOF
  JOIN SOFTWARE_LANGUAGES SL 
    ON (SL.SOF_SOF_ID = SOF.SOF_ID)
  JOIN LANGUAGES LAN 
    ON (SL.LAN_LAN_ID = LAN.LAN_ID)
  JOIN SOFTWARE_DEVELOPMENT_CYCLE SDC 
    ON (SDC.SOF_LAN_SOF_LAN_ID = SL.SOF_LAN_ID)
 WHERE SDC.SOF_DC_ID IN (SELECT MAX(SDC2.SOF_DC_ID)
                           FROM SOFTWARE_DEVELOPMENT_CYCLE SDC2
                          WHERE SDC2.SOF_LAN_SOF_LAN_ID = SL.SOF_LAN_ID)
 ORDER BY SOF.VENDOR, 
          SOF.NAME, 
          LAN.LANGUAGE, 
          SOF.VERSION;

Solution

  • You could do something like this to avoid having to hit the SOFTWARE_DEVELOPMENT_CYCLE table a second time

    SELECT vendor,
           name,
           language,
           version,
           status,
           sof_dc_id
      FROM (SELECT SOF.VENDOR, 
                   SOF.NAME, 
                   LAN.LANGUAGE, 
                   SOF.VERSION, 
                   SDC.STATUS, 
                   SDC.SOF_DC_ID,
                   RANK() OVER (PARTITION BY sl.sdf_lan_id 
                                    ORDER BY sdc.sdf_dc_id DESC) rnk
              FROM SOFTWARE SOF
              JOIN SOFTWARE_LANGUAGES SL 
                ON (SL.SOF_SOF_ID = SOF.SOF_ID)
              JOIN LANGUAGES LAN 
                ON (SL.LAN_LAN_ID = LAN.LAN_ID)
              JOIN SOFTWARE_DEVELOPMENT_CYCLE SDC 
                ON (SDC.SOF_LAN_SOF_LAN_ID = SL.SOF_LAN_ID))
     WHERE rnk = 1
     ORDER BY VENDOR, 
              NAME, 
              LANGUAGE, 
              VERSION;
    

    The RANK analytic function is partitioning the result set by sl.sdf_lan_id. Then for each distinct sl.sdf_lan_id, it is assigning a numeric rank to the row based on the descending order of sdc.sdf_dc_id. That means that the row with the largest sdc.sdf_dc_id for a particular sl.sdf_lan_id will have a RANK of 1. The outer WHERE rnk=1 predicate then selects only the rows that have that maximum value. That should accomplish the same thing that your MAX subquery is accomplishing.