MYSQL搜索表由双向数据透视表连接

时间:2016-06-21 05:56:10

标签: mysql database join

我有一个展览和艺术家数据库。每个展览都与任何数量的艺术家联系在一起,并通过数据透视表加入,如下:

'exhibitions'
+-----+--------------------------+
| id  | title                    |
+-----+--------------------------+
| 358 | A Closed Circuit         |
| 360 | Do You Love Me?          |
| 361 | Romans                   |
| 364 | Men in Love              |
| 367 | Bien Hoa                 |
| 369 | Jokes                    |
| 370 | Speech                   |
| 373 | Shimabuku's Fish & Chips |
+-----+--------------------------+

'artists'
+-----+-----------------+----------------------+
| id  | first_name      | last_name            |
+-----+-----------------+----------------------+
| 301 | Roman           | Schramm              |
| 302 | Ben             | Schumacher           |
| 303 | Hugh            | Scott-Douglas        |
| 304 | Nina            | Beier and Marie Lund |
| 305 | Constant        | Dullaart             |
| 306 | Brenna          | Murphy               |
| 307 | Jaako           | Pallasvuo            |
| 308 | Nicolas         | Pelzer               |
| 309 | Jon             | Rafman               |
+-----+-----------------+----------------------+

'associations'
+-------+-------------+------+-------------+------+
| id    | a_t         | a_id | b_t         | b_id |
+-------+-------------+------+-------------+------+
| 21371 | exhibitions |  369 | artists     |  301 |
| 21373 | exhibitions | 1842 | artists     | 2644 |
| 21379 | exhibitions |  315 | artists     | 2644 |
| 27752 | exhibitions | 4015 | artists     | 2644 |
| 21848 | exhibitions |   71 | artists     | 2650 |
|    34 | artists     |    1 | exhibitions |    1 |
|    85 | artists     |    5 | exhibitions |   36 |
|    90 | artists     |    8 | exhibitions |   38 |
|    97 | artists     |   10 | exhibitions |   39 |
|    98 | artists     |   54 | exhibitions |   40 |
|   100 | artists     |   55 | exhibitions |   42 |
|   102 | artists     |   55 | exhibitions |   43 |
|   103 | artists     |  301 | exhibitions |  370 |
|   584 | exhibitions |  998 | venues      |   22 |
|  1234 | venues      |   15 | exhibitions |  370 |
+-------+-------------+------+-------------+------+

'venues'
+------+--------------------+
| id   | name               |
+------+--------------------+
|   22 | ACME               |
| 1116 | Adams and Ollman   |
|  510 | Adamski            |
| 1077 | Agustina Ferreyra  |
|   15 | Air de Paris       |
+------+--------------------+

我需要创建一个符合以下条款的搜索:

  • 展览名称
  • 与展览有关的艺术家
  • 与展览有关的场地

但是,正如您所看到的,associations表中有一些交换的条目。有时展览是“A”表,有时它是“B”。此外,它也不是一个简单的数据透视表 - 正如您所看到的,它正在为所有表创建关联。这是我必须使用的,并将其分解为更简洁的数据透视表(表A至B,而不是当前的表A / B / C / D / E至A / B / C / D / E)将需要在别处进行大量重构并且是不可能的。

作为一个例子:艺术家David Leiske的ID为128,以及双向关联:

mysql> select * from associations where (a_t = 'artists' AND a_id = 126 AND b_t = 'exhibitions') OR (a_t = 'exhibitions' AND b_id = 126 AND b_t = 'artists');

+-------+-------------+------+-------------+------+
| id    | a_t         | a_id | b_t         | b_id |
+-------+-------------+------+-------------+------+
| 10438 | artists     |  126 | exhibitions |  458 |
| 10772 | exhibitions |   55 | artists     |  126 |
| 27490 | artists     |  126 | exhibitions | 3877 |
| 27500 | artists     |  126 | exhibitions | 3878 |
| 28435 | artists     |  126 | exhibitions | 4378 |
| 28474 | artists     |  126 | exhibitions | 4379 |
| 28475 | artists     |  126 | exhibitions | 4380 |
+-------+-------------+------+-------------+------+

这两个问题分别给了我需要的东西:

