SQL-запрос, возвращающий дубликаты

#sql #oracle

#sql #Oracle

Вопрос:

Я пытаюсь запустить инструкцию SQL как материализованное представление, а затем объединить таблицу с гораздо большей таблицей. У меня возникают проблемы с нарушением ограничения дублирования для комбинации элементов / местоположений в таблице большего размера. Вот мой материализованный запрос представления:

 SELECT /*  materialize */ CAN.CNCL_CNT, CAN.ITEM, CAN.LOCATION,
      CAN.LAST_CNCL_DTE, OL.CANCEL_ID
FROM ORDLOC OL,
     (SELECT COUNT(CANCEL_DATE) AS CNCL_CNT, ITEM, LOCATION, 
             MAX(CANCEL_DATE) AS LAST_CNCL_DTE
      FROM ORDLOC
      WHERE CANCEL_DATE between  (to_date(20160123,'yyyymmdd') -60) and to_date(20160123,'yyyymmdd') 
        AND CANCEL_DATE IS NOT NULL
      GROUP BY ITEM, LOCATION) CAN  
WHERE CAN.ITEM = OL.ITEM 
AND CAN.LOCATION = OL.LOCATION
AND CAN.LAST_CNCL_DTE = OL.CANCEL_DATE
GROUP BY CAN.CNCL_CNT, CAN.ITEM, CAN.LOCATION, CAN.LAST_CNCL_DTE, OL.CANCEL_ID
  

Теперь, когда я запускаю только вложенный запрос, у меня на несколько сотен строк меньше, а все комбинации элементов / местоположений уникальны, однако при выполнении всего запроса будет возвращено еще несколько сотен строк с повторяющимися элементами / местоположениями.

Комментарии:

1. ЭЛЕМЕНТ и МЕСТОПОЛОЖЕНИЕ будут уникальными внутри подзапроса CAN, но как насчет таблицы / представления ORDOC? Кроме того, только потому, что вы используете подсказку materialize, это не делает его «материализованным представлением», что в Oracle совсем другое. Кроме того, подсказка materialize не документирована и поэтому не должна использоваться в производственном коде, если вы не готовы к ошибкам (которые я видел с помощью этой подсказки) и к неожиданным изменениям функциональности в разных версиях.

2. Спасибо за ваш комментарий. Использовал материализованную подсказку, чтобы материализовать временную таблицу. Не уверен, имеет ли он какую-либо эффективность, поскольку, по-моему, я пробовал это без подсказки с тем же эффектом.

3. Что касается таблицы ordoc, она не содержит уникального элемента / местоположения, но содержит уникальный «номер заказа», в идеале я хотел бы использовать только последнюю дату отмены.

4. Это просто семантика, но вы используете подсказку для материализации запроса во временную таблицу. Хотя есть причины, по которым необходимо сделать что-то подобное (обычно потому, что вы обращаетесь к одному и тому же набору данных несколько раз быстрее получить данные один раз сохранить их), в вашем случае это не обязательно может замедлять работу. Пожалуйста, обновите свой вопрос, включив в него пример ввода выходных данных, показывающий вашу проблему. (Кстати, материализованные представления , которые вы упомянули в своем первоначальном вопросе, — это нечто совершенно другое!).

5. Итак, вы находите последнюю дату отмены для каждого элемента / местоположения. Что вам нужно отобразить из таблицы ORDOC? Последний идентификатор CANCEL_ID? Или вам нужно отобразить все соответствующие CANCEL_IDs? Потому что, если это последнее, вы не можете ожидать, что результаты будут уникальными по отношению к элементу местоположению.

Ответ №1:

Решение состояло в том, чтобы использовать функцию max для CANCEL_ID для устранения дублирующегося элемента / МЕСТОПОЛОЖЕНИЯ. Поскольку существует редкий сценарий, когда у меня есть один и тот же ЭЛЕМЕНТ, МЕСТОПОЛОЖЕНИЕ, LAST_CNCL_DATE, но с двумя разными идентификаторами CANCEL_ID. Вот код, который я использовал.

 SELECT CAN.CNCL_CNT, CAN.ITEM, CAN.LOCATION,
 CAN.LAST_CNCL_DTE, MAX (OL.CANCEL_ID) AS CANCEL_ID
FROM ORDLOC OL,
     (SELECT COUNT(CANCEL_DATE) AS CNCL_CNT, ITEM, LOCATION, 
     MAX(CANCEL_DATE) AS LAST_CNCL_DTE
     FROM ORDLOC
     WHERE CANCEL_DATE BETWEEN (TO_DATE(20160123,'yyyymmdd') -60) AND TO_DATE(20160123,'yyyymmdd') 
     GROUP BY ITEM, LOCATION) CAN  
WHERE CAN.ITEM = OL.ITEM 
AND CAN.LOCATION = OL.LOCATION
AND CAN.LAST_CNCL_DTE = OL.CANCEL_DATE
GROUP BY CAN.CNCL_CNT, CAN.ITEM, CAN.LOCATION, CAN.LAST_CNCL_DTE