我在这里尝试了几个主题:How to find missing data rows using SQL?,但我无法在我的情况下使用它。
我在MySQL中有一个名为posts
的表,我每天都会在其中保存用户日记。有时用户忘记写一天的帖子,我想让他们以后再提交。
所以数据库结构如下:
date userid
2011-10-01 1
2011-10-02 1
(missing)
2011-10-04 1
2011-10-05 1
(missing)
2011-10-07 1
所以我想在这个缺失行表中向用户显示缺少日期的下拉列表,这样他就可以选择他想要提交帖子的日期。
我该怎么做? 感谢。
答案 0 :(得分:5)
查找缺少日期的最简单方法是使用日历表。我发布了code to create and populate a calendar table for PostgreSQL;你应该能够毫无困难地适应它。
使用日历表,您的查询非常简单,易于理解。要查找2011年10月的缺失日期,您可以使用这些内容。 (猜猜你的“帖子”表。)
select c.cal_date
from calendar c
left join posts p on (c.cal_date = p.date)
where p.date is null
and c.cal_date between '2011-10-01' and '2011-10-31'
and p.userid = 1
order by c.cal_date
答案 1 :(得分:3)
如果您有日期表,这些类型的查询最容易解决。 在您的数据库中,将此批处理作为一次性运行以创建填充日期表。
DROP PROCEDURE IF EXISTS FillDateTable;
delimiter //
CREATE PROCEDURE FillDateTable()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
drop table if exists datetable;
create table datetable (thedate datetime primary key, isweekday smallint);
SET @x := date('2000-01-01');
REPEAT
insert into datetable (thedate, isweekday) SELECT @x, case when dayofweek(@x) in (1,7) then 0 else 1 end;
SET @x := date_add(@x, interval 1 day);
UNTIL @x >= '2030-12-31' END REPEAT;
END//
delimiter ;
CALL FillDateTable;
然后你可以使用常规LEFT JOIN
SELECT thedate
FROM datetable
LEFT JOIN posts on posts.date = datetable.thedate
WHERE posts.date IS NULL
当然,您不希望2000年到2030年之间的所有“缺失”日期。将其限制在posts表中的MIN和MAX日期(对于用户而言),即
SELECT thedate
FROM datetable
INNER JOIN (select min(date) postStart, max(date) postEnd
FROM posts
where userid=123) p on datetable.thedate BETWEEN p.postStart and p.postEnd
LEFT JOIN posts on posts.date = datetable.thedate
WHERE posts.date IS NULL
答案 2 :(得分:1)
您可以每次(结束日期)自动输入一个空帖子,其中包含空标题,空内容但实际日期。然后,如果用户想要添加前一天的帖子,则显示所有具有空标题和内容的帖子并更新他选择的帖子。
这不应该是一个空间问题,如果他们写的比他们想念的还多。例如,如果他们写了4天而错过了1。
此外,您将运行脚本并删除具有空标题,空内容和早于X天的日期的条目。如果他们没有添加X天的遗失帖子,他们可能永远不会。
如果我的解决方案很简单/过于抽象,我道歉。