如何在T-SQL中以分层格式有效地分组数据?

时间:2010-01-06 22:28:23

标签: sql sql-server sql-server-2005 tsql

我有这样的数据:

Task   | Hours
1.1    |    40
2      |    40
2.1    |    60
2.1.1  |    15
15.9   |    24
16     |     5
19.1   |    40
19.1.1 |     8
19.1.2 |    12
19.2   |     6
19.2.1 |    21
19.2.2 |    15
19.2.3 |     2
19.3   |    64

我想根据任务的前两个级别进行分组,产生这个结果:

Task   | Hours
1.1    |    40
2      |    40
2.1    |    75
15.9   |    24
16     |     5
19.1   |    60
19.2   |    44
19.3   |    64

我希望16不要卷起它下面的东西,但是我需要所有其他级别来卷起来。这是SQL Server 2005.我通常会对小数进行拆分,然后将其分解,但我想知道在SQL中是否有更好的方法。

4 个答案:

答案 0 :(得分:2)

更改模型是一个选项吗?如果您的任务列真的要表示层次结构,那么您应该在关系模型中正确地表示层次结构。

如果深度级别固定为3,则另一个选项可能是添加三列来独立地表示任务列的每个“部分”。

如果那不是一个选项,我认为你可以通过一系列解析字符串的CASE语句(加上SUM和GROUP BY)来实现这一点。

更新:

好的,这似乎是一个有趣的挑战,所以我提出了这个:

SELECT
    main_task,
    SUM(hours)
FROM
    (
    SELECT      
        task,
        CASE 
            WHEN 
                LEN(task) + 1 - CHARINDEX('.', REVERSE(task)) = CHARINDEX ('.', task) THEN task
                ELSE LEFT(task, LEN(task) + 1 - CHARINDEX('.', REVERSE(task)) - 1)
            END main_task,
        hours
    FROM 
        #temp
    ) sub
GROUP BY 
      main_task

答案 1 :(得分:1)

假设字段任务的结构是一致的,您可以使用以下

select left(task,4) as Task,sum(hours) as Hours
from table
group by left(task,4)

这是一个稍微修改过的版本

select LEFT(task,charindex('.',task+'.')+1),SUM(hours)
from test1
group by LEFT(task,charindex('.',task+'.')+1)

答案 2 :(得分:1)

另一种方法是添加一些计算列,将各个任务级别分开,然后根据需要进行分组和求和。

答案 3 :(得分:1)

我在开车回家的时候想到了这个问题,我想提出这个解决方案:

创建一个存储层次结构的表,然后执行连接以获取任务的父级。

TaskStructureTable:

task  | task_group
1     | 1
1.1   | 1.1
1.1.1 | 1.1
1.1.2 | 1.1
1.1.3 | 1.1
1.2   | 1.2
1.2.1 | 1.2

然后我可以这样做:

SELECT SUM(d.Hours) AS "Hours", t.task_group
FROM Data d
JOIN TaskStructureTable t ON d.Task = t.task

认为这会比执行CHARINDEX更快? (是的,我可以测量并确切知道)