使用一次JOIN作为更多列

时间:2015-08-06 09:13:21

标签: sql join

我有四张表如下(还有很多,实际上,我省略了这个问题的不重要的表):

enter image description here

一个产品最多可以使用联结表关联5个组。我需要JOIN表格并打印所有5组和5个区域,并将一个相关产品打印为11列。

预期结果(例如):

+---------+---------+---------+---------+---------+---------+
| Product | Group 1 | Group 2 | Group 3 | Group 4 | Group 5 |
+---------+---------+---------+---------+---------+---------|
|    1    |    2    |    1    |   NULL  |   NULL  |   NULL  |
+---------+---------+---------+---------+---------+---------+

          +---------+---------+---------+---------+---------+
          | Area 1  | Area 2  | Area 3  | Area 4  | Area 5  |
          +---------+---------+---------+---------+---------|
          |    5    |    8    |   NULL  |   NULL  |   NULL  |
          +---------+---------+---------+---------+---------+

我有以下SQL查询: `

Select p.id, a1.area_id as 'Area 1', a2.area_id as 'Area 2', a3.area_id as 'Area 3', a4.area_id as 'Area 4', a5.area_id as 'Area 5', g1.group_id as 'Group 1', g2.group_id as 'Group 2', g3.group_id as 'Group 3', g4.group_id as 'Group 4', g5.group_id as 'Group 5'
From Product p
Inner Join group_product_junction j on p.product_id = j.product_id
Inner Join Group g1 on j.group_id = g1.group_id
Inner Join Group g2 on j.group_id = g2.group_id
Inner Join Group g3 on j.group_id = g3.group_id
Inner Join Group g4 on j.group_id = g4.group_id
Inner Join Group g5 on j.group_id = g5.group_id
Inner Join Area a1 a on g1.area_id = a1.area_id
Inner Join Area a2 a on g2.area_id = a2.area_id
Inner Join Area a3 a on g3.area_id = a3.area_id
Inner Join Area a4 a on g4.area_id = a4.area_id
Inner Join Area a5 a on g5.area_id = a5.area_id

`

但是这给了我所有列的相同值。我想我错过了WHERE条款或其他内容,但我无法弄清楚它应该是什么样子。

2 个答案:

答案 0 :(得分:2)

为了满足您的要求,您必须在链接到给定产品的组中创建订单的概念。这是因为您最终将按特定顺序选择最多五个组(和区域)(即组 1 ,组 2 ,组 3 等,对于给定的产品。

使用order by子句可以实现整个结果集的订单,但这还不够,因为我们需要为每个产品单独订购 。这就是分区功能存在的原因;允许在结果集的子组上操作,而不将整个组聚合到流程中的一个记录中(这是group by将要执行的操作)。

因此,我们可以做的是将每个产品记录与其所有组(如您所示,每个产品的编号不超过五个)一起加入,然后运行分区函数row_number()进行产品分区。这将允许我们创建一个新列,该列将标记每个产品的每个组,并在该产品的组中使用不同的编号。然后,我们将能够使用标记的中间表left join五次,分别过滤标签1,2,3,4和5,从而使每个组都在其自己的连接中。然后,通过组表和区域表遍历表链接就可以获得构建所需结果集所需的所有信息。

create table FArea (area_id int primary key);
create table FGroup (group_id int primary key, area_id int references FArea(area_id));
create table FProduct (product_id int primary key);
create table Fgroup_product_junction (group_id int references FGroup(group_id), product_id int references FProduct(product_id));

-- product 1
insert into FProduct (product_id) values (1);
insert into FArea (area_id) values (1), (2), (3), (4), (5);
insert into FGroup (group_id,area_id) values (1,1), (2,2), (3,3), (4,4), (5,5);
insert into Fgroup_product_junction (group_id,product_id) values (1,1), (2,1), (3,1), (4,1), (5,1);

-- product 2
insert into FProduct (product_id) values (2);
insert into FArea (area_id) values (6), (7), (8);
insert into FGroup (group_id,area_id) values (6,6), (7,7), (8,8);
insert into Fgroup_product_junction (group_id,product_id) values (6,2), (7,2), (8,2);

select * from FArea;
select * from FGroup;
select * from FProduct;
select * from Fgroup_product_junction;

with t_pg as (
    select
        p.product_id,
        j.group_id,
        row_number() over (partition by p.product_id order by j.group_id) num
    from
        FProduct p
        inner join Fgroup_product_junction j on j.product_id=p.product_id
)
select
    p.product_id "Product",
    g1.group_id "Group 1",
    g2.group_id "Group 2",
    g3.group_id "Group 3",
    g4.group_id "Group 4",
    g5.group_id "Group 5",
    a1.area_id "Area 1",
    a2.area_id "Area 2",
    a3.area_id "Area 3",
    a4.area_id "Area 4",
    a5.area_id "Area 5"
from
    FProduct p
    left join t_pg j1 on j1.product_id=p.product_id and j1.num=1 left join FGroup g1 on g1.group_id=j1.group_id left join FArea a1 on a1.area_id=g1.area_id
    left join t_pg j2 on j2.product_id=p.product_id and j2.num=2 left join FGroup g2 on g2.group_id=j2.group_id left join FArea a2 on a2.area_id=g2.area_id
    left join t_pg j3 on j3.product_id=p.product_id and j3.num=3 left join FGroup g3 on g3.group_id=j3.group_id left join FArea a3 on a3.area_id=g3.area_id
    left join t_pg j4 on j4.product_id=p.product_id and j4.num=4 left join FGroup g4 on g4.group_id=j4.group_id left join FArea a4 on a4.area_id=g4.area_id
    left join t_pg j5 on j5.product_id=p.product_id and j5.num=5 left join FGroup g5 on g5.group_id=j5.group_id left join FArea a5 on a5.area_id=g5.area_id
;

results

答案 1 :(得分:1)

尝试以下,

 select 
  product_id , 
    case when row_id = 1 then group_id end as Group1,
    case when row_id = 2 then group_id end as Group2,
    case when row_id = 3 then group_id end as Group3,
    case when row_id = 4 then group_id end as Group4,
    case when row_id = 5 then group_id end as Group5,
    case when row_id = 1 then area_id end as Area1,
    case when row_id = 2 then area_id end as Area2,
    case when row_id = 3 then area_id end as Area3,
    case when row_id = 4 then area_id end as Area4,
    case when row_id = 5 then area_id end as Area5
from 
(
  Select 
    row_number() over (partition by p.product_id order by p.product_id,j.group_id) row_id,
    p.product_id,
    g.group_id,
    g.area_id
  From Product p
  left Join group_product_junction j on p.product_id = j.product_id
  Left Join groups g on  g.group_id = j.group_id
 ) T

这是Sql Fiddle