SQL-запрос, чтобы получить результаты только при наличии всех запрошенных совпадений из двух столбцов

0

Я хочу получить результат, когда значение столбца 1 можно найти для трех (или более) комбинаций столбца 2 и 3 (по парам?) Пример... здесь гипотетическая таблица из 3 столбцов:

FRUIT   |  TRAIT    |   DESCRIBED
-------------------------------
Apple   |  color    |  red 
Apple   |  shape    |  round
Pear    |  surface  |  smooth 
pear    |  stem     |  red 
grape   |  shape    |  round 
grape   |  color    |  red 
grape   |  surface  |  smooth

Я хочу найти фрукты, имеющие форму = круглые, цвет = красный и всплывающий = гладкий. Результат в приведенной выше таблице должен быть "grape", но мои попытки выяснить правильный SQL-запрос, я не могу сузить его. Я получаю Apple, потому что она красная, и груша, потому что она гладкая. Но я не хочу этих. Мне нужен плод, который появляется для всех трех признаков/описаний.

Я добрался до этого, думая, что есть способ использовать группу, и я использовал подзапросы - думая, что это даст мне способ потребовать. Но это все равно не дает мне только "виноград" в результатах.

 SELECT fruit /* DISTINCT ?*/ FROM table1 WHERE fruit 
 IN  (SELECT fruit FROM table1 WHERE trait = 'shape' AND described = 'round')
 AND (SELECT fruit FROM table1 WHERE trait = 'color' AND described = 'red')
 AND (SELECT fruit FROM table1 WHERE trait = 'surface' AND described = 'smooth')     
 HAVING count(fruit) = 3   /* or whatever number of trait/described combos were searched for */
Теги:

3 ответа

1
Лучший ответ

Ты был так близко. Просто продолжайте выбирать фрукты из своих статей и не беспокойтесь о счете - также вы были правы в использовании DISTINCT

SELECT DISTINCT FRUIT FROM Table1 
WHERE FRUIT IN (SELECT FRUIT FROM Table1 WHERE TRAIT = 'shape' AND DESCRIBED = 'round')
AND FRUIT IN (SELECT FRUIT FROM Table1 WHERE TRAIT = 'color' AND DESCRIBED = 'red')
AND FRUIT IN (SELECT FRUIT FROM Table1 WHERE TRAIT = 'surface' AND DESCRIBED = 'smooth')

Вы можете выполнить свое тестирование на SQL Fiddle, который я использовал

1

Я бы просто сделал:

SELECT fruit 
FROM table1 
WHERE (trait, described) IN ( ('shape', 'round'), ('color', 'red'), ('surface', 'smooth') )  
GROUP BY fruit 
HAVING count(fruit) = 3  ;

Это намного проще читать, писать и поддерживать, чем запрос с ненужными подзапросами. Что касается производительности, SELECT DISTINCT по существу совпадает с GROUP BY с точки зрения производительности, и это не делает ненужных подзапросов. Поэтому он должен побеждать и на этом фронте.

  • 0
    Это выглядит многообещающе для меня ... но в моем реальном тесте таблицы это дает нулевые результаты? ... ВЫБРАТЬ Entity_id ОТ field_plant_descriptors WHERE (field_plant_descriptors_plant_part_described, field_plant_descriptors_description_term) IN ((8770, 8060), (8758, 8109), (8773, 8236)) GROUP BY Entity_id HAVING count = 3 Entity = 3
  • 0
    поцарапайте это ... просто опечатка. Спасибо! Я мог бы пойти с этим. Мне нравится, что нет подзапросов
Показать ещё 2 комментария
0

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

SELECT FRUIT
FROM table1
GROUP BY FRUIT
HAVING SUM(CASE WHEN TRAIT = 'color' AND DESCRIBED = 'red' THEN 1 ELSE 0 END  ) > 0
AND SUM(CASE WHEN TRAIT = 'shape' AND DESCRIBED = 'round' THEN 1 ELSE 0 END  ) > 0
AND SUM(CASE WHEN TRAIT = 'surface' AND DESCRIBED = 'smooth' THEN 1 ELSE 0 END  ) > 0

демонстрация

Используя Mysql, вы также можете использовать sum(a=b), SUM(TRAIT = 'color' AND DESCRIBED = 'red' ) как сокращенное выражение, используя выражение внутри sum() приведет к логическому значению 0/1, true/false

  • 0
    Решение dbmitch сработало для меня, но есть ли некоторые преимущества в вышеописанном методе, которые могут сделать его более подходящим?
  • 0
    @ user3385160 вы можете видеть, что он выполняет всю логику, используя один запрос, не включающий подзапросы, также я не уверен в производительности, которую вы могли бы выполнить, объяснить план для обоих запросов и принять решение

Ещё вопросы

Сообщество Overcoder
Наверх
Меню