T-SQL中每N条记录分组

T-SQL中每N条记录分组,sql,sql-server,tsql,Sql,Sql Server,Tsql,我在数据库上有一些性能测试结果,我想做的是对每1000条记录进行分组(以前按日期升序排序),然后用平均值对结果进行聚合 事实上,我正在寻找一个标准的SQL解决方案,但是,任何特定于T-SQL的结果都是值得赞赏的 查询如下所示: SELECT TestId,Throughput FROM dbo.Results ORDER BY id 像这样的事情应该会让你开始。如果您能提供您的实际模式,我可以根据需要进行更新。I+1'd@yack,因为我认为这是一个很好的答案。但值得一提的是NTILE()

我在数据库上有一些性能测试结果,我想做的是对每1000条记录进行分组(以前按日期升序排序),然后用平均值对结果进行聚合

事实上,我正在寻找一个标准的SQL解决方案,但是,任何特定于T-SQL的结果都是值得赞赏的

查询如下所示:

SELECT TestId,Throughput  FROM dbo.Results ORDER BY id

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

I+1'd@yack,因为我认为这是一个很好的答案。但值得一提的是NTILE()

原因是,如果您有10010条记录(例如),那么您将有11个分组——第一个10条记录中有1000条,最后一个记录中只有10条

如果你比较每组1000人之间的平均数,那么你要么放弃最后一组,因为它不是一个代表性的组,要么……你可以让所有的组大小相同

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

因此,如果您的表有25250条记录,您将使用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...
;

回答“恶心”。我只发布一个答案,这样我就可以包含一个代码块。我做了一个计数测试,看看它是否按1000分组,第一组是999。这产生了1000套尺寸。太好了,太恶心了

    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 

上面的答案实际上并没有为每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

您还可以使用Row_Number()而不是rank。不需要发言

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

如果你直接使用“恶心”,你可以包含一个count(*),这样至少你知道最后一个组的大小。我已经使用了很多sql功能,但从来没有遇到过这个函数。非常好的例子,有一个很好的用例。感谢您的回答和详细回复。请参阅。函数“将有序分区中的行分配到指定数量的组中。这些组从一开始进行编号。对于每一行,NTILE返回该行所属组的编号”。
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