4 таблицы SQL Присоединение Проблема

У меня есть четыре таблицы, подобные следующим:

Cars:
car_id | make_id
1      | 1
2      | 3

Cars Makes 
make_id  | make_name
1        | BMW
2        | Ferrari
3        | Mercedes 


Car Properties 
car_id  | property_id | property_value
1       | 1           | Automatic
1       | 2           | 1000
1       | 3           | Diesel
2       | 1           | Manual
2       | 2           | 15000
2       | 3           | Gasoline

Properties
property_id | property_name
1           | Transmission
2           | Mileage
3           | Fuel

Как видите, у каждой машины есть make_id из таблицы "Makes" .

А есть отдельная таблица, содержащая все основные свойства автомобилей. Затем есть таблица "Свойства автомобиля", которая содержит car_id, property_id, property_value

Теперь я хочу сделать следующий запрос: получить автомобили BMW с автоматической коробкой передач и пробег 1000 с дизельным топливом. давайте предположим, что форма может обеспечить следующее: make_id = 1 (BMW) properties = Automatic, 1000, Diesel

PS: все будет хорошо, если я просто получу результат car_id

6 ответов

Решение

Предполагая, что запрос должен удовлетворять всем трем свойствам:

SELECT c.car_id
FROM
    Cars c INNER JOIN (
        SELECT car_id, COUNT(*) AS prop_count
        FROM
            CarProperties
        WHERE
            (property_id = 1 AND property_value = 'Automatic')
            OR (property_id = 2 AND property_value = '1000')
            OR (property_id = 3 AND property_value = 'Diesel')
        GROUP BY car_id
    ) AS cp ON c.car_id = cp.car_id AND cp.prop_count = 3
WHERE
    c.make_id = 1;

Тогда мне пришло в голову:

SELECT c.car_id
FROM
    Cars c INNER JOIN (
        SELECT car_id FROM CarProperties
        WHERE property_id = 1 AND property_value = 'Automatic'
    ) AS t ON c.car_id = t.car_id INNER JOIN (
        SELECT car_id FROM CarProperties
        WHERE property_id = 2 AND property_value = '1000'
    ) AS m ON c.car_id = m.car_id INNER JOIN (
        SELECT car_id FROM CarProperties
        WHERE property_id = 3 AND property_value = 'Diesel'
    ) AS f ON c.car_id = f.car_id
WHERE
   c.make_id = 1;

Не 100% на синтаксис mysql (извините, слишком много живите в TSQL), но это идея отношений, которую нужно использовать.

FROM Car 
JOIN CarProperties Trans
    ON Car.car_id = Trans.CarID AND Trans.property_id = 1
JOIN CarProperties Mileage 
    ON Car.car_id = Mileage.CarID AND Mileage.property_id = 2
JOIN CarProperties Fuel 
    ON Car.car_id = Fuel.CarID AND Fuel.property_id = 3

Ваш выбор может опираться на пробег, топливо или транс, как и пункт, где вы

Поскольку вход имеет только такие значения, как "Автоматически,1000, Дизель" и ни одно из них, например "Трансмиссия, Пробег, Топливо", вам придется игнорировать таблицу свойств и молиться о том, чтобы ваши типы свойств никогда не включали перекрывающиеся ключи (или более одного числового типа).). Кроме того, поскольку вход уже имеет make_id напрямую, мы можем оставить Cars Makes стол тоже.

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

SELECT c.car_id 
FROM cars c
INNER JOIN `Car Properties` cp1 
    ON cp1.car_id = c.car_id AND cp1.property_value = 'Automatic'
INNER JOIN `Car Properties` cp2 
    ON cp2.car_id = c.car_id AND cp2.property_value = 'Diesel'
INNER JOIN `Car Properties` cp3 
    ON cp3.car_id = c.car_id  AND cp3.property_value = '1000'

Возможно, это может сработать:

SELECT car_id
FROM Cars LEFT JOIN CarMakes USING (make_id)
     JOIN (SELECT car_id
           FROM CarProperties JOIN Properties USING (property_id)
           WHERE property_name='Transmission' AND property_value='Automatic') a
     JOIN (SELECT car_id
           FROM CarProperties JOIN Properties USING (property_id)
           WHERE property_name='Mileage' AND property_value='1000') b
     JOIN (SELECT car_id
           FROM CarProperties JOIN Properties USING (property_id)
           WHERE property_name='Fuel' AND property_value='Diesel') c
WHERE make_name = 'BMW'

Сначала вы можете присоединиться к свойствам и свойствам автомобилей, присвоить им псевдоним и получить массив car_id, а затем выполнить поиск "Присоединение к автомобилям". "Делает IN" (car_id_array).

select cars.car_id
   from
      cars 
         join `car properties` cp
            on cars.car_id = cp.car_id
            join properties p
               on cp.property_id = p.property_id
   where
         cars.make_id = 1
      and (   ( p.property_name = "Transmission" and cp.property_Value = "Automatic" )
           OR ( p.property_name = "Mileage" and cp.property_Value = "1000" )
           OR ( p.property_name = "Fuel" and cp.property_Value = "Diesel" )
          )
   group by
      cars.car_id
   having
      count(*) = 3 
Другие вопросы по тегам