SQL优化GROUP BY同一表,同一列

时间:2019-05-02 10:11:41

标签: sql oracle query-optimization

我有这个GROUP BY查询,我需要从TABLE_1中选择一些记录并进行汇总。

SELECTs很相似,但是我需要分别汇总LONBHAM,因为它们是两个不同的概念,但都位于同一表中。

我的问题是我可以在oracle中以不同的方式编写以下内容以优化查询性能吗?

SELECT  *
FROM (
        (    SELECT  /*+ full(t1) */ 
                t3.custId AS ID,       
                t2.secID AS SEC_ID, 
                t1.org_date AS SETT_DATE,
                SUM(t1.amount) AS TOTAL
            FROM test.TABLE_1 t1 
            INNER JOIN test.TABLE_2 t2 on t2.a_code = t1.a_code  and t2.c_code = t1.c_code and t2.expiry_date > trunc(sysdate)
            INNER JOIN test.TABLE_3 t3 on t3.account_id = t1.account_id 
            WHERE t1.city = 'LON'         
                AND t1.amount < 50000 and t1.amount > -50000
            GROUP BY t3.custId,  t2.secID, t1.org_date

        )

          UNION ALL

        (    SELECT  /*+ full(t1) */ 
                t3.custId AS ID,      
                t2.secID AS SEC_ID,
                t1.org_date AS SETT_DATE,
                SUM(t1.amount) AS TOTAL
            FROM test.TABLE_1 t1 
            INNER JOIN test.TABLE_2 t2 on t2.a_code = t1.a_code  and t2.c_code = t1.c_code and t2.expiry_date > trunc(sysdate)
            INNER JOIN test.TABLE_3 t3 on t3.account_id = t1.account_id 
            WHERE t1.city = 'BHAM'
                AND t3.alias = 'ABC' 
                AND t1.amount < 50000 and t1.amount > -50000
            GROUP BY t3.custId,  t2.secID, t1.org_date
        )   
    )
 ORDER BY ID,  SEC_ID, 
          CASE WHEN SETT_DATE < TRUNC(sysdate) THEN trunc(sysdate) ELSE TRUNC(SETT_DATE) end       

2 个答案:

答案 0 :(得分:2)

删除union all及其后的所有内容,删除外部select,像下面这样写where子句:

where -50000 < t1.amount and t1.amount < 50000 
  and (t1.city = 'LON' or (t1.city = 'BHAM' and t3.alias = 'ABC'))

答案 1 :(得分:2)

您需要将city列添加到group by中,并更新where子句以获取两组行,例如:

SELECT custid,
       sec_id,
       sett_date,
       total
FROM   (SELECT t3.custid AS id,
               t2.secid AS sec_id,
               CASE
                 WHEN t1.org_date < trunc(SYSDATE) THEN
                  trunc(SYSDATE)
                 ELSE
                  trunc(t1.org_date)
               END AS sett_date,
               t1.city,
               SUM(t1.amount) AS total
        FROM   test.table_1 t1
        INNER  JOIN test.table_2 t2
        ON     t2.a_code = t1.a_code
        AND    t2.c_code = t1.c_code
        AND    t2.expiry_date > trunc(SYSDATE)
        INNER  JOIN test.table_3 t3
        ON     t3.account_id = t1.account_id
        WHERE  (t1.city = 'LON' OR (t1.city = 'BHAM' AND t3.alias = 'ABC'))
        AND    t1.amount < 50000
        AND    t1.amount > -50000
        GROUP  BY t3.custid,
                  t2.secid,
                  CASE
                    WHEN t1.org_date < trunc(SYSDATE) THEN
                     trunc(SYSDATE)
                    ELSE
                     trunc(t1.org_date)
                  END)
ORDER  BY id,
          sec_id,
          sett_date;

但是,令您惊讶的是您同时需要两行,因为您无法确定哪个城市属于哪个城市。我怀疑您需要在最终结果中包括城市(或别名)列。