SQL(postgres)连接可变数量的子选择

时间:2015-03-31 12:38:34

标签: sql postgresql

我有3张桌子:

  • 购物{' ID',' NAME'}
  • 产品{' ID',' NAME'}
  • 订单{' SHOP_ID',' PRODUCT_ID',' QTY'}

orders表格引用product.id表示已在shop.id商店销售的产品。

我想创建一个sql视图,每个商店选择前10个产品。因此,我希望结果表有10行(每个等级一个)和shop表中存在商店ID的列数,每列中有10个卖家。

获得每个商店的十大产品很容易。通过重复和加入选择从单个商店获得这个,它也很容易得到固定数量的n个商店,但我不知道如何为不同数量的商店做这个。 我搜索了类似的例子,我的感觉是,这应该可以通过公用表表达式来实现,但我没有得到它。

所以问题是:

如何在循环或类似构造中加入可变数量的子选择

示例结果如何:

'RANK' 'Berlin' 'Hamburg' 'München'
  1        2        3         4
  2        .        .         .
  .        .        .         .
  .        .        .         .
  9        .        .         .
 10        .        .         x 

其中数字是前10名卖家的产品编号。 即这些列的创建方式与xx.product_id一样为' Berlin'。

3 个答案:

答案 0 :(得分:1)

以下内容产生了您正在寻找的转置:

    select shop_id, 
    max(case when r = 1 then product_id else 0 end) as p_1,
    max(case when r = 2 then product_id else 0 end) as p_2,
    max(case when r = 3 then product_id else 0 end) as p_3,
    max(case when r = 4 then product_id else 0 end) as p_4,
    max(case when r = 5 then product_id else 0 end) as p_5,
    max(case when r = 6 then product_id else 0 end) as p_6,
    max(case when r = 7 then product_id else 0 end) as p_7,
    max(case when r = 8 then product_id else 0 end) as p_8,
    max(case when r = 9 then product_id else 0 end) as p_9,
    max(case when r = 10 then product_id else 0 end) as p_10
    from
    (
        select shop_id, product_id, sum(qty) as sales, 
        row_number() over (partition by shop_id order by sum(qty) desc) as r
        from orders
        group by shop_id, product_id
    )group by shop_id

要转置此项,您可以使用crosstab,但这需要您事先了解商店数量。数据库通常不会设计为具有未知列数的表。一种可能的方法是创建一个类似于here的函数。

答案 1 :(得分:0)

我认为你只想要row_number()聚合:

select s.*, o.product_id
from shops s join
     (select shop_id, product_id, sum(qty) as qty,
             row_number() over (partition by shop_id order by sum(qty) desc) as rnk
      from orders o
      group by shop_id, product_id
     ) o
     on s.shop_id = o.shop_id
where rnk <= 10;

如果您想了解产品的更多信息(超过产品ID),那么您可以加入products表。

答案 2 :(得分:0)

您可以查看crosstab函数来创建数据透视表。 AFAIK无法创建动态列,但请试一试。