SQL query that returns all dates not used in a table

一曲冷凌霜 提交于 2019-11-29 07:46:34
pilcrow

You're right — SQL does not make it easy to identify missing data. The usual technique is to join your sequence (with gaps) against a complete sequence, and select those elements in the latter sequence without a corresponding partner in your data.

So, @BenHoffstein's suggestion to maintain a permanent date table is a good one.

Short of that, you can dynamically create that date range with an integers table. Assuming the integers table has a column i with numbers at least 0 – 13, and that your table has its date column named datestamp:

   SELECT candidate_date AS missing
     FROM (SELECT CURRENT_DATE + INTERVAL i DAY AS candidate_date
             FROM integers
            WHERE i < 14) AS next_two_weeks
LEFT JOIN my_table ON candidate_date = datestamp
    WHERE datestamp is NULL;

One solution would be to create a separate table with one column to hold all dates from now until eternity (or whenever you expect to stop blogging). For example:

CREATE TABLE Dates (dt DATE);
INSERT INTO Dates VALUES ('2011-01-01');
INSERT INTO Dates VALUES ('2011-01-02');
...etc...
INSERT INTO Dates VALUES ('2099-12-31');

Once this reference table is set up, you can simply outer join to determine the unused dates like so:

SELECT d.dt 
FROM Dates d LEFT JOIN Blogs b ON d.dt = b.dt 
WHERE b.dt IS NULL

If you want to limit the search to two weeks in the future, you could add this to the WHERE clause:

AND d.dt BETWEEN NOW() AND ADDDATE(NOW(), INTERVAL 14 DAY)

The way to extract rows from the mysql database is via SELECT. Thus you cannot select rows that do not exist.

What I would do is fill my blog table with all possible dates (for a year, then repeat the process)

 create table blog (
    thedate date not null,
    thetext text null,
    primary key (thedate));

doing a loop to create all dates entries for 2011 (using a program, eg $mydate is the date you want to insert)

  insert IGNORE into blog (thedate,thetext) values ($mydate, null);

(the IGNORE keyword to not create an error (thedate is a primary key) if thedate exists already).
Then you insert the values normally

  insert into blog (thedate,thetext) values ($mydate, "newtext") 
  on duplicate key update thetext="newtext";

Finally to select empty entries, you just have to

  select thedate from blog where thetext is null;

You probably not going to like this:

select '2011-01-03', count(*) from TABLE where postdate='2011-01-03' 
  having count(*)=0 union
select '2011-01-04', count(*) from TABLE where postdate='2011-01-04' 
  having count(*)=0 union
select '2011-01-05', count(*) from TABLE where postdate='2011-01-05' 
  having count(*)=0 union
... repeat for 2 weeks

OR

create a table with all days in 2011, then do a left join, like

select a.days_2011
from all_days_2011
left join TABLE on a.days_2011=TABLE.postdate
where a.days_2011 between date(now()) and date(date_add(now(), interval 2 week))
and TABLE.postdate is null;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!