Можете ли вы решить этот простой запрос SQL? - PullRequest
2 голосов
/ 02 февраля 2012

Предположим, это веб-сайт, который продает фотоаппараты.Вот мои сущности (таблицы):

Camera: A simple camera
Feature: A feature like: 6mp, max resolution 1024x768, 

Дело в том, что между камерами и функцией у меня есть отношение многие ко многим, поэтому у меня есть дополнительная таблица:

camera -> cameras_features -> feature

Итак, запрос прост:

Как получить все камеры, имеющие функцию 1,2 и 3?

Это похоже на создание индекса растрового изображения.

Данные, которые можно использовать для проверки правильности решения

C1 has features 1,2,3
C2 has features 1,2,4
C3 has features 1,2

Вот запросы и ожидаемый результат:

  • Показать все камеры с функциями 1,2 и 3: C1
  • Показать все камеры с функциями 1,2 и 4: C2
  • Показать все камеры, которые имеют функции 1 и 2: C1 , C2 и C3

Вот что я сделал (это работает, но это действительно ужасно, я не хочу его использовать):

SELECT * FROM camera c

WHERE c.id IN (    
    (SELECT c.id FROM camera c JOIN cameras_features f ON (c.id=f.camera_id)
    WHERE f.feature_id=1)
        q1 JOIN -- simple intersect
    (SELECT c.id FROM camera c JOIN cameras_features f ON (c.id=f.camera_id)
    WHERE f.feature_id=2)
        q2 JOIN ON (q1.id=q2.id)
)

Ответы [ 3 ]

5 голосов
/ 02 февраля 2012
SELECT camera.id
FROM camera JOIN camera_features ON camera.id=camera_features.camera_id
GROUP BY camera.id
HAVING sum(camera_features.feature_id IN (1,2,3))=3

3 - количество функций в (1,2,3). И предполагая, что (camera_id,feature_id) является уникальным в camera_features.

3 голосов
/ 02 февраля 2012
SELECT DISTINCT Camera.*
FROM Camera c
     INNER JOIN cameras_features fc1 ON c.id = fc1.camera_id AND fc1.feature_id = 1
     INNER JOIN cameras_features fc2 ON c.id = fc2.camera_id AND fc2.feature_id = 2

Здесь происходит то, что камеры будут отфильтрованы до камер с функцией 1, а затем в этой группе камеры будут отфильтрованы до камер с функцией 2

.
1 голос
/ 02 февраля 2012

Это проще всего обобщить, поместив значения поиска в таблицу ...

INSERT INTO search SELECT 1
         UNION ALL SELECT 2
         UNION ALL SELECT 3

SELECT
  camera_features.camera_id
FROM
  camera_features
INNER JOIN
  search
    ON search.id = camera_features.feature_id
GROUP BY
  camera_features.camera_id
HAVING
  COUNT(DISTINCT camera_features.feature_id) = (SELECT COUNT(DISTINCT id) FROM search)
...