如何将产品的前5个评论“转移”到列中?

时间:2009-08-11 23:17:41

标签: sql

我需要(安全地)处理有< 5“评论”的产品(甚至没有)。此外,能够定义“评论”的顺序很重要。我更喜欢一个适用于SQL Server和PostgreSQL的解决方案(稍作修改)。我愿意使用PIVOT作为最后的手段,但从我所看到的它不会做我想做的事。

表1
id 产品
1,'产品1'
2,'产品2'

表2
id 审核
1,'回顾#1a'
1,'回顾#1b'
1,'回顾#1c'
1,'回顾#1d'
1,'评论#1e'
1,'回顾#1f'
2,'回顾#2a'
2,'回顾#2b'
2,'回顾#2c'
2,'回顾#2d'
2,'回顾#2e'
2,'回顾#2f'

结果
1,'产品1','评论#1a','评论#1b','评论#1c','评论#1d','评论#1e'
2,'产品2','评论#2a','评论#2b','评论#2c','评论#2d','评论#2e'

3 个答案:

答案 0 :(得分:1)

试试这个(调整以引用适当的东西):

这个想法是......使用row_number()来获得每个产品最多5个评论。然后转动结果,然后执行左连接以获取产品详细信息(包括那些没有任何评论的内容)。

with top5reviews as 
(
select * 
from
(
select 
  productid, review
  , row_number() over (partition by productid order by reviewid) as reviewnum
from reviews
) r
where reviewnum <= 5
)
, pivotted as
(
select productid, [1] as review1, [2] as review2, [3] as review3, [4] as review4, [5] as review5
from top5reviews r
 pivot
 (max(review) for reviewnum in ([1],[2],[3],[4],[5])) p
)
select *
from products p
  left join
  pivotted r
  on p.productid = r.productid

答案 1 :(得分:0)

PIVOT与ROW_NUMBER()结合使用即可。以下是SQL Server的Northwind示例数据库中的示例。如果您对如何调整它有任何疑问,请询问并发布表和样本数据的CREATE TABLE和INSERT语句。

我使用了CTE,因为它很方便,但可以将其重写为派生表。

请注意,使用MAX只是为了满足旋转聚合的PIVOT语法要求。 MIN也可以。

with Ranked(EmployeeID,Freight,rk) as (
  select 
    EmployeeID,
    Freight,
    row_number() over (
      partition by EmployeeID
      order by Freight desc, OrderID
    )
  from Orders
)
  select EmployeeID, [1],[2],[3],[4],[5]
  from (select * from Ranked where rk <= 5) as T pivot (
    max(Freight) for rk in ([1],[2],[3],[4],[5])
  ) AS P;

答案 2 :(得分:-1)

请注意,当OP提供它时,table2中的id列是table1的外键。

alter table table2 add column rank int; 
-- better reviews have lower ranks

alter table table2  constraint table2idrank unique( id, rank) ; 
-- ranks are unique within a product

-- note, ranks must also be consecutive

create view min_rank_review as 
select id, min(rank) as rank
from table2 
group by id;


create view product_review_pivot as
select a.product, b.review as r1, c.review as r2, d.review as r3, e.review as r4
from
table1 a left outer join table2 b on (a.id = b.id)
join min_rank_review m on (b.id = m.id and b.rank = m.rank)
left outer join table2 c on (c.id = b.id and c.rank + 1 = b.rank)
left outer join table2 d on (d.id = c.id and d.rank + 1 = c.rank)
left outer join table2 e on (e.id = f.id and e.rank + 1 = d.rank);

select * from product_review_pivot;

编辑:我认为down-mods是因为这不起作用。但是将left outer join min_rank_review m on (b.id = m.id and b.rank = m.rank)替换为join min_rank_review m on (b.id = m.id and b.rank = m.rank)(并进行一些其他小修正)并且它可以正常工作。

对不起,我的办公室伙伴想回家,并没有给我时间去校对。 :)

插入以下数据:

insert into table1 ( product ) values  ('a'), ('b');
insert into table2(id, review, rank) values 
(1, 'r1', 1 ), (1, 'r2', 2), (1, 'r3', 3 ), 
(1, 'r4', 4), (1, 'r5', 5 ), (2, 'rr2', 1);

我得到以下输出(在MySQL 5中):

mysql> select * from product_review_pivot;
+---------+------+------+------+------+
| product | r1   | r2   | r3   | r4   |
+---------+------+------+------+------+
|  a      | r1   | r2   | r3   | r4   |
|  b      | rr2  | NULL | NULL | NULL |
+---------+------+------+------+------+

(非连续排名的解决方案留作练习。)