根据作用在第二个表上的where子句过滤通过数据透视表链接到另一个表的表行

时间:2019-05-14 10:02:11

标签: mysql orm knex.js bookshelf.js

+--------------+
|  paintings   |
+--------------+
| id | title   |
+----+---------+
| 1  | muzelf1 |
| 2  | muzelf2 |
| 3  | muzelf3 |
+----+---------+

+----------------------------------------+
|                  tags                  |
+----------------------------------------+
| id | type            | name            |
+----+-----------------+-----------------+
| 1  | painting_medium | oil_painting    |
| 2  | painting_style  | impressionistic |
| 3  | painting_medium | mixed_media     |
| 4  | painting_medium | watercolours    |
| 5  | painting_style  | mixed_media     |
| 6  | painting_style  | photorealistic  |
+----+-----------------+-----------------+


+---------------------------+
|       paintings_tags      |
+---------------------------+
| id | painting_id | tag_id |
+----+-------------+--------+
| 1  | 1           | 1      |
| 2  | 1           | 2      |
| 3  | 2           | 4      |
| 4  | 3           | 2      |
| 5  | 3           | 1      |
+----+-------------+--------+

sql

CREATE TABLE paintings (
id integer AUTO_INCREMENT PRIMARY KEY,
title text
);

INSERT INTO paintings(id,title) VALUES
 (1,'muzelf1'),(2,'muzelf2'),(3,'muzelf3');

CREATE TABLE tags (
id integer AUTO_INCREMENT PRIMARY KEY,
name text,
type text
);

INSERT INTO tags(id,name,type) VALUES
(1,'oil_painting','painting_medium')
,(2,'impressionistic','painting_style')
,(3,'mixed_media','painting_medium')
,(4,'watercolours','painting_medium')
,(5,'mixed_media','painting_style')
,(6,'photorealistic','painting_style');

CREATE TABLE paintings_tags (
id integer AUTO_INCREMENT PRIMARY KEY,
painting_id integer,
tag_id integer
);

INSERT INTO paintings_tags(id,painting_id,tag_id) VALUES
(1,1,1)
,(2,1,2)
,(3,2,4)
,(4,3,2)
,(5,3,1);
  

使用[{tags.type =“ painiting_medium”,tags.name =“ oil_painitng”},{tags.type =“ painiting_style”,tags.name =“ impressionistic”}]查找所有绘画。

+-----------------------------------+
|         Expected Output           |
+-----------------------------------+
| id | painting_title | painting_id |
+----+----------------+-------------+
| 1  | muzelf1        | 1           |
+----+----------------+-------------+
| 2  | muzelf3        | 3           |
+----+----------------+-------------+

这是我尝试使用 bookShelf ORM knex查询生成器进行的操作。

 Painting.query(function (qb) {
    qb.innerJoin('painting_tags','paintings.id','painting_tags.painting_id')
            .innerJoin('tags','painting_tags.tag_id','tags.id')
            .where(qb => {
              tagFilters.forEach(filter => {
                qb.where('tags.type',filter.type).andWhere('tags.name',filter.name)
              })
            });
    });

仅当标签过滤器数组只有一个元素时,以上内容才有效。但是我需要它对数组中的所有过滤器起作用。

  

上面的原始查询会是什么样?以及如何使用ORM和查询生成器将其转换为正常工作?

1 个答案:

答案 0 :(得分:0)

这是一个主意:

SELECT p.id painting_id
     , p.title
     , MAX(CASE WHEN t.type = 'painting_medium' THEN t.name END) medium
     , MAX(CASE WHEN t.type = 'painting_style' THEN t.name END) style 
  FROM paintings p 
  JOIN paintings_tags pt 
    ON pt.painting_id = p.id 
  JOIN tags t 
    ON t.id = pt.tag_id 
 GROUP 
    BY p.id;
+-------------+---------+--------------+-----------------+
| painting_id | title   | medium       | style           |
+-------------+---------+--------------+-----------------+
|           1 | muzelf1 | oil_painting | impressionistic |
|           2 | muzelf2 | watercolours | NULL            |
|           3 | muzelf3 | oil_painting | impressionistic |
+-------------+---------+--------------+-----------------+

您可以将其过滤为子查询(或使用HAVING),但是除非数据集庞大,否则我倾向于使用一些JavaScript进行过滤。