编写Oracle查询以获得前5000家商店的前10个产品

时间:2011-02-14 07:09:59

标签: sql oracle rank

  

可能重复:
  Get top 10 products for every category

我正在寻找一个Oracle查询,以获得前5000名商店,每个商店获得前10名产品,每个前10名产品获得前5名子产品。总的来说,我应该得到5000 * 10 * 5行。

有人可以使用Oracle的分析功能帮助我解决这个问题。

我当前的查询类似于

SELECT 
store,
product, 
sub-product,
 count(*) as sales 
 FROM stores_data
 GROUP BY store, product, sub-product;

请假设表名为stores_data,其列为store_id,product,sub_product

2 个答案:

答案 0 :(得分:4)

你应该使用dense_rank来获得前N行。

这样的东西
SELECT
  storeid,
  store,
  productid,
  product,
  subproductid,
  subproduct
FROM
  (
    SELECT
      s.storeid,
      s.store,
      p.productid,
      p.product,
      sp.subproductid,
      sp.subproduct,
      dense_rank() over ( order by s.storeid) as storerank,
      dense_rank() over ( partition by s.storeid 
                          order by p.productid) as productrank
      dense_rank() over ( partition by s.storeid, p.productid 
                          order by sp.subproductid) as productrank
    FROM
      stores s
      INNER JOIN products p on p.storeid = s.storeid
      INNER JOIN subproduct sp on sp.productid = p.productid
  ) t
WHERE
  t.storerank <= 5000 and
  t.productrank < 10 and
  t.subproductrank < 5

当然,我现在不是你的表,也不是它们之间的关系。以及您要检查的实际字段和条件,因此这只是一个基于其ID获取前N个记录的简单查询。此外,此查询要求产品只有一个商店,可能不是这样。至少它会告诉您如何使用dense_rank进行三层排序/过滤。

答案 1 :(得分:1)

我会留下另一个答案,因为这看起来更像是这样的表结构应该是什么,我想。

但是你在另一个帖子中描述了一个看起来像这样的表:

create table store_data (
  store varchar2(40), 
  product varchar2(40), 
  subproduct varchar2(40), 
  sales int);

实际上看起来已经聚合的数据已经存在并且您现在想要再次进行分析。您的查询可能如下所示。它首先汇总销售总额,因此您也可以通过销售订购商店和产品(表中的销售额似乎是针对子产品。之后,您可以按销售额向商店和产品添加排名。我添加了一个我也在这里使用排名。所以当更多的记录具有相同的销售额时,编号存在差距。这样,当你得到8个排名为1的记录时,因为它们都具有相同的销售额,第6条记录实际上将排名第9而不是2,所以你只会选择8个顶级商店(你想要5个,但为什么跳过其他3个,如果它们实际上卖的完全相同)而不是4个其他商店。

select
  ts.*
from  
  (
    select
      ss.*,
      rank() over (order by storesales) as storerank,
      rank() over (partition by store order by productsales) as productrank,
      rank() over (partition by store, product order by subproductsales) as subproductrank
    from
      (
        select 
          sd.*,
          sum(sales) over (partition by store) as STORESALES,
          sum(sales) over (partition by store, product) as PRODUCTSALES,
          sum(sales) over (partition by store, product, subproduct) as SUBPRODUCTSALES
        from 
          store_data sd
      ) ss 
  ) ts
where
  ts.storerank <= 2 and
  ts.productrank <= 3 and
  ts.subproductrank <= 4