根据行值获取列的总和

时间:2012-10-26 07:10:04

标签: sql oracle crystal-reports pivot

我的表格如下所示。

EMPNUM  EMPNAME     LOCATION    CATEGORY    COUNT
123     JOHN DOE    BLDG A      1           5
123     JOHN DOE    BLDG A      1           6
123     JOHN DOE    BLDG A      2           4
123     JOHN DOE    BLDG A      3           7
123     JOHN DOE    BLDG B      1           1
123     JOHN DOE    BLDG B      2           3
234     EMILY DOE   BLDG A      1           1
234     EMILY DOE   BLDG A      2           2
234     EMILY DOE   BLDG A      3           4
234     EMILY DOE   BLDG B      2           3
234     EMILY DOE   BLDG B      2           9
234     EMILY DOE   BLDG B      3           3

我想将它传输到列中,这些列将产生类似于下面的输出。我需要根据LOCATION和CATEGORY

的值得到COUNT的总和
EMPNUM  EMPNAME     SUM_A1  SUM_A2  SUM_A3  SUM_B1  SUM_B2  SUM_B3  
123     JOHN DOE    11      4       7       1       3       0
234     EMILY DOE   1       2       4       0       12      3   

有没有办法以SQL查询的方式执行此操作?或者在Crystal报表中(虽然我更喜欢使用SQL输出)

3 个答案:

答案 0 :(得分:3)

如果您使用11g或更高版本,请尝试

select * from table1
PIVOT  (SUM("COUNT")         
        FOR ("LOCATION","CATEGORY") IN 
        (('BLDG A',1) AS sum_a1,
         ('BLDG A',2) AS sum_a2,
         ('BLDG A',3) AS sum_a3,
        ('BLDG B',1) AS sum_b1,
        ('BLDG B',2) AS sum_b2,
        ('BLDG B',3) AS sum_b3));

Here是一个小提琴

否则使用APC's solution

答案 1 :(得分:2)

这将使LOCATION和CATEGORY中的值保持不变:

select empnum
       , empname
       , sum(case when location='BLDG A' and category = 1 then count else 0 end) sum_a1 
       , sum(case when location='BLDG A' and category = 2 then count else 0 end) sum_a2
       , sum(case when location='BLDG A' and category = 3 then count else 0 end) sum_a3
       , sum(case when location='BLDG B' and category = 1 then count else 0 end) sum_b1
       , sum(case when location='BLDG B' and category = 2 then count else 0 end) sum_b2
       , sum(case when location='BLDG B' and category = 3 then count else 0 end) sum_b3
from your_table
group by empnum
       , empname

如果在运行查询时值未知或不稳定,则需要使用动态SQL。


请注意,如果您使用11g,则应使用A B Cade's PIVOT solution,这样会更优雅。

答案 2 :(得分:0)

如果您有一定数量的值可以转换为列,那么其他答案将会很有效。但是如果你有一个未知的数字,那么你可以使用动态的sql来生成结果。

您将创建以下过程:

CREATE OR REPLACE procedure test_dynamic_pivot(p_cursor in out sys_refcursor)
as
    sql_query varchar2(1000) := 'select empnum, empname';

    begin
        for x in (select distinct location, category from yourtable order by 1)
        loop
            sql_query := sql_query ||
              ' , sum(case when location = '''||x.location||''' and category='||x.category||' then cnt else 0 end) as sum_'||substr(x.location, -1, 1)||x.category;

                dbms_output.put_line(sql_query);
        end loop;

        sql_query := sql_query || ' from yourtable group by empnum, empname';

        open p_cursor for sql_query;
    end;
/

然后执行它:

variable x refcursor
exec test_dynamic_pivot(:x)
print x

结果与硬编码版本相同:

| EMPNUM |   EMPNAME | SUM_A1 | SUM_A2 | SUM_A3 | SUM_B1 | SUM_B2 | SUM_B3 |
----------------------------------------------------------------------------
|    234 | EMILY DOE |      1 |      2 |      4 |      0 |     12 |      3 |
|    123 |  JOHN DOE |     11 |      4 |      7 |      1 |      3 |      0 |