SQL 按前 n 个出现的 SKU 进行分组

问题描述 投票:0回答:4

我有一张像所谓的桌子

billing

sku_code | invoice_id | sku_amount | sku_sale
integer  | integer    | float      | float

我想做的是首先找到前 350 名

sku_code
by
sku_amount

SELECT TOP 350 Sum(sku_amount) AS amt, 
       sku_code
FROM   billing 
GROUP  BY sku_code
ORDER  BY amt DESC 

然后我想将整个表格按上面显示的 350

sku_code
进行切片

我认为这将是某种通过

inner-join
sub-query
,但我无法弄清楚语法。

我想最终运行的查询是,但它只返回上述查询中的 350 个 sku_codes。

SELECT sum(sku_amount) as amt,sku_code, invoice_id
from billing 

group by sku_code, invoice_id

order by amt DESC

这给了我一个看起来应该有大约 20-3000 万行的表。

amt | sku_code | invoice_id
sql sql-server
4个回答
1
投票

如果我理解正确的话,您需要前 350 个 sku 的原始行。 一个

JOIN
就足够了:

SELECT b.*
FROM billing b JOIN
     (SELECT TOP 350 Sum(sku_amount) AS amt, 
             sku_code
      FROM billing 
      GROUP BY sku_code
      ORDER BY amt DESC 
     ) s
     ON s.sku_code = b.sku_code

1
投票

如果我理解正确,你可以只使用排名。这将为您提供 sku_amount 位于前 350 名的所有记录

SELECT * 
  FROM (
    SELECT billing.*,
           RANK() OVER ( PARTITION BY 1 ORDER BY sku_amount DESC ) rnk
    FROM   billing 
    ) TMP
 WHERE rnk <= 350

1
投票

如果您的数据库版本是 2012+,则使用

OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
    [
      FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
    ]

语法为

SELECT SUM(sku_amount) AS amt, sku_code, invoice_id
  FROM billing 
 GROUP BY sku_code, invoice_id  
 ORDER BY ROW_NUMBER() OVER (ORDER BY SUM(sku_amount) DESC)
 OFFSET 0 ROWS
 FETCH NEXT 350 ROWS ONLY

在 order by 子句中使用窗口分析函数(在本例中为

row_number()
),无需子查询

演示


1
投票

您可以通过为

row_number
内的行指定
CTE
并使用 row_number 小于或等于 350 的行来实现此目的。

查询

;with cte as(
  select [rn] = row_number() over(
    partition by [sku_code]
    order by [amount] desc
  ), *
  from [bill]
)
select sum([sku_amount]) as [amount]
from cte
where [rn] <= 350;
© www.soinside.com 2019 - 2024. All rights reserved.