0

With this query I can get all entries created during the last week:

SELECT day, COALESCE(ct, 0) AS ct
FROM  (SELECT now::date - d AS day FROM generate_series (0, 6) d) d  -- 6, not 7
  LEFT   JOIN (
     SELECT created_at::date AS day, count(*) AS ct 
     FROM   entries
     WHERE  created_at >= date_trunc('day', now()) - interval '6d'
     GROUP  BY 1
  ) e USING (day);

It returns a result like this one:

 count | date
   2   |  15.01.2014
   0   |  14.01.2014
   1   |  13.01.2014
   0   |  12.01.2014
   0   |  11.01.2014
   0   |  10.01.2014
   9   |  09.01.2014

Now I also want to display all the deleted Entries of last Week! I can get them through the field deleted_at: What I tried was:

SELECT day, COALESCE(ct, 0) AS created, COALESCE(dl,0) AS deleted
FROM  (SELECT current_date - d AS day FROM generate_series (0, 6) d) d  
LEFT   JOIN (
   SELECT created_at::date AS day, 
      count(
        CASE WHEN (created_at >= date_trunc('day', now()) - interval '6d') THEN 1 ELSE 0 END
      ) AS ct,
count(
    CASE WHEN (canceled_at >= date_trunc('day', now()) - interval '6d') THEN 1 ELSE 0 END
) AS dl  
  FROM   entries

   GROUP  BY 1
  ) e USING (day);

But that didn't work! Now I get two rows that are the same:

deleted | created | date
  2     |  2      |  15.01.2014
  0     |  0      |  14.01.2014
  1     |  1      |  13.01.2014
  0     |  0      |  12.01.2014
  0     |  0      |  11.01.2014
  0     |  0      |  10.01.2014
  9     |  9      |  09.01.2014

What do I wrong? How can I display created as well as deleted entries?

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
John Smith
  • 6,105
  • 16
  • 58
  • 109

2 Answers2

1

At first glance it looks like your performing a count function rather than a sum which is what you need, your simply just counting each record twice.

sum( CASE WHEN (created_at >= date_trunc('day', now()) - interval '6d') 
       THEN 1 ELSE 0 END) AS ct,
sum(CASE WHEN (canceled_at >= date_trunc('day', now()) - interval '6d') 
       THEN 1 ELSE 0 END) AS dl  

You need to use sum which will then add all the cases where you case when is returning 1 rather than count which just counts all the values regardless whether they are 1 or 0!

Carl Upton
  • 143
  • 9
1

Since both timestamps can exist 0 - n times in the time frame and independent from each other, you have to do more:

Requires Postgres 9.3+:

WITH var(ts_min) AS (SELECT date_trunc('day', now()) - interval '6 days')
SELECT day
     , COALESCE(c.created, 0) AS created
     , COALESCE(d.deleted, 0) AS deleted
FROM   var v
CROSS  JOIN LATERAL (
   SELECT d::date AS day
   FROM   generate_series (v.ts_min
                         , v.ts_min + interval '6 days'
                         , interval '1 day') d
   ) t
LEFT   JOIN (
   SELECT created_at::date AS day, count(*) AS created
   FROM   entries
   WHERE  created_at >= (SELECT ts_min FROM var)
   GROUP  BY 1
   ) c USING (day)
LEFT   JOIN (
   SELECT canceled_at::date AS day, count(*) AS deleted
   FROM   entries
   WHERE  canceled_at >= (SELECT ts_min FROM var)
   GROUP  BY 1
   ) d USING (day)
ORDER  BY 1;

The CTE var is only for the convenience to provide the starting timestamp once.

SQL Fiddle.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • Sorry but I get a syntax error for `GROUP BY 1` and dont really know how to fix that! Also I am not sure if this query returns me th right results because it makes a `left join` on `created_at` and not `canceled_at` as well! Thanks again for your help! If you can fix that I would rate your answer as correct! Thanks! – John Smith Apr 01 '15 at 10:03
  • 1
    @JohnSmith: The queries were buggy. I provided a completely new, tested version. – Erwin Brandstetter Apr 01 '15 at 12:50