Как объединить таблицы в несколько записей и несколько полей - PullRequest
1 голос
/ 22 сентября 2019

Мне нужно решение для довольно сложного соединения MySQL: скажем, у нас есть 3 таблицы: T1, T2 и T3.Таблица 1 содержит основной идентификатор и поле имени.

Таблица1

| ID | Name |
|  1 |   A  |
|  2 |   B  |
|  3 |   C  |
|  4 |   D  |

Таблица 2 содержит столбец для идентификатора таблицы 1 и значение

Таблица2

| ID |  oID | Value |
|  1 |   1  | aaa   |
|  2 |   1  | bbb   |
|  3 |   1  | ccc   |
|  4 |   2  | ddd   |
|  5 |   2  | eee   |
|  6 |   3  | fff   |
|  7 |   3  | ggg   |
|  8 |   3  | hhh   |
|  9 |   4  | iii   |

Пока все хорошо, простое JOIN даст мне Table2.Values, связанные с Table1.Name. Но есть также таблица 3

Table3

| ID |  oID | Condition  | Value |
| 1  |   1  | color      | red   |
| 2  |   1  | brightness | 20    |
| 3  |   2  | color      | green |
| 4  |   2  | brightness | 50    |
| 5  |   2  | saturation | 100   |
| 6  |   3  | color      | green |
| 7  |   3  | brightness | 40    |
| 8  |   3  | saturation | 70    |
| 9  |   4  | color      | purple|

ЧтоМне нужно сделать, это получить T1.Name со всеми связанными T2.Values ​​ТОЛЬКО ЕСЛИ 2 (или более) условия T3 в порядке: Например: Все имена с совпадающими T2.Values ​​IF T3.Condition = 'green' ANDT3.brightness = 50 Поскольку только ID 2 зеленого цвета с яркостью 50, это должно дать мне

B ddd
B eee

Я пробовал несколько вещей:

SELECT  t1.ID,
        t1.Name,
    t2.Value
FROM
    Table1 t1
JOIN Table2 t2  ON t1.ID = t2.oID
JOIN Table3 t3 ON t1.ID = t3.oID
WHERE 
    t3.Condition = 'color'
AND
    t3.Value = 'green'
AND
        t3.Condition = 'brightness'
AND
    t3.Value = 50

GROUP BY p.ID

Ничего не получалось, конечно, поскольку ни одна запись не имеет всех четырех условий

SELECT  t1.ID,
        t1.Name,
    t2.Value
FROM
    Table1 t1
JOIN Table2 t2  ON t1.ID = t2.oID
JOIN Table3 t3 ON t1.ID = t3.oID
WHERE 
    (t3.Condition = 'color' AND t3.Value = 'green')
AND
    (t3.Condition = 'brightness'AND t3.Value = 50)

GROUP BY p.ID

Тот же результат: ничего

SELECT  t1.ID,
        t1.Name,
    t2.Value
FROM
    Table1 t1
JOIN Table2 t2  ON t1.ID = t2.oID
JOIN Table3 t3 ON t1.ID = t3.oID
WHERE 
    (t3.Condition = 'color' AND t3.Value = 'green')
OR
    (t3.Condition = 'brightness' AND    t3.Value = 50)

GROUP BY p.ID

Я получаю все записи с яркостью 50 и те, которые имеют зеленый цвет ... но не те, которые имеют обаэти условия.

Я также пробовал с условиями в операторе JOIN ON, LEFT JOINS, WHERE coIN (.., ..) и так далее, но безуспешно.

Тот, кто находит решение, получает вечную славу!

Ответы [ 3 ]

1 голос
/ 22 сентября 2019
SELECT * FROM table3;
+----+-----+------------+--------+
| ID | oID | condition  | value  |
+----+-----+------------+--------+
|  1 |   1 | color      | red    |
|  2 |   1 | brightness | 20     |
|  3 |   2 | color      | green  |
|  4 |   2 | brightness | 50     |
|  5 |   2 | saturation | 100    |
|  6 |   3 | color      | green  |
|  7 |   3 | brightness | 40     |
|  8 |   3 | saturation | 70     |
|  9 |   4 | color      | purple |
+----+-----+------------+--------+
9 rows in set (0.00 sec)

mysql>
SELECT x.oid
  FROM table3 x
 WHERE (x.condition,x.value) IN(('color','green'),('brightness','50'))
 GROUP
    BY x.oid
HAVING COUNT(*) = 2;
+-----+
| oid |
+-----+
|   2 |
+-----+

Обратите внимание, что condition является зарезервированным словом, что делает его менее чем идеальным выбором в качестве идентификатора таблицы / столбца

0 голосов
/ 23 сентября 2019

Что вы делаете неправильно, так это то, что вы присоединяете table3 к двум другим таблицам.Вместо этого вам следует присоединиться к подзапросу table3, который возвращает oID s, которые удовлетворяют вашим условиям:

SELECT t1.name, t2.value
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.oid
INNER JOIN (
  SELECT oID FROM table3
  GROUP BY oID
  HAVING SUM(`condition` = 'color' AND value = 'green') > 0
     AND SUM(`condition` = 'brightness' AND value = '50') > 0
) t3 ON t1.id = t3.oID

См. demo .Результаты:

| name | value |
| ---- | ----- |
| B    | ddd   |
| B    | eee   |
0 голосов
/ 22 сентября 2019

Вы можете присоединиться к table1 с table2, а затем использовать два условия EXISTS с коррелированными подзапросами для проверки условий на table3:

SELECT t1.name, t2.value
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.oid
WHERE
    EXISTS (
        SELECT 1
        FROM table3 t3
        WHERE t3.oid = t1.id AND t3.condition = 'color' AND t3.value = 'green'
    )
    AND EXISTS (
        SELECT 1
        FROM table3 t3
        WHERE t3.oid = t1.id AND t3.condition = 'brightness' AND t3.value = '50'
    )

Демонстрация в БДСкрипка :

| name | value |
| ---- | ----- |
| B    | ddd   |
| B    | eee   |
...