Question

Hi am having an SQL problem, and I hope the answer is pretty easy.

I have a database with the following structure.

State      Gender     birthyear     birthname      count
-----      ------     ---------     ---------     ------
AK          F           1923          Helen         15
AK          F           1926          Helen         35
AK          F           1927          Susan         25
AK          F           1920          Helen         15

There are thousands of records and I would like the output to look like this:

birthname   1910        1911          1912      -->2012
-----      ------     ---------     ---------     ------
Helen          5         6             12           800

Using MS Access I was able to get some results with this:

SELECT DISTINCT as1.birthname AS Expr1,

 (select totalcount from  AK as2 where as1.birthname=as2.birthname and as1.gender=as2.gender and as1.state=as2.state and as1.birthyear=as2.birthyear and birthyear=1910) as 1910,
 (select totalcount from  AK as2 where as1.birthname=as2.birthname and as1.gender=as2.gender and as1.state=as2.state and as1.birthyear=as2.birthyear and birthyear=1911) as 1911,

 (select totalcount from  AK as2 where as1.birthname=as2.birthname and as1.gender=as2.gender and as1.state=as2.state and as1.birthyear=as2.birthyear and birthyear=2012) as 2012

FROM AK AS as1
Was it helpful?

Solution

You should do this using conditional aggregation:

SELECT as1.birthname AS Expr1,
       SUM(case when birthyear = 1910 then `count` else 0 end) as yr_1910,
       SUM(case when birthyear = 1911 then `count` else 0 end) as yr_1911,
       SUM(case when birthyear = 1912 then `count` else 0 end) as yr_1912
FROM AK AS as1
GROUP BY as1.birthname;

I am not sure where gender and state come in. These are not included in the outer query, which is probably the cause of your syntax error. You might want to include these in the aggregation:

SELECT as1.birthname, as1.gender, as1.state,
       SUM(case when birthyear = 1910 then `count` else 0 end) as yr_1910,
       SUM(case when birthyear = 1911 then `count` else 0 end) as yr_1911,
       SUM(case when birthyear = 1912 then `count` else 0 end) as yr_1912
FROM AK AS as1
GROUP BY as1.birthname, as1.gender, as1.state;

OTHER TIPS

If you are using Oracle 11g+ you can use the SQL PIVOT syntax to generate a crosstab report. With sample data the query would be something like this:

with sample_data as
    (select 'AK' state, 'F' gender, 1923 birthyear, 'Helen' birthname, 15 namecount from dual union all
    select 'AK', 'F', 1926, 'Helen', 35 from dual union all
    select 'AK', 'F', 1927, 'Susan', 25 from dual union all
    select 'AK', 'F', 1920, 'Helen', 15 from dual)

select * from (
  select * from sample_data
  )
  pivot
  (
    sum(namecount)
    for birthyear in (1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1230)
  );

Unfortunately the list of years in the IN clause must be hardcoded, you cannot generate that list dynamically with a subquery. However, that should be not be too hard to initially populate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top