2

I have two tables t1, t2 and the following query:

SELECT t2.year,
       Count(t1.id) AS count
FROM   t1,
       t2
WHERE  t2.t1id = t1.id
       AND t2.year IN ( 1995, 1996, 1997, 1998,
                    1999, 2000 )
GROUP  BY t2.year
ORDER  BY t1.year 

Which results in:

+----------+--------+
| year     | count  |
+----------+--------+
|     1995 |      1 |
|     1998 |      3 |
|     1999 |      3 |
|     2000 |     28 |
+----------+--------+

And as you can see some years are missing. Is it possible to rewrite this query such that it results in?

+----------+--------+
| year     | count  |
+----------+--------+
|     1995 |      1 |
|     1996 |      0 |
|     1997 |      0 |
|     1998 |      3 |
|     1999 |      3 |
|     2000 |     28 |
+----------+--------+

I could use php and check which rows are missing to fill in the missing gaps, but that doesn't seem very efficient.. Any ideas?

edit

t1

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| name      | varchar(128) | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

t2

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| t1id      | int(11)      | NO   |     | NULL    |                |
| year      | int(11)      | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

For example:

t1

+----------+---------+
| id       | name    |
+----------+---------+
|        1 |    john |
|        2 |     bob |
|       .. |      .. |
+----------+---------+

t2

+----------+---------+---------+
| id       | t1id    |    year |
+----------+---------+---------+
|      100 |       1 |    1995 |
|      101 |       2 |    1998 |
|      103 |       3 |    1998 |
|       .. |      .. |      .. |  
+----------+---------+---------+

Where after the combination I end up with:

+----------+---------+
| id       |    year |
+----------+---------+
|      100 |    1995 |
|      101 |    1998 |
|      103 |    1998 |
|       .. |      .. |  
+----------+---------+
Community
  • 1
  • 1
dietervdf
  • 400
  • 2
  • 12

4 Answers4

1
SELECT t2.year,
       IF(Count(t1.id) > 0, Count(t1.id), 0)
FROM   t1,
       t2
WHERE  t2.t1id = t1.id
       AND t2.year IN ( 1995, 1996, 1997, 1998,
                    1999, 2000 )
GROUP  BY t2.year
ORDER  BY t1.year 
Mahdyfo
  • 1,155
  • 7
  • 18
1

Without a source of all possible years that your query could cover you are going to have to use php to do this. One approach would could look something like this.

function getCountsForRange(\PDO $dbConn, $startYear, $endYear){
    $ret = array_fill_keys(range($startYear, $endYear), 0);
    $stmt = $dbConn->prepare("SELECT t2.year,Count(t1.id) AS count ".
                             "FROM t1,t2 ".
                             "WHERE  t2.t1id = t1.id AND t2.year between ? and ? ".
                             "GROUP  BY t2.year ORDER  BY t1.year");

    $stmt->execute([$startYear, $endYear]);
    while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)){
        $ret[$row["year"]] = $row["count"];
    }
    return $ret;
}
Orangepill
  • 24,500
  • 3
  • 42
  • 63
0

You will need to handle the empty rows pragmatically or in the query itself depending on the situation.

See:

MySQL GROUP BY and Fill Empty Rows

or

Populating query results with empty rows

For some ideas.

Community
  • 1
  • 1
Rob W
  • 9,134
  • 1
  • 30
  • 50
0
create table yrCheat
(   year int not null
);

create table t1
(   -- forgive lack of PK
    id int not null,
    name varchar(128) not null
);

create table t2
(   -- forgive lack of PK
    id int not null,
    t1id int not null,
    year int not null
);

insert t1(id,name) values (100,'john'),(101,'bob'),(102,'sally');
insert t2(id,t1id,year) values (100,1,1995),(101,2,1998),(101,3,1998),(101,4,1998);
insert into yrCheat (year) values (1990),(1991),(1992),(1993),(1994),(1995),(1996),(1997),(1998),(1999),(2000);
-- etc

select yc.year,count(t1.id) as count
from yrCheat yc
left join t2
on t2.year=yc.year -- and yc.year in (1995,1996,1997,1998,1999,2000)
left join t1
on t1.id=t2.id
where yc.year in (1995,1996,1997,1998,1999,2000)
group by yc.year
order by yc.year

+------+-------+
| year | count |
+------+-------+
| 1995 |     1 |
| 1996 |     0 |
| 1997 |     0 |
| 1998 |     3 |
| 1999 |     0 |
| 2000 |     0 |
+------+-------+
6 rows in set (0.00 sec)
Drew
  • 24,851
  • 10
  • 43
  • 78