Оптимизация запроса - PullRequest
       1

Оптимизация запроса

0 голосов
/ 10 января 2020

У меня есть таблица с двумя видами источников в столбце источника, один внешний и другой внутренний. Моё требование - найти одну и ту же запись между внешним и внутренним на основе COLUMNA и COLUMNB. Если внутренняя и внешняя записи совпадают для COLUMNA, мне нужно взять соответствующий идентификатор (значение столбца ID всегда будет уникальным) как из внутренней, так и из внешней. У меня в таблице миллионы записей. И в каждом источнике будут дубликаты записей , Я дал запрос, который написан (я использую UNION ALL для повышения производительности, даже если в окончательном выводе появится дубликат ID), но он занимает 2 часа. Так что я все равно могу переписать этот запрос, я использую DB2 здесь.

Например, если ниже моя входная запись.

enter image description here

ID  COLUMNA COLUMNB  SOURCE

1   DELL    Finland  INTERNAL

2   CTS     USA      INTERNAL

3   CTS     AUST     INTERNAL

4   TCS     FIN      INTERNAL

5   CTS     SING     INTERNAL

6   IBM     NEWZ     EXTERNAL

7   CTS     AUST     EXTERNAL

8   TCS     Finland  EXTERNAL

9   TCS     Finland  EXTERNAL

Ожидаемый результат

enter image description here

Запрос, который уже написан, приведен ниже.

select  ID from TABLE where COLUMNA in(
(select SRC.COLUMNA from TABLE SRC,TABLE REF  
where SRC.SOURCE<>'EXTERNAL' and REF.SOURCE='EXTERNAL' and SRC.COLUMNA=REF.COLUMNA))
UNION ALL
select  ID from TABLE where COLUMNB in(
(select SRC.COLUMNB from TABLE SRC,TABLE REF  
where SRC.SOURCE<>'EXTERNAL' and REF.SOURCE='EXTERNAL' and 
SRC.COLUMNB=REF.COLUMNB))

Ответы [ 3 ]

1 голос
/ 10 января 2020

Попробуйте это

SELECT ID FROM (
    SELECT ID
    , SUM(SOURCE = 'INTERNAL') OVER(PARTITION BY CA) AS INT_A
    , SUM(SOURCE = 'EXTERNAL') OVER(PARTITION BY CA) AS EXT_A
    , SUM(SOURCE = 'INTERNAL') OVER(PARTITION BY CB) AS INT_B
    , SUM(SOURCE = 'EXTERNAL') OVER(PARTITION BY CB) AS EXT_B
    FROM 
        T
) WHERE (INT_A > 0 AND EXT_A) > 0 OR (INT_B > 0 AND EXT_B) > 0
ORDER BY ID

, которое возвращает

ID
--
 1
 2
 3
 4
 5
 7
 8
 9
1 голос
/ 10 января 2020

Вы, похоже, хотите id s, когда любой столбец повторяется в двух сторонах.

Для этого вы можете использовать оконные функции:

select distinct t.id
from (select t.*,
             min(source) over (partition by column_a) as min_a,
             max(source) over (partition by column_a) as max_a,
             min(source) over (partition by column_b) as min_b,
             max(source) over (partition by column_b) as max_b
      from t
     ) t
where min_a <> max_a or min_b <> max_b;

Это предполагает только два источники у вас есть в вопросе. Если есть другие, добавьте предложение where в подзапрос, чтобы отфильтровать только эти два.

0 голосов
/ 10 января 2020

Попробуйте:

SELECT ID
--, COLUMNA_SOURCE_DISTINCT, COLUMNB_SOURCE_DISTINCT
FROM
(
SELECT 
  T.*
-- COUNT DISTINCT OLAP specification is not supported; we emulate it below
-- COUNT(DISTINCT SOURCE) OVER (PARTITION BY COLUMNA) COLUMNA_SOURCE_DISTINCT 
, COUNT(NULLIF(SOURCE, LAG(SOURCE) OVER (PARTITION BY COLUMNA ORDER BY SOURCE))) 
  OVER (PARTITION BY COLUMNA) COLUMNA_SOURCE_DISTINCT 
, COUNT(NULLIF(SOURCE, LAG(SOURCE) OVER (PARTITION BY COLUMNB ORDER BY SOURCE))) 
  OVER (PARTITION BY COLUMNB) COLUMNB_SOURCE_DISTINCT 
FROM TABLE T
)
WHERE COLUMNA_SOURCE_DISTINCT + COLUMNB_SOURCE_DISTINCT <> 2;

Альтернативное решение без функций OLAP

SELECT ID
FROM TABLE A
WHERE EXISTS 
(
SELECT 1
FROM TABLE B
WHERE B.COLUMNA=A.COLUMNA 
AND 
   CASE A.SOURCE WHEN 'EXTERNAL' THEN 'EXTERNAL' ELSE 'INTERNAL' END
<> CASE B.SOURCE WHEN 'EXTERNAL' THEN 'EXTERNAL' ELSE 'INTERNAL' END
)

  UNION

SELECT ID
FROM TABLE A
WHERE EXISTS 
(
SELECT 1
FROM TABLE B
WHERE B.COLUMNB=A.COLUMNB 
AND 
   CASE A.SOURCE WHEN 'EXTERNAL' THEN 'EXTERNAL' ELSE 'INTERNAL' END
<> CASE B.SOURCE WHEN 'EXTERNAL' THEN 'EXTERNAL' ELSE 'INTERNAL' END
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...