2017-09-25 35 views
0

我有以下结果集。SQL dense_rank()按组和计数

Tmp_Table 
Tag | Code | Rel 
A  ABC 1 
A  ABC 1 
A  ABC 1 
A  ABC 1 
B  XYZ 1 
B  XYZ 1 
B  XYZ 1 
B  XYZ 1 
B  XYZ 1 
C  QWE 1 
C  QWE 1 
C  QWE 1 
D  EFG 1 

的要求是:

  1. 集团通过标签记录,并添加组ID为每个组。
  2. 每个组不应该超过4个记录/行
  3. 应该将分组数超过4的记录分成不同的组。

我试着用dense_rank()来创建每个记录的简单增量。

SELECT DENSE_RANK() OVER(Order By Tag)groupID, * FROM Tmp_Table 

这里是当前结果集。

groupID | Tag | Code | Rel 
1   A  ABC 1 
1   A  ABC 1 
1   A  ABC 1 
1   A  ABC 1 
2   B  XYZ 1 
2   B  XYZ 1 
2   B  XYZ 1 
2   B  XYZ 1 
2   B  XYZ 1 
3   C  QWE 1 
3   C  QWE 1 
3   C  QWE 1 
4   D  EFG 1 

预期结果。

groupID | Tag | Code | Rel 
1   A  ABC 1 
1   A  ABC 1 
1   A  ABC 1 
1   A  ABC 1 
2   B  XYZ 1 
2   B  XYZ 1 
2   B  XYZ 1 
2   B  XYZ 1 
3   B  XYZ 1 
4   C  QWE 1 
4   C  QWE 1 
4   C  QWE 1 
5   D  EFG 1 

我也用row_number() over (partition by Tag order by Tag)只为每个标签的增量尝试。

groupID | Tag | Code | Rel 
1   A  ABC 1 
2   A  ABC 1 
3   A  ABC 1 
4   A  ABC 1 
1   B  XYZ 1 
2   B  XYZ 1 
3   B  XYZ 1 
4   B  XYZ 1 
5   B  XYZ 1 
... 

肯定缺少重要的东西。任何想法将非常感激!

回答

0

实际上,您应该在行中确定一些定义的特征,以确保顺序是正确的(并且通常情况下,重复数据没有任何特别的行独特性是多余的),但没有这些,这里是一个这样你可以用的窗函数(假设SQL Server的2012+)的组合做到这一点:

DECLARE @T TABLE (Tag CHAR(1), Code CHAR(3), Rel INT); 
INSERT @T VALUES 
('A', 'ABC', 1), 
('A', 'ABC', 1), 
('A', 'ABC', 1), 
('A', 'ABC', 1), 
('B', 'XYZ', 1), 
('B', 'XYZ', 1), 
('B', 'XYZ', 1), 
('B', 'XYZ', 1), 
('B', 'XYZ', 1), 
('C', 'QWE', 1), 
('C', 'QWE', 1), 
('C', 'QWE', 1), 
('D', 'EFG', 1); 

SELECT GroupID = SUM(RN2) OVER (ORDER BY RN1), Tag, Code, Rel 
FROM 
(
    SELECT *, RN2 = CASE WHEN ROW_NUMBER() OVER (PARTITION BY Tag ORDER BY RN1) % 4 = 1 THEN 1 ELSE 0 END 
    FROM (
     SELECT *, RN1 = ROW_NUMBER() OVER (ORDER BY Tag) 
     FROM @T 
    ) AS T 
) AS T; 
0

这里的另一种选择......

IF OBJECT_ID('tempdb..#tmp_table', 'U') IS NOT NULL 
DROP TABLE #tmp_table; 

CREATE TABLE #tmp_table (
    Tag CHAR(1), 
    Code CHAR(3), 
    Rel TINYINT 
    ); 
INSERT #tmp_table (Tag, Code, Rel) VALUES 
    ('A', 'ABC', 1), 
    ('A', 'ABC', 1), 
    ('A', 'ABC', 1), 
    ('A', 'ABC', 1), 
    ('B', 'XYZ', 1), 
    ('B', 'XYZ', 1), 
    ('B', 'XYZ', 1), 
    ('B', 'XYZ', 1), 
    ('B', 'XYZ', 1), 
    ('C', 'QWE', 1), 
    ('C', 'QWE', 1), 
    ('C', 'QWE', 1), 
    ('D', 'EFG', 1); 

--============================================= 

WITH 
    cte_AddRN AS (
     SELECT 
      tt.Tag, tt.Code, tt.Rel, 
      RN = ROW_NUMBER() OVER (PARTITION BY tt.Tag ORDER BY (SELECT NULL)) 
     FROM 
      #tmp_table tt 
     ) 
SELECT 
    GroupID = DENSE_RANK() OVER (ORDER BY gv.GroupVal), 
    ar.Tag, ar.Code, ar.Rel 
FROM 
    cte_AddRN ar 
    CROSS APPLY (VALUES (ISNULL(NULLIF(ar.RN, 0), 4))) r (RN) 
    CROSS APPLY (VALUES (ISNULL(NULLIF(r.RN % 4, 0), 4))) m (ModRN) 
    CROSS APPLY (VALUES (ar.Tag + CAST(r.RN - m.ModRN AS VARCHAR(10)))) gv (GroupVal); 

结果...

GroupID    Tag Code Rel 
-------------------- ---- ---- ---- 
1     A ABC 1 
1     A ABC 1 
1     A ABC 1 
1     A ABC 1 
2     B XYZ 1 
2     B XYZ 1 
2     B XYZ 1 
2     B XYZ 1 
3     B XYZ 1 
4     C QWE 1 
4     C QWE 1 
4     C QWE 1 
5     D EFG 1 
0

我的#tmp_table包含您提供的数据。解决方案如下:

我添加到标签1记录超过四个,所以然后在此标签上,您可以直接应用dense_rank()

select GroupID = dense_rank() over (order by OverFour), tag, code, rel from (
    select case when rn < 5 then tag + '0' else tag + '1' end as OverFour, 
      tag, code, rel 
    from (
     select rn = row_number() over (partition by tag order by tag), 
     tag, code, rel 
     from #tmp_table 
    ) as a 
) as b