#sql #oracle11g #oracle10g
#sql #оракул11g #оракул10g
Вопрос:
Я надеюсь, что кто — нибудь сможет мне помочь. Случай:
У меня есть таблица COMPANY_ACCESS
с этими столбцами:
ID NUMBER, COMPANY_ID NUMBER, AREA_ID NUMBER, TEAM_ID NUMBER, CAN_ACCESS BOOLEAN
И у меня есть мой запрос (не работает):
SELECT * FROM COMPANY_ACCESS ca WHERE ca.CAN_ACCESS = true AND ((ca.COMPANY_ID = ?1 AND ca.AREA_ID = ?2 AND ca.TEAM_ID = ?3) OR (ca.COMPANY_ID = ?1 AND ca.AREA_ID = ?2 AND ca.TEAM_ID IS NULL) OR (ca.COMPANY_ID = ?1 AND ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL))
Каковы мои намерения здесь. Выполните поиск от более конкретного доступа (со всеми параметрами) к менее конкретному. Если у меня есть один регистр в первом условии :
(COMPANY_ID = ?1 AND AREA_ID = ?2 AND TEAM_ID = ?3)
Мне не нужно проверять другие и возвращать только этот реестр. Если у меня его нет. Я проверю без идентификатора TEAM_ID (доступ без идентификатора TEAM_ID действителен для всех команд внутри AREA_ID). Но если я выполню этот запрос, я получу регистры в первом условии, во втором условии и в третьем условии. И это не входит в мои намерения. Если бы я нашел его в первом условии (более конкретном) Мне не нужно, чтобы остальные возвращали только этот регистр. Я проверю только второе и третье условие, если раньше ничего не найду в этом условии.
Пожалуйста, кто-нибудь может мне помочь?
Комментарии:
1. Чтобы уточнить, необязательно ли передаются переменные привязки? Это означает, что если вы передадите только идентификатор компании, он просто вернет доступ к компании? Или будут переданы все параметры, и вы хотите вернуть все, что соответствует какому-либо условию?
2. Все параметры должны быть переданы. И со всеми этими параметрами я буду проверять форму от более конкретной до менее конкретной @Nick
Ответ №1:
В Oracle 12 вы можете отфильтровать строки с помощью переменных привязки, а затем упорядочить результирующий набор так, чтобы сначала были выбраны нужные строки, а затем отфильтровать другие строки с помощью FETCH FIRST ROW WITH TIES
:
SELECT * FROM COMPANY_ACCESS ca WHERE ca.CAN_ACCESS = true AND ca.COMPANY_ID = ? AND ( (ca.AREA_ID = ? AND (ca.TEAM_ID = ? OR ca.TEAM_ID IS NULL)) OR (ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL)) ORDER BY ca.AREA_ID NULLS LAST, ca.TEAM_ID NULLS LAST FETCH FIRST ROW WITH TIES;
В более ранних версиях для фильтрации можно использовать аналитические функции:
SELECT * FROM ( SELECT ca.*, RANK() OVER ( ORDER BY ca.AREA_ID NULLS LAST, ca.TEAM_ID NULLS LAST ) AS rnk FROM COMPANY_ACCESS ca WHERE ca.CAN_ACCESS = true AND ca.COMPANY_ID = ? AND ( (ca.AREA_ID = ? AND (ca.TEAM_ID = ? OR ca.TEAM_ID IS NULL)) OR (ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL)) ) WHERE rnk = 1;
Если когда-либо будет только одна совпадающая строка, вы можете использовать ROWNUM
вместо этого фильтрацию:
SELECT * FROM ( SELECT * FROM COMPANY_ACCESS ca WHERE ca.CAN_ACCESS = true AND ca.COMPANY_ID = ? AND ( (ca.AREA_ID = ? AND (ca.TEAM_ID = ? OR ca.TEAM_ID IS NULL)) OR (ca.AREA_ID IS NULL AND ca.TEAM_ID IS NULL)) ORDER BY ca.AREA_ID NULLS LAST, ca.TEAM_ID NULLS LAST ) WHERE ROWNUM = 1;
Комментарии:
1. Это работает довольно хорошо. Я не знал, что эта команда ОБНУЛЯЕТСЯ ПОСЛЕДНЕЙ. Есть ли способ упорядочить результаты с регистрами с нулем в конце?
2. @LucasAlves Да.