sql-запрос для получения клиентов, которые использовали поездки только для аэропортов

#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: это просто способ проверить, что все значения одинаковы (поскольку минимальное и максимальное значения равны)