ВЫБЕРИТЕ РАЗЛИЧНЫЕ значения после СОЕДИНЕНИЯ - PullRequest
4 голосов
/ 22 декабря 2009

У меня есть 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?

Ответы [ 2 ]

7 голосов
/ 22 декабря 2009

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

SELECT person_id, vehicles.* 
FROM vehicles 
LEFT OUTER JOIN Owners on vehicles.vehicle_id = owners.vehicle_id 
and person_id = 1
3 голосов
/ 22 декабря 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.

...