SQL query that returns all dates not used in a table

偶尔善良 提交于 2019-12-18 05:06:27

问题


So lets say I have some records that look like:

2011-01-01 Cat
2011-01-02 Dog
2011-01-04 Horse
2011-01-06 Lion

How can I construct a query that will return 2011-01-03 and 2011-01-05, ie the unused dates. I postdate blogs into the future and I want a query that will show me the days I don't have anything posted yet. It would look from the current date to 2 weeks into the future.

Update:

I am not too excited about building a permanent table of dates. After thinking about it though it seems like the solution might be to make a small stored procedure that creates a temp table. Something like:

CREATE PROCEDURE MISSING_DATES()
BEGIN
    CREATE TABLE TEMPORARY DATES (FUTURE DATETIME NULL)
    INSERT INTO DATES (FUTURE) VALUES (CURDATE())
    INSERT INTO DATES (FUTURE) VALUES (ADDDATE(CURDATE(), INTERVAL 1 DAY))
    ...
    INSERT INTO DATES (FUTURE) VALUES (ADDDATE(CURDATE(), INTERVAL 14 DAY))

    SELECT FUTURE FROM DATES WHERE FUTURE NOT IN (SELECT POSTDATE FROM POSTS)

    DROP TABLE TEMPORARY DATES
END 

I guess it just isn't possible to select the absence of data.


回答1:


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;



回答2:


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)



回答3:


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;



回答4:


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;


来源:https://stackoverflow.com/questions/4559817/sql-query-that-returns-all-dates-not-used-in-a-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!