#sql #inner-join #having-clause
#sql #внутреннее соединение #наличие-предложение
Вопрос:
Поездки
Customer_id src_id dest_id
c1 1 2
c1 2 1
c2 1 2
c2 2 3
Расположение
id name
1 Airports
2 Movies
3 Market
Есть ли другой хороший способ, кроме использования EXCEPT
(select cust_id from trips t
join location l
on src_id = id or dest_id=id
where name='Airport' )
except
(
select cust_id from trips t
left join location l
on src_id =l.id
left join location l2
on dest_id = l2.id
where l.name not in('Airport') and l2.name not in('Airport')
)
Итак, вопрос был 1) Клиенты, которые использовали поездки для аэропортов
Последующий вопрос: 2) Клиенты, которые использовали поездки только для аэропортов?
Для вопроса 1 выводом будут c1 и c2, но для вопроса 2 он должен быть только c1, потому что c2 использовал поездки для мест, отличных от аэропортов. Я использовал EXCEPT, но интервьюер упомянул, что я могу использовать некоторую функцию SQL для удаления записи c2, и это можно сделать без дополнительных объединений. Я хочу знать, есть ли какая-либо функция, о которой я здесь не знаю.
Более широкий вопрос: как создавать запросы, чтобы получать ТОЛЬКО записи с условиями?
Комментарии:
1. Можете ли вы немного более четко указать, какой именно конечный результат должен быть предоставлен в предоставленных вами образцах данных? Должны ли клиенты, использующие аэропорты в источнике или пункте назначения, быть включены в выходной набор? Как источник, так и пункт назначения? Ни то, ни другое?
2. Пометьте свой вопрос базой данных, которую вы используете. Почему в таблице trips нет a
trip_id
?3. @esqew Да, аэропорт может быть как в источнике, так и в пункте назначения.
4. @harshini Как вы определили, что
c1
это должно быть результатом для вопроса 2 ( только для аэропортов ), если у этого клиента также есть поездка в пункт назначения2 Movies
в первой строке? Каким должен быть результат, если также были эти маршруты:(c1, 1, 2), (c1, 2, 3), (c1, 3, 1)
? Как вы определите, была ли это одна поездка или просто много поездок, и в одну из них клиент случайно посетил место, откуда он или она начал в какой-то день?5. Это хороший вопрос! Сейчас меня смущает актуальный вопрос. Но, как я понимаю, я думаю, что c1 выводится там, потому что «Airport» включен в каждую поездку c1, тогда как у c2 есть поездки, в которых нет «Airport» ни в источнике, ни в dest, по крайней мере, в одной из поездок. В упомянутых вами маршрутах c1 не будет включен из-за записи (c1,2,3).
Ответ №1:
Вы можете попробовать приведенную ниже демонстрацию здесь
select customer_id
from trips t left join locations l
on src_id = l.id left join locations l1 on dest_id = l1.id
where l.name='Airports' or l1.name='Airports'
group by customer_id
having min(l.name)=min(l1.name) and max(l.name)=max(l1.name)
Ответ №2:
Я бы сформулировал это как единое соединение, затем агрегирование:
select t.customeri_d
from trips t
inner join location l on l.id in (t.src_id, t.dest_id)
group by t.customer_id
having min(l.name) = max(l.name) and min(l.name) = 'Airports'
Вы также можете сделать это с помощью двух объединений — но вам нужно поместить логику фильтрации having
только в предложение, а не в where
предложение:
select t.customeri_d
from trips t
inner join location ls on l.id = t.src_id
inner join location ld on l.id = t.dest_id
group by t.customer_id
having min(ls.name) = max(ls.name) and min(ls.name) = 'Airports'
and min(ld.name) = max(ld.name) and min(ld.name) = 'Airports'
Комментарии:
1. Можете ли вы объяснить, почему там используется min() = max() ?
2. @harshini: это просто способ проверить, что все значения одинаковы (поскольку минимальное и максимальное значения равны)