首页 > 解决方案 > 有没有办法在一个简单的查询中做到这一点?

问题描述

我有一个 BIG(2300 万行)表 CONTRATOS,其中包含以下列:

SELECT
    CONTRATO,
    CODIGO_ORIGEN,
    ORIGEN
FROM CONTRATOS;

列 CODIGO_ORIGEN 有多个具有相同值的行:

CODIGO_ORIGEN     CONTRATO       ORIGEN 
-------------    ----------     --------
     1               345          CONT
     1               363          BKP
     1               645          BKP
     1               365          CONT 

我只需要每个 CODIGO_ORIGEN 获得一个 CONTRATO,但始终优先考虑“CONT”值。所以在这个示例中,它将是值为365的 CONTRATO

我试图做这样的事情:

SELECT  
   CODIGO_ORIGEN,
   CASE
    WHEN ORIGEN = 'CONT' THEN
        FIRST_VALUE (CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY CONTRATO DESC) 
    WHEN ORIGEN = 'BKP' THEN
        FIRST_VALUE (CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY CAMPO1 DESC, CAMPO2 DESC, CONTRATO DESC) 
   END AS CONTRATO
FROM CONTRATOS;

如果 ORIGEN 是“CONTR”,我应该按最高的 CONTRATO 排序并获得 CONTRATO 列。如果 ORIGEN 是“BKP”,我应该按不同的列排序并获得 CONTRATO 列。

最后,我应该能够拥有一个具有 CODIGO_ORIGEN -> CONTRATO (1:1) 的唯一行。

有没有一种简单的方法可以做到这一点(1个查询)?

提前致谢!

标签: sqloraclegroup-bysubquery

解决方案


我想我明白了:

      SELECT 
        C.contrato, C.codigo_origen,  NVL2(MX.CONTRATO, NULL, 'F') AS ESTADO, NVL2(MX.CONTRATO, NULL, '4008') AS ERROR
      FROM MGR_CUENTA_CTL C
      LEFT JOIN
      (
          select /*+ PARALLEL */
            DISTINCT CODIGO_ORIGEN,
            CASE
              WHEN ORIGEN_TABLA = 'CONT' THEN FIRST_VALUE(CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY CONTRATO DESC) 
              WHEN ORIGEN_TABLA = 'BKP' THEN FIRST_VALUE(CONTRATO) OVER (PARTITION BY CODIGO_ORIGEN ORDER BY CAMPO1 DESC, CAMPO2 DESC) 
            END AS CONTRATO
          FROM
          (  
             SELECT /*+ PARALLEL */ ctl.*
             FROM mgr_cuenta_ctl ctl
             LEFT JOIN 
             (
                   select /*+ PARALLEL */ CODIGO_ORIGEN
                   from mgr_cuenta_ctl
                   group by codigo_origen having count(distinct origen) > 1
             ) CTL2 ON ctl.CODIGO_ORIGEN = ctl2.CODIGO_ORIGEN
             WHERE (CTL2.CODIGO_ORIGEN IS NOT NULL AND CTL.ORIGEN <> 'BKP') OR (CTL2.CODIGO_ORIGEN IS NULL)
          )
      ) MX ON MX.CONTRATO = C.CONTRATO;

我认为它做了我试图解释的事情。

它对你有意义吗?

谢谢!


推荐阅读