具有相同类别的SUM行,直到总和为1

时间:2018-02-09 15:18:57

标签: sql sql-server

我尝试进行查询,当相同类别的值为1时,总计列总和。

实施例

|---------------------|------------------|------------------|------------------|
|      categoria      |    categoria 2   |       valor      |       Total      |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |        0.2       |        20        |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |        0.2       |        42        |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |        0.2       |        46        |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |        0.2       |        23        |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |        0.2       |         6        |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |        0.7       |        30        |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |        0.3       |        30        |
|---------------------|------------------|------------------|------------------|
|          b          |         c        |        0.6       |        80        |
|---------------------|------------------|------------------|------------------|
|          c          |         b        |        0.4       |        54        |
|---------------------|------------------|------------------|------------------|
|          c          |         b        |        0.6       |        23        |
|---------------------|------------------|------------------|------------------|

我想要的是什么

|---------------------|------------------|------------------|------------------|
|      categoria      |    categoria 2   |       valor      |       Total      |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |         1        |        137       |
|---------------------|------------------|------------------|------------------|
|          a          |         a        |         1        |        60        |
|---------------------|------------------|------------------|------------------|
|          c          |         b        |         1        |        77        |
|---------------------|------------------|------------------|------------------|

可以是多行但值最大为1 我正在使用像这样的

SELECT DISTINCT
  c.category,
  c.category2,
  sum(c.value),
  sum(c.total)
FROM dbo.categoryTable
GROUP BY c.category, category2
HAVING sum(c.value) >= 1

2 个答案:

答案 0 :(得分:0)

正如我在评论中已经简要介绍的那样,我将尝试在此处给出一个更明确的答案。

您的主要问题是需求定义不明确。 假设你有一堆像

这样的行
1. a, a, 0.1, 0.1
2. a, a, 0.2, 0.2
3. a, a, 0.3, 0.3
4. a, a, 0.4, 0.4
5. a, a, 0.5, 0.5
6. a, a, 0.6, 0.6
7. a, a, 0.7, 0.7
8. a, a, 0.8, 0.8
9. a, a, 0.9, 0.9

如果你想要

,现在没有定义
1+9, 2+8, 3+7, 4+6:
a, a, 1, 1 -- 4 times

1+2+3+4:
a, a, 1, 1 -- 1 time

2+3+5, 4+6, 1+9:
a, a, 1, 1 -- 3 times

1+3+6, 2+8:
a, a, 1, 1 -- 2 times

找到总和达到某个值的一组数字的所有子集相对比较困难。然后找到不相交的子集,以便使用原始集的最大元素数。

从SQL这样的语言中提问有点多。

答案 1 :(得分:0)

这可以帮助你。只需几个小时,您就可以提高效率。这是相当混乱的,但是,我今天没时间调整它。

注意,使用LEAD()LAG()可能会将此缩小一点,但是,我的笔记本电脑仍在运行2008.

DECLARE @T TABLE
(
    Categoria NVARCHAR(10),
    Categoria2 NVARCHAR(10),
    Valor DECIMAL(18,2),
    Total INT
)
INSERT @T SELECT 'a','a',0.2,20
INSERT @T SELECT 'a','a',0.2,42
INSERT @T SELECT 'a','a',0.2,46
INSERT @T SELECT 'a','a',0.2,23
INSERT @T SELECT 'a','a',0.2,6
INSERT @T SELECT 'a','a',0.7,30
INSERT @T SELECT 'a','a',0.3,30
INSERT @T SELECT 'b','c',0.6,80
INSERT @T SELECT 'c','b',0.4,54
INSERT @T SELECT 'c','b',0.6,23

;
WITH GetRowNumber AS
(   
    SELECT
        This.Categoria,This.Categoria2,Valor,Total,
        RowNumber = ROW_NUMBER() OVER (ORDER BY This.categoria, This.Categoria2)
    FROM
        @T This
        INNER JOIN
        (
            SELECT Categoria,Categoria2,SumValor=SUM(Valor)
            FROM @T     
            GROUP BY Categoria,Categoria2
            HAVING SUM(Valor) >=1
        )AS That ON That.Categoria=This.Categoria AND That.Categoria2=This.Categoria2
),
 RunningSum AS
(
    SELECT
        RowNumber= This.RowNumber,
        SumValor = SUM(That.Valor)
    FROM
        GetRowNumber This
        LEFT OUTER JOIN GetRowNumber That ON This.RowNumber > That.RowNumber
    GROUP BY
        This.Categoria,This.Categoria2,This.Valor,This.Total,This.RowNumber
),
BoundryMarkersNoGrouped AS
(
    SELECT 
        RowNumber=This.RowNumber,
        Boundry=FLOOR(That.SumValor + This.Valor)
    FROM 
        GetRowNumber This
        LEFT OUTER JOIN RunningSum That ON This.RowNumber = That.RowNUmber
    WHERE
        FLOOR(That.SumValor + This.Valor) > 0
),
BoundryMarkers AS
(
    SELECT
        Boundry, 
        BoundryRowNumber = MIN(RowNUmber)
    FROM 
        BoundryMarkersNoGrouped 
    GROUP BY
        Boundry
),
LowHigh AS
(
    SELECT 
        HighBoundry = This.BoundryRowNumber,
        LowBoundry = COALESCE( MAX(That.BoundryRowNumber) +1 , 1)
    FROM 
        BoundryMarkers This
        LEFT OUTER JOIN BoundryMarkers That ON That.Boundry < This.Boundry
    GROUP BY
        This.BoundryRowNumber   
)

SELECT
    Categoria,
    Categoria2,
    Valor=SUM(Valor),
    Total=SUM(Total)
FROM
    GetRowNumber D  
    LEFT OUTER JOIN LowHigh ON D.RowNumber BETWEEN LowHigh.LowBoundry AND LowHigh.HighBoundry
GROUP BY
    Categoria,
    Categoria2,
    LowHigh.LowBoundry