【问题标题】:wanted to get all dates in mysql result想在 mysql 结果中获取所有日期
【发布时间】:2010-04-16 07:15:15
【问题描述】:

我有一个名为 user(id, name, join_on) 的 mysql 表 join on 是一个日期字段 我想要显示每天创建了多少个用途 我可以使用 group by 但它只会给我日期当用户被添加时 日期

4/12/10  5 users added
4/13/10  2 users added
4/15/10  7 users added

这里缺少 4/14/10 日期,我想列出一个月内的所有日期。 我有一个解决方案,通过创建另一个表仅用于添加日期,该表将在 join_on 上加入我的用户表并给出总结果,但我不想这样做,因为创建我需要创建和添加条目请在日期表中提出不同的方法。

谢谢。

【问题讨论】:

  • +1 我已经在代码中(在 SQL 之外)完成了它,但是看看是否会弹出一些干净的纯 SQL 解决方案非常有趣
  • 这是关于 SO 的常见问题和解答(搜索 date[sql][mysql])。参见,例如,stackoverflow.com/questions/1046865/…
  • @pilcrow:这是一个常见问题,但链接的答案在细节上并不是特别详尽。 @OP:通常这种事情在不支持递归 SQL 的数据库中并不容易;我仍然发布了一些 SQL(有一些问题,但它可能有用)

标签: mysql sql gaps-and-islands


【解决方案1】:

只使用 GROUP BY 然后在您的实际代码中添加缺少的日期可能更简单(或者如果查询结果中缺少日期,则遍历整个日期范围并输出零)。

并非所有事情都必须在 SQL 中解决,许多事情在其他地方更容易解决。 :)

【讨论】:

  • 感谢您的回复,但我只想在 sql 中做,因为我想用它做更多的事情,除此之外我也会学到更多好的东西:)
【解决方案2】:

有一种方法可以在纯 SQL 中做到这一点,但它有局限性。

首先,您需要有一个数字序列 1,2,3...n 作为行(假设 select row from rows 返回)。

然后您可以离开加入并根据最小和最大之间的天数转换为日期。

 select @min_join_on := (select min(join_on) from user);
 select @no_rows := (select datediff(max(join_on), @min_join_on) from user)+1;

会给你所需的行数,然后你可以用它来

 select adddate(@min_join_on, interval row day) from rows where row <= @no_rows;

将返回所需的日期序列,然后您可以对用户表执行左连接。
如果您使用子查询,则可以避免使用变量,为了便于阅读,我将其分解。

现在,问题是表rows 中的行数必须大于@no_rows。 对于 10,000 行,您可以使用长达 27 年的日期范围,对于 100,000 行,您可以使用长达 273 年的日期范围(这感觉真的很糟糕,但恐怕如果您不想使用存储过程它必须看起来和感觉很尴尬)。

因此,如果您可以使用此类固定日期范围,您甚至可以用查询替换表格,例如这个

SELECT @row := @row + 1 as row FROM (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t3, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4, (SELECT @row:=0) r

这将产生从 1 到 10,000 的 10,000 行,并且不会非常低效。

所以最后它在单个查询中是可行的。

create table user(id INT NOT NULL AUTO_INCREMENT, name varchar(100), join_on date, PRIMARY KEY(id));

mysql> select * from user;
+----+-------+------------+
| id | name  | join_on    |
+----+-------+------------+
|  1 | user1 | 2010-04-02 | 
|  2 | user2 | 2010-04-04 | 
|  3 | user3 | 2010-04-08 | 
|  4 | user4 | 2010-04-08 | 
+----+-------+------------+
4 rows in set (0.00 sec)

insert into user values (null, 'user1', '2010-04-02'), (null, 'user2', '2010-04-04'), (null, 'user3', '2010-04-08'), (null, 'user4', '2010-04-08')


SELECT date, count(id)
FROM (
SELECT adddate((select min(join_on) from user), row-1) as date 
FROM ( 
SELECT @row := @row + 1 as row FROM (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2, (SELECT @row:=0) r ) n  
WHERE n.row <= ( select datediff(max(join_on), min(join_on)) from user) + 1
) dr LEFT JOIN user u ON dr.date = u.join_on
GROUP BY dr.date

+------------+-----------+
| date       | count(id) |
+------------+-----------+
| 2010-04-02 |         1 | 
| 2010-04-03 |         0 | 
| 2010-04-04 |         1 | 
| 2010-04-05 |         0 | 
| 2010-04-06 |         0 | 
| 2010-04-07 |         0 | 
| 2010-04-08 |         2 | 
+------------+-----------+
7 rows in set (0.00 sec)

【讨论】:

    【解决方案3】:
    SELECT * FROM TABLE WHERE DATE LIKE '4/%/10'
    

    这将为您提供 2010 年 4 月的所有数据

    同样,您可以通过指定月份的数值来获取任何月份的数据,在这种情况下为 4

    【讨论】:

    • 它不像我只想从范围中获取日期,我还想获取不在我的记录中的所有其他日期
    • 您应该使用日期作为日期,而不是字符串。上面的代码可能会为您提供 4 月份的数据,也可能会为您提供每月 4 日的数据,或者最终可能会出现错误。
    • @PankajK :在这种情况下,您可以根据需要将代码放入您的程序中。可以通过查询来完成,但这会增加执行时间
    猜你喜欢
    • 2017-03-17
    • 1970-01-01
    • 2017-08-21
    • 2012-04-27
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多