按T-SQL中的每N条记录分组

时间:2011-08-15 17:20:07

标签: sql sql-server tsql

我在数据库上有一些性能测试结果,我想要做的是分组每1000条记录(之前按日期按升序排序),然后用 AVG汇总结果

我实际上正在寻找标准的SQL解决方案,但是也欢迎任何特定于T-SQL的结果。

查询如下所示:

SELECT TestId,Throughput  FROM dbo.Results ORDER BY id

6 个答案:

答案 0 :(得分:20)

WITH T AS (
  SELECT RANK() OVER (ORDER BY ID) Rank,
    P.Field1, P.Field2, P.Value1, ...
  FROM P
)
SELECT (Rank - 1) / 1000 GroupID, AVG(...)
FROM T
GROUP BY ((Rank - 1) / 1000)
;

这样的事情应该让你开始。如果您可以提供实际架构,我可以根据需要进行更新。

答案 1 :(得分:7)

给出Yuck的答案。我只发布一个答案,所以我可以包含一个代码块。我做了一个计数测试,看看它是否按1000分组,第一组是999.这样产生的设置大小为1,000。好查询Yuck。

    WITH T AS (
    SELECT RANK() OVER (ORDER BY sID) Rank, sID 
    FROM docSVsys
    )
    SELECT (Rank-1) / 1000 GroupID, count(sID)
    FROM T
    GROUP BY ((Rank-1) / 1000)
    order by GroupID 

答案 2 :(得分:6)

我给@Yuck 1,因为我认为这是一个很好的答案。但值得一提的是NTILE()。

原因是,如果您有10,010条记录(例如),那么您将有11个分组 - 前10个分别为1000个分组,最后一个分组为10个分组。

如果您要比较每组1000的平均值,那么您应该丢弃最后一组,因为它不是代表组,或者......您可以使所有组的大小相同。

NTILE()会使所有组的大小相同;唯一需要注意的是,你需要知道你想要多少组。

因此,如果您的表有25,250条记录,那么您将使用NTILE(25),并且您的分组大小将大约 1000 - 它们的实际大小为1010;好处是,它们都是相同的大小,这可能使它们在您正在进行的任何比较分析方面彼此更相关。

你可以通过

简单地获得你的组大小
DECLARE @ntile int
SET  @ntile = (SELECT count(1) from myTable) / 1000

然后使用NTILE()替换修改@Yuck的方法:

;WITH myCTE AS (
  SELECT NTILE(@ntile) OVER (ORDER BY id) myGroup,
    col1, col2, ...
  FROM dbo.myTable
)
SELECT myGroup, col1, col2...
FROM myCTE
GROUP BY (myGroup), col1, col2...
;

答案 3 :(得分:1)

您也可以使用 Row_Number() 代替排名。无需楼层。

declare @groupsize int = 50

;with ct1 as (  select YourColumn, RowID = Row_Number() over(order by YourColumn)
                from YourTable
             )

select YourColumn, RowID, GroupID = (RowID-1)/@GroupSize + 1
from ct1

答案 4 :(得分:0)

以上答案实际上并未为每1000条记录分配唯一的组ID。需要添加Floor()。下面的代码将返回表中的所有记录,每1000行具有唯一的GroupID:

WITH T AS (
  SELECT RANK() OVER (ORDER BY your_field) Rank,
    your_field
  FROM your_table
  WHERE your_field = 'your_criteria'
)
SELECT Floor((Rank-1) / 1000) GroupID, your_field
FROM T

出于我的需要,我希望我的GroupID是随机字符集,因此我将Floor(...)GroupID更改为:

TO_HEX(SHA256(CONCAT(CAST(Floor((Rank-1) / 10) AS STRING),'seed1'))) GroupID

没有种子值,您和我将获得完全相同的输出,因为我们只是在数字1、2、3等上执行SHA256。但是添加种子会使输出唯一,但仍可重复。

这是BigQuery语法。 T-SQL可能略有不同。

最后,如果您要保留最后一个不是完整的1000的块,可以通过以下操作找到它:

WITH T AS (
  SELECT RANK() OVER (ORDER BY your_field) Rank,
    your_field
  FROM your_table
  WHERE your_field = 'your_criteria'
)
SELECT Floor((Rank-1) / 1000) GroupID, your_field
, COUNT(*) OVER(PARTITION BY TO_HEX(SHA256(CONCAT(CAST(Floor((Rank-1) / 1000) AS STRING),'seed1')))) AS CountInGroup
FROM T
ORDER BY CountInGroup

答案 5 :(得分:0)

在阅读@user15481328 答案后,我阅读了更多关于 NTILE 的信息 (资源:https://www.sqlservertutorial.net/sql-server-window-functions/sql-server-ntile-function/

这个解决方案让我可以在我的数据集的 25 组中的每组中找到最大日期:

with cte as (
    select date,
           NTILE(25) OVER ( order by date ) bucket_num

    from mybigdataset
)
select max(date), bucket_num
from cte
group by bucket_num
order by bucket_num