#sql #oracle #outer-join
#sql #Oracle #внешнее соединение
Вопрос:
Представьте, что у меня есть эти данные
люди -> изменения адреса -> причины изменения адреса
Мне нужны сведения обо всех людях, которых я также хочу знать, меняли ли они когда-либо адрес из-за пожара. Поэтому я не хочу знать, в чем причины, но если они изменили адрес по одной единственной причине.
У каждого пользователя может быть несколько причин для изменения адреса
итак, у меня есть
SELECT people.*
CASE WHEN add_change.reason_id is not NULL THEN
'Y'
ELSE
'N'
END as been_fire
from people
left outer join add_change ON person.id = add_change.person
left outer join add_change_reason ON add_change.reason_id = add_change_reason.id AND add_change_reason.text = 'FIRE'
но это возвращает несколько строк на человека, если у них много изменений адреса.
Я не могу просто использовать
left outer join add_change ON add_change.person = person.id AND add_change.reason_id = 5
поскольку это не фиксированные данные.
Комментарии:
1. Примеры данных и желаемые результаты помогут. Кажется, вам нужна причина изменения, а затем вы жалуетесь, что несколько причин приводят к нескольким строкам.
2. @GordonLinoff Образцов данных нет, поскольку это не реальные данные, просто простой пример. Поэтому я уверен, что вы можете представить, как эти таблицы спроектированы моим примером SQL и чрезмерно упрощенным ERD.
Ответ №1:
Использовать exists
:
SELECT p.*,
(CASE WHEN EXISTS (SELECT 1
FROM add_change ac JOIN
add_change_reason acr
ON ac.reason_id = acr.id
NVL(address_change.reason,'N')
WHERE p.id = ac.person AND
acr.text = 'FIRE'
)
THEN 'Y' ELSE 'N'
END) as has_fire_address_change
from people p;
Обратите внимание, что это изменяет флаг на 'Y'
и 'N'
, что, как следует из описания вашей проблемы, вы хотите.
Комментарии:
1. да, у меня действительно есть случай, возвращающий Y и N в реальном выборе. (который у меня сейчас есть в вопросе здесь)
2. Я использую это решение сейчас, но не принимаю его, поскольку это не очень хорошая форма в первые 24 часа
Ответ №2:
Вы могли бы выполнить левое соединение с производной таблицей, которая возвращает только идентификаторы пользователей, у которых есть причина изменения «ОГОНЬ»:
SELECT p.*
CASE WHEN cr.person IS NOT NULL THEN 'Y' ELSE 'N' END as been_fire
from people
left join (
select ac.person
from add_change ac
where exists (select *
from add_change_reason acr
where acr.id = ac.reason_id
AND acr.text = 'FIRE')
) cr on cr.person = p.id