SELECT exhibitions.id as result_id, 'exhibitions' as result_type, exhibitions.title AS result_title, GROUP_CONCAT(CONCAT_WS(' ', artists.first_name, artists.last_name)) AS col_3
FROM exhibitions
LEFT JOIN associations AS associations ON (associations.b_id = exhibitions.id AND b_t = 'exhibitions' AND a_t = 'artists')
LEFT JOIN artists ON (associations.a_id = artists.id AND a_t = 'artists')
WHERE
  (artists.id IS NOT NULL)
  AND ((CONCAT_WS(' ', artists.first_name, artists.last_name)) RLIKE 'Lieske')
  OR (exhibitions.title RLIKE 'Lieske')
GROUP BY exhibitions.id

+-----------+-------------+------------------------------------------------------------+
| result_id | result_type | result_title                                | col_3        |
+-----------+-------------+------------------------------------------------------------+
|       458 | exhibitions | Deformation Professionelle                  | David Lieske |
|      3877 | exhibitions | Der africanishe Stuhl von marcel Breuer     | David Lieske |
|      3878 | exhibitions | Imerium in Imperio                          | David Lieske |
|      4378 | exhibitions | A Greater Administration of Lower Interests | David Lieske |
|      4379 | exhibitions | Platitude Normale                           | David Lieske |
|      4380 | exhibitions | Fantôme Mains Sur                           | David Lieske |
+-----------+-------------+------------------------------------------------------------+

SELECT exhibitions.id as result_id, 'exhibitions' as result_type, exhibitions.title AS result_title, GROUP_CONCAT(CONCAT_WS(' ', artists.first_name, artists.last_name)) AS col_3
FROM exhibitions
LEFT JOIN associations AS associations ON (associations.a_id = exhibitions.id AND a_t = 'exhibitions' AND b_t = 'artists')
LEFT JOIN artists ON (associations.b_id = artists.id AND b_t = 'artists')
WHERE
  (artists.id IS NOT NULL)
  AND ((CONCAT_WS(' ', artists.first_name, artists.last_name)) RLIKE 'Lieske')
  OR (exhibitions.title RLIKE 'Lieske')
GROUP BY exhibitions.id

+-----------+-------------+--------------+--------------+
| result_id | result_type | result_title | col_3        |
+-----------+-------------+--------------+--------------+
|        55 | exhibitions | Adequate     | David Lieske |
+-----------+-------------+--------------+--------------+

我可以将两个查询联合成一个 - 这给了我最终的结果。但是,我将动态地构建这个查询 - 这只是一个更全面的搜索的一个(麻烦)部分,如果我能处理这个A:B / B:一种更动态的关系会更容易。

我尝试在连接中添加OR:

SELECT exhibitions.id as result_id, 'exhibitions' as result_type, exhibitions.title AS result_title, GROUP_CONCAT(CONCAT_WS(' ', artists.first_name, artists.last_name)) AS col_3
FROM exhibitions
LEFT JOIN associations AS associations ON (associations.b_id = exhibitions.id AND b_t = 'exhibitions' AND a_t = 'artists')
  OR (associations.a_id = exhibitions.id AND a_t='exhibitions' AND b_t='artists')
LEFT JOIN artists ON (associations.a_id = artists.id AND a_t = 'artists')
  OR (associations.b_id = artists.id AND b_t = 'artists')
WHERE
  (artists.id IS NOT NULL)
  AND ((CONCAT_WS(' ', artists.first_name, artists.last_name)) RLIKE 'Lieske')
  OR (exhibitions.title RLIKE 'Lieske')
GROUP BY exhibitions.id

但是,我知道我做错了,因为查询需要30秒,而UNION'd查询需要0.07。

我在这里做错了什么?

最后:我如何将venues.name加入到表中并将其添加到查询中?

示例搜索:

  • RLIKE 'art|acme',预期结果:在标题中art并且在会场ACME
  • 的展览
  • RLIKE 'davis|paris',预期结果:展览包括名字为davis的艺术家,该作品发生在Air de Paris

(我知道这些会带来所有的OR比赛 - 但是,这篇文章已经足够长了,所以我可以再做一个关于排名结果的人。)

0 个答案:

没有答案