SELECT DISTINCT значения после JOIN

У меня есть 3 таблицы:

Vehicle: vehicle_id, vehicle_type
1, motorcycle
2, car
3, van

Owners: person_id, vehicle_id, date_bought
1, 1, 2009
1, 2, 2008
2, 3, 2009
2, 1, 2005

Я хочу отобразить список всех названий транспортных средств. Если person_id = 1, date_bought также должны быть возвращены.

Вот я и подумал, что начну с этого:

SELECT * FROM vehicles
LEFT JOIN Owners USING (vehicle_id)

который возвращает это:

1, 1, motorcycle, 2009
1, 2, car, 2008
2, 3, van, 2009
2, 1, motorcycle, 2005

Однако сейчас я не могу сузить это до нужного результата. Если я использую DISTINCT(car_id), ничего не изменится, так как я уже выбираю разные идентификаторы автомобилей до JOIN; они неразличимы только после соединения. Если я использую WHERE person_id = 1, я удаляю последние 2 строки, и все ссылки на фургон исчезают. Если я использую GROUP BY car_id, первая и последняя строки объединяются, но date_bought для мотоцикла выбирается произвольно. Я хочу вот что:

1, 1, motorcycle, 2009
1, 2, car, 2008
 , 3, van, 

Мне нужен отдельный идентификатор автомобиля, но это происходит до JOIN и поэтому не имеет никакого эффекта. Как я могу получить уникальность с помощью JOIN?


person Rupert Madden-Abbott    schedule 22.12.2009    source источник
comment
Возможный дубликат Выбрать отдельные записи в объединении   -  person NIKHIL NEDIYODATH    schedule 15.03.2018


Ответы (2)


Вам нужно включить ограничение на идентификатор человека в ваше соединение и использовать внешнее соединение. Внешние соединения используются, когда вы хотите вернуть информацию, даже если в таблице, к которой вы присоединяетесь, нет записей. Пытаться

SELECT person_id, vehicles.* 
FROM vehicles 
LEFT OUTER JOIN Owners on vehicles.vehicle_id = owners.vehicle_id 
and person_id = 1
person Robert Christie    schedule 22.12.2009

Это должно вернуть то, что вы указали как ожидаемый результат:

   SELECT DISTINCT
          o.person_id,
          v.vehicle_id,
          v.vehicle_type,
          o.date_bought
     FROM VEHICLES v
LEFT JOIN OWNERS o ON o.vehicle_id = v.vehicle_id
LEFT JOIN (SELECT t.vehicle_id,
                  MAX(t.date_bought) 'max_date_bought'
            FROM OWNERS t
        GROUP BY t.vehicle_id) x ON x.vehicle_id = o.vehicle_id
                                AND x.max_date_bought = o.date_bought
    WHERE o.person_id IS NULL 
       OR o.person_id = 1

Имейте в виду, что из-за левого соединения столбцы OWNERS вернут NULL, если в таблице OWNERS нет соответствующего vehicle_id.

person OMG Ponies    schedule 22.12.2009