簡體   English   中英

按 T-SQL 中的每 N 條記錄分組

[英]Group by every N records in T-SQL

我在數據庫上有一些性能測試結果,我想做的是對每 1000 條記錄進行分組(之前按日期升序排序),然后使用AVG聚合結果。

我實際上正在尋找標准的 SQL 解決方案,但是任何 T-SQL 特定結果也值得贊賞。

查詢如下所示:

SELECT TestId,Throughput  FROM dbo.Results ORDER BY id
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)
;

這樣的事情應該讓你開始。 如果您可以提供您的實際架構,我可以酌情更新。

把答案交給Yuck。 我只發布作為答案,所以我可以包含一個代碼塊。 我做了一個計數測試,看看它是否按 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 

我為@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...
;

您也可以使用 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

上面的答案實際上並沒有為每 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

如果沒有種子值,你和我會得到完全相同的 output 因為我們只是對數字 1、2、3 等進行 SHA256。但是添加種子會使 output 獨一無二,但仍然可以重復。

這是 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

在閱讀@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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM