Pregunta

I would like to ask you guys how would you do a query to show the data of this table:

week name   total
==== ====== =====
1    jon     15.2
1    jon     10
1    susan   10
1    howard   9
1    ben     10
3    ben     30
3    susan   10
3    mary    10
5    jon     10
6    howard  12
7    tony    25.1
8    tony     7
8    howard  10
9    susan    6.2
9    howard   9
9    ben     10
11   howard  10
11   howard  10

like this:

week name   total
==== ====== =====
1    ben     10
1    howard   9
1    jon     25.2
1    mary     0
1    susan   10
1    tony     0
3    ben     30
3    howard   0
3    jon      0
3    mary    10
3    susan   10
3    tony     0
5    ben      0
5    howard   0
5    jon     10
5    mary     0
5    susan    0
5    tony     0
6    ben      0
6    howard  12
6    jon      0
6    mary     0
6    susan    0
6    tony     0
7    ben      0
7    howard   0
7    jon      0
7    mary     0
7    susan    0
7    tony    25.1
8    ben      0
8    howard  10
8    jon      0
8    mary     0
8    susan    0
8    tony     7
9    ben     10
9    howard   9
9    jon      0
9    mary     0
9    susan    6.2
9    tony     0
11   ben      0
11   howard  20
11   jon      0
11   mary     0
11   susan    0
11   tony     0

I tried something like:

select t1.week_id ,
       t2.name    ,
       sum(t1.total)
from xpto as t1 ,
     xpto as t2
where t1.week_id = t2.week_id
group by t1.week_id, t2.name
order by t1.week_id, t2.name

But I'm failing to understand the "sum" part and I can't figure out why...

Any help would be very appreciated. Thanks in advance, and sorry for my english.

¿Fue útil?

Solución

you might try something like the following:

select week      = w.week ,
       name      = n.name ,
       sum_total = coalesce( sum( d.total ) , 0 )
from       ( select distinct week from my_table ) w
cross join ( select distinct name from my_table ) n
left  join my_table d on d.week = w.week
                    and  d.name = n.name
group by w.week ,
         n.name
order by 1,2

The cross join of first two derived tables constructs their cartesian product: all week and all names from the table, regardless of whether or not a particular week/name combination exists.

We then take that, join it against the actual data rows and summarize it, using coalesce() to collapse any null results from the aggregate function sum() to 0.

Otros consejos

As I understood you you want to show all weeks and all names across all table regardless whether they were entered for the week or not. To do so you will need to first build a list of all names and week, cross join them and then join them to the list of totals, like this:

;with names as (select distinct name from xpto),
weeks as (select distinct week from xpto),
totals as (select week, name, sum(total) as total 
           from xpto group by week, name)
select w.week, n.name, coalesce(total, 0) as total 
from names n cross join weeks w
left join totals t on t.name=n.name and w.week = t.week
order by 1,2

SQL Fiddle

I've edited my answer because I now understand what you want to do a bit better.

I prefer doing things in several steps rather than trying to do several transformations of data with a single join or subquery. So I would approach this like this:

;
with Weeks as (
  select distinct Week_id 
  from   xpto
)
,    Names as (
  select distinct Name
  from   xpto
)
,    Scores as (
  select  week_id
      ,   name
      ,   score = sum(t1.score)
  from    xpto t1
  group by 
          t1.week_id
      ,   t1.name
)
,   WeeksAndNames as (
  select  week_id
     ,    name
  from    Weeks
     cross join Names
 )
-- The final query!
select  wan.week_id
   ,    wan.name
   ,    total = COALESCE(s.total,0)
from    WeeksAndNames wan
   left join Scores s
       on  wan.week_id = s.week_id
       and wan.name = s.name
order by
       wan.week_id
   ,   wan.name

Lengthy, I'll grant you, and you can probably condense it. But this shows each step you need to go through to transform your data into the list you want.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top