想要获取 mysql 结果中的所有日期

发布于 2024-08-29 06:45:53 字数 371 浏览 6 评论 0原文

我有一个名为 user(id, name, join_on) 的 mysql 表,join on 是一个日期字段,我想要的是显示每天创建了多少个用户,我可以使用 group by 但它只会给我用户获取时的日期添加就像如果 此处缺少 2010 年 4 月 14 日日期

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

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

谢谢。

I have mysql table called user(id, name, join_on) join on is a date field what I want is to show in each day how many uses has been created I can use group by but it will only give me the dates when users get added like if
date

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

here date 4/14/10 is missing and I want listing of all dates in one month.
I have one solution for it by creating another table only for adding date and that table will left join my users table on join_on and will give total result but I don't want to do that as for creating that I need to create and add entries in date table please suggest the different approach for doing so.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

骄傲 2024-09-05 06:45:53

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

并不是所有事情都必须在 SQL 中解决,而且很多事情在其他地方更容易解决。 :)

It might be simpler to just use GROUP BY and then in your actual code add in the missing dates (or iterate through the entire date range and output a zero if the date is missing from the query results).

Not everything has to be solved in SQL, and many things are easier to solve elsewhere. :)

如梦 2024-09-05 06:45:53

有一种方法可以在纯 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)

There is an approach that can do this in pure SQL but it has limitations.

First you need to have a number sequence 1,2,3...n as rows (assume select row from rows return that).

Then you can left join on this and convert to dates based on number of days between min and max.

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

will give you the required number of rows, which then you can use to

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

will return a required sequence of dates on which then you can do a left join back to the users table.
Using variables can be avoided if you use sub queries, I broke it down for readability.

Now, the problem is that the number of rows in table rows has to be bigger then @no_rows.
For 10,000 rows you can work with date ranges of up to 27 years, with 100,000 rows you can work with date ranges of up to 273 years (this feels really bad, but I am afraid that if you don't want to use stored procedures it will have to look and feel awkward).

So, if you can work with such fixed date ranges you can even substitute the table with the query, such as this

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

which will produce 10,000 rows going from 1 to 10,000 and it will not be terribly inefficient at it.

So at the end it is doable in a single query.

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)
只有影子陪我不离不弃 2024-09-05 06:45:53
SELECT * FROM TABLE WHERE DATE LIKE '4/%/10'

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

同样,您可以通过指定月份的数值(本例中为 4)来获取任何月份的数据

SELECT * FROM TABLE WHERE DATE LIKE '4/%/10'

This will give u all data for the month of april 2010

Similarly u can get any month's data by specifying month's numeric value ie 4 in this case

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文