在多个标签上创建连接视图

时间:2016-09-28 20:14:53

标签: sql join

我有以下表格作为示例

球拍

--------------------
|   id  | Name     |
|   1   | Raquet 1 | 
|   2   | Raquet 2 | 
--------------------

字符串

--------------------
|   id  | Name     |
|   1   | String 1 | 
|   2   | String 2 | 
|   3   | String 3 | 
|   4   | String 4 | 
--------------------

标签

--------------------
|   id  | Name     |
|   1   | Label 1  | 
|   2   | Label 2  | 
|   3   | Label 3  | 
|   4   | Label 4  | 
--------------------

Raquet_Labels

--------------------
|  r_id  | l_id    |
|   1    |   1     | 
|   1    |   2     | 
|   2    |   3     | 
|   2    |   4     | 
--------------------

String_Labels

--------------------
|  s_id  | l_id    |
|   1    |   1     | 
|   1    |   2     |
|   1    |   3     | 
|   2    |   1     | 
|   2    |   2     | 
|   3    |   1     | 
|   3    |   3     | 
|   4    |   3     | 
|   4    |   4     | 
--------------------

我想匹配所有列表中的所有Raquet,String组合,其中String应该具有相应Raquet的所有标签。

例如

Raquet 1有标签1,2 Raquet 2具有标签3,4

字符串1的标签为1,2,3 字符串2具有标签1,2 字符串3具有标签1,3 字符串4具有标签3,4

从上面 - 字符串1包含作为Raquet 1一部分的所有标签 字符串2包含作为Raquet 1一部分的所有标签 字符串3没有任何Raquet的标签 字符串4包含Raquet 2

的所有标签

以下是期望

--------------------
|  r_id  | s_id    |
|   1    |   1     | 
|   1    |   2     |
|   2    |   4     | 
--------------------

用于创建所需数据的SQL。

create table raquet(id integer not null, name varchar(256) not null);
insert into raquet values (1,'Raquet 1'), (2,'Raquet 2'), (3,’Raquet 3’);
create table string(id integer not null, name varchar(256) not null);
insert into string values (1,'String 1'), (2,'String 2'), (3,'String 3'), (4,'String 4');
create table label(id integer not null, name varchar(256) not null);
insert into label values (1,'Label 1'), (2,'Label 2'), (3,'Label 3'), (4,'Label 4');
create table raquet_labels(r_id integer not null, l_id integer not null);
insert into raquet_labels values (1,1), (1,2), (2,3), (2,4);
create table string_labels(s_id integer not null, l_id integer not null);
insert into string_labels values (1,1), (1,2), (1,3), (2,1), (2,2), (3,1), (3,3), (4,3), (4,4);

1 个答案:

答案 0 :(得分:0)

这项任务看起来很容易,但并非如此。这是一种方式:

  1. 我们创建了我们希望看到的记录,即所有raquet标签与所有字符串相结合。这是表Raquet_Labels与表String的交叉连接。这就是我们希望看到的所有匹配,现在我们必须测试字符串是否真正实现了这一点。
  2. 我们外部加入现有的球拍标签,因此我们得到所有比赛和所有不匹配。
  3. 我们汇总了我们的数据:对于一个raquet和一个字符串:我们只有匹配吗?我们可以做到这一点; count(*)计算所有记录,但count(<column from the outer-joined table>)仅统计匹配。计数是否相等(每个标签匹配)或不。
  4. 查询:

    select rl.r_id, s.id as s_id
    from raquet_labels rl
    cross join string s
    left join string_labels sl on sl.s.id = s.id and sl.l_id = rl.l_id
    group by rl.r_id, s.id
    having count(*) = count(sl.s_id);
    

    这是另一种方式:

    1. 我们创建了一组球拍和弦乐的所有可能组合。这是两个表的交叉连接。
    2. 对于每个这样的组合,我们检查是否找到没有匹配字符串标签的球拍标签。如果不是这样,没有没有匹配的球拍标签,所以我们保留这对。
    3. 查询:

      select r.id as r_id, s.id as s_id
      from racket r
      cross join string s
      where not exists
      (
        select l_id from raquet_labels rl where rl.r_id = r.id
        except
        select l_id from string_labels sl where sl.s_id = s.id
      );