4

我已经尝试过几个类似这样的主题:如何使用 SQL 查找丢失的数据行?在这里,但我无法让它在我的情况下工作。

我有一个posts在 MySQL 中命名的表,我每天都在其中保存用户日记。有时用户会忘记写一天的帖子,我想让他们稍后再提交。所以数据库结构是这样的:

date           userid
2011-10-01     1
2011-10-02     1
(missing)
2011-10-04     1
2011-10-05     1
(missing)
2011-10-07     1

所以我想在这个缺失行的表格中向用户显示一个缺失日期的下拉列表,这样他就可以选择他想要提交帖子的日期。

我怎样才能做到这一点?谢谢。

4

4 回答 4

5

查找缺失日期的最简单方法是使用日历表。我已经发布了为 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
于 2011-04-02T11:05:59.480 回答
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 年的所有“缺失”日期。将其限制为帖子表中的 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
于 2011-04-02T11:08:37.393 回答
1

您可以每次(一天结束)自动输入一个空标题,空内容但实际日期的空帖子。然后,如果用户想要添加前一天的帖子,则显示所有标题和内容为空的帖子并更新他选择的帖子。

这不应该是空间问题,如果他们写的比他们错过的多的话。例如,如果他们写了 4 天却错过了 1 天。

此外,您将运行一个脚本并删除具有空标题、空内容和日期早于 X 天的条目。如果他们 X 天没有添加丢失的帖子,他们可能永远不会添加。

如果我的解决方案微不足道/过于抽象,我深表歉意。

于 2011-04-02T11:08:50.577 回答
0
select  
    t0.date,
    t1.date1
    if(t1.date1 is null, date_add(t0.date, interval 1 day), '') missing_date
from
(select date from posts group by date) t0
left join
(select date_add(date, interval 1 day) date1 from posts group by date) t1
on t0.date = t1.date1
order by t0.date asc

您可以通过这种方式找到丢失的日期。请注意,您需要删除最后一行,您可以选择一种适合您的方式来实现。

于 2021-08-31T09:26:23.390 回答