【问题标题】:SQL (postgres) to join over a variable number of subselectsSQL(postgres)加入可变数量的子选择
【发布时间】:2015-06-04 19:22:47
【问题描述】:

我有 3 张桌子:

  • 商店 {'ID','NAME'}
  • 产品 {'ID','NAME'}
  • 订单{'SHOP_ID','PRODUCT_ID','QTY'}

orders 表引用了product.id,用于在带有shop.id 的商店出售的产品。

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

获取每家商店的前十名产品很容易。通过重复并加入选择以从单个商店获取此信息,对于固定数量的 n 家商店也很容易获得此信息,但我不知道如何为可变数量的商店执行此操作。 我搜索了类似的例子,我的感觉是,这应该可以通过 common table expression 实现,但我不明白。

所以问题是:

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

结果应该是这样的示例:

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

其中的数字是前 10 名卖家的产品 ID。 IE。列的创建类似于 xx.product_id 为 'Berlin'。

【问题讨论】:

    标签: sql postgresql


    【解决方案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 的函数。

    【讨论】:

    • 这会获取数据,但如果可能的话,我真的很想知道如何以转置形式获取这些数据。
    【解决方案2】:

    我想你只想要 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 表。

    【讨论】:

    • 这给了我按商店排列的十个产品,但在行而不是列中。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2016-05-16
      • 1970-01-01
      • 2020-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-20
      相关资源
      最近更新 更多