SQL query to return nil for dates not present in t

2019-08-05 05:48发布

问题:

I have a table 'my_table'. It has the following data :

ID  ---   Date         

1   ---   01/30/2012  
2   ---   01/30/2012   
3   ---   05/30/2012  

I can write a SQL query to return the count of ID's between certain dates, grouped by month, like this :

{"01/30/2012" => 2, "05/30/2012" => 1}

How can I get a result which has all the missing months between the requested dates with value '0', like this :

{"01/30/2012" => 2, "02/30/2012" => 0, "03/30/2012" => 0, "04/30/2012" => 0, "05/30/2012" => 1} 

Thanks in advance.

回答1:

The way I do it is to have a static table with list of all the dates. In your case that's 30th of each month (what about February?). Lets call this table REF_DATE. It has a single column DT that holds the date.

Assuming that my_table only contains 0 or at most 1 distinct date (30th) in each month, what you need to do is:

select DT,count(ID) from 
REF_DT REF 
left outer join my_table MT 
on REF.DT=my_table.DATE
group by REF.DT;


回答2:

I came up with somewhat hackish way through rails

class Month<Date   # for getting months in range
  def succ
    self >> 1
  end
end

range = Month.new(2010,1,1)..Month.new(2013,1,1) # range of date to query
months=Hash.new
(range).each do |month|
  months.merge!({month.to_s => 0}) # get all months as per range requirement of project
end

db_months = MyTable.find_all_by_date(range).group_by{ |u| u.date.beginning_of_month }.map{|m,v| [m.to_s , v.size]} #get all records grouped by months

all_months = months.merge(Hash[db_months]) # merge all missing months

Replace the range with the dates you want also the format of the date as per your requirement.