#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