Оптимизация SQL GROUP BY та же таблица, тот же столбец - PullRequest
0 голосов
/ 02 мая 2019

У меня есть запрос GROUP BY, где мне нужно выбрать несколько записей из TABLE_1 и объединить их.

SELECTs похожи, но мне нужно агрегировать LON и BHAM по отдельности, поскольку они представляют собой две разные концепции, но находятся в одной таблице.

Мой вопрос заключается в том, могу ли я по-другому написать ниже в 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 ]

2 голосов
/ 02 мая 2019

Вам нужно добавить столбец города в группу и обновить предложение 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;

Тем не менее, я удивлен, что вам нужны оба ряда, так как вы не можете определить, какой город принадлежит. Я подозреваю, что вам нужно включить столбцы города (и, возможно, псевдоним) в окончательные результаты.

2 голосов
/ 02 мая 2019

Удалить union all и все после, удалить внешние select, написать where предложение, как здесь:

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