Мне нужно создать базу данных парней, у парней может быть один или несколько атрибутов, и атрибут каждого парня имеет определенное значение, звучит легко, а?ну, продолжайте читать, так как проблема вроде как становится невозможной (5 дней на ее решение: s).
Итак, я создаю 3 таблицы:
CREATE TABLE guy (
id int(11),
name varchar(255)
);
CREATE TABLE attribute (
id int(11),
name varchar(255)
);
-- each value references one guy and one attribute
CREATE TABLE _value (
id int(11),
guy_id int(11),
attribute_id int(11),
_value varchar(255)
);
с данными этого примера:
INSERT INTO attribute VALUES (1, 'age'), (2, 'dollars'), (3, 'candies');
INSERT INTO guy VALUES (1, 'John'), (2, 'Bob');
INSERT INTO _value VALUES (1, 1, 1, 12), (2, 1, 2, 15), (3, 1, 3, 3);
INSERT INTO _value VALUES (4, 2, 1, 15), (5, 2, 2, 20), (6, 2, 3, 6);
и создайте этот запрос:
SELECT g.name 'guy', a.name 'attribute', v._value 'value'
FROM guy g
JOIN _value v ON g.id = v.guy_id
JOIN attribute a ON a.id = v.attribute_id;
, который даст мне такой результат:
+------+-----------+-------+
| guy | attribute | value |
+------+-----------+-------+
| John | age | 12 |
| John | dollars | 15 |
| John | candies | 3 |
| Bob | age | 15 |
| Bob | dollars | 20 |
| Bob | candies | 6 |
+------+-----------+-------+
ЭТО НАСТОЯЩАЯ ЗАДАЧА:
Позже, мой босс сказал мне, что он хочет фильтровать данные, используя столько условий, сколько ему нужно, чтобы иметь возможность группировать эти условия с помощью «ands» и «ors», например, он может захотеть выполнить это безумное условие:
Получите парней, возраст которых больше 10, у которых меньше 18 долларов, у которых больше 2 конфет и меньше 10 конфет, но, не смотря ни на что, также включите парней, которым ровно 15 лет.этот фильтр:
-- should return both John and Bob
(age > 10 and dollars < 18 and candies > 2 and candies < 10) or (age = 15)
У меня нет проблем с созданием фильтра (для этого я использую jqgrid), проблема в том, что атрибуты - это не столбцы, а строки вместо , и из-зачто я не знаю, как смешать запрос с фильтром, я пытался счто-то вроде этого:
SELECT g.name 'guy', a.name 'attribute', v._value 'value'
FROM guy g
JOIN _value v ON g.id = v.guy_id
JOIN attribute a ON a.id = v.attribute_id
GROUP BY guy
HAVING (
(attribute = 'age' and value > 10) AND
(attribute = 'dollars' and value < 18) AND
(attribute = 'candies' and value > 2) AND
(attribute = 'candies' and value < 10)
)
OR
(
(attribute = 'age' and value = 15)
)
но возвращается только Боб :( и я должен получить и Джона, и Боба.
ТАК, КАК СЛЕДУЕТ СМЕШИВАТЬ ФИЛЬТР И ЗАПРОС?
Имейте в виду, что количество атрибутов, которые есть у каждого парня, одинаково для всех парней, но в любое время можно добавить больше атрибутов и больше парней, например, если я хочу добавить парня «Марио»«Я бы сделал:
-- we insert the guy Mario
INSERT INTO guy VALUES (3, 'Mario');
-- with age = 5, dollars = 100 and candies = 1
INSERT INTO _value VALUES (7, 3, 1, 5), (8, 3, 2, 100), (9, 3, 3, 1);
И если бы я хотел создать атрибут« яблоки », я бы сделал:
-- we insert the attribute apples
INSERT INTO attribute VALUES (4, 'apples');
-- we create a value for each guy's new attribute, John as 7 apples, Bob has 3 and Mario has 8
INSERT INTO _value VALUES (10, 1, 4, 7), (11, 2, 4, 2), (12, 3, 4, 8);
, и теперь я смогу включить условия о яблоках вмой запрос.
Надеюсь, я стал понятен, спасибо за все ваше время:)
Примечание: Может быть, если бы был способ поместить все атрибуты каждого парня в один ряд ?,что-то вроде этого:
+------+-----------+-------+------+------------+--------+------+------------+--------+------+------------+--------+
| guy | attribute | value | guy | attribute | value | guy | attribute | value | guy | attribute | value |
+------+-----------+-------+------+------------+--------+------+------------+--------+------+------------+--------+
| John | age | 12 | John | dollars | 15 | John | candies | 3 | John | apples | 7 |
| Bob | age | 15 | Bob | dollars | 20 | Bob | candies | 6 | Bob | apples | 2 |
| Mario| age | 5 | Mario| dollars | 100| Mario| candies | 1 | Mario| apples | 8 |
+------+-----------+-------+------+------------+--------+------+------------+--------+------+------------+--------+
Примечание 2: предложил @iim (В этом вопросе: Как искать в сгруппированных столбцах в MySQL?(также в Hibernate, если это возможно) ), что я мог бы выполнить самостоятельное объединение для каждого атрибута, и да, это может решить проблему, но могут быть проблемы с производительностью, когда у ребят множество атрибутов (например, 30 или более).
Примечание 3: я не могу изменить схему базы данных: (