MySql строк на основе значения столбца по сравнению с другим столбцом - PullRequest
1 голос
/ 28 марта 2020

У меня есть таблица person, которая выглядит следующим образом:

Persons

id | name
1  | Alex
2  | Jack
3  | Roy

У меня есть другая таблица

Свойства

id | title          | format
1  | Age            | number
2  | Plays Football | checkbox
3  | Weight         | number

Персоны и Свойства имеют отношение многие ко многим через третью таблицу PersonProperties.

PersonProperties

PersonId | PropertyId | value
1        | 1          | 24
1        | 2          | true
2        | 1          | 43

Я хочу отфильтровать лиц в возрасте от 20 до 30 лет и играет в футбол. Поскольку у меня уже есть идентификаторы Age и Plays Football, их значения равны id 1 (min = 20, max = 30) и id 2 (true). Чтобы получить такой запрос,

SELECT `Persons`.`id`,`name` FROM `Persons`
INNER JOIN `PersonProperties` ON `Persons`.id = `PersonProperties`.`PersonId`
WHERE ((`PersonProperties`.`value` >= 20 AND `PersonProperties`.`value` <= 30) AND `PersonProperties`.`PropertyId` = 1) 
  AND (`PersonProperties`.`value` = true AND `PersonProperties`.`PropertyId` = 2)
GROUP BY `Persons`.`id`

Возвращает пустой результат.

Желаемый результат

id | name
1  | Alex

Ответы [ 2 ]

1 голос
/ 28 марта 2020

Вы можете использовать агрегацию:

select pe.id, pe.name
from persons pe
inner join person_properties pp on pp.person_id = p.id
inner join properties pr on pr.id = pp.property_id
group by pe.id, pe.name
having 
    max(pr.title = 'Age' and pp.value + 0 between 20 and 30) = 1
    and max(pr.title = 'Plays Football' and pp.value = 'true')
1 голос
/ 28 марта 2020

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

Для этого используйте агрегирование:

SELECT p.id, p.name
FROM Persons p JOIN
     PersonProperties pp
     ON p.id = pp.PersonId
WHERE (p.PropertyId = 1 AND (p.value + 0) >= 20 AND (p.value + 0) <= 30) OR
      (p.PropertyId = 2 AND p.value = 'true')
GROUP BY p.id, p.name
HAVING COUNT(*) = 2;  -- both match

Примечания:

  • Псевдонимы таблиц значительно упрощают написание и чтение запроса .
  • Обратные метки затрудняют написание и чтение запроса.
  • Value - строка (предположительно). Следовательно, вы должны быть осторожны со сравнениями. Я добавил (+ 0), чтобы было ясно, что конверсия задействована.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...