英文:
Output of data from the entire last month
问题
我们公司使用一个库存工具,它应该在每个月初(即每月的第一天)自动输出上个月的所有库存移动。在这里,我可以通过日期筛选来控制要输出的表格数据。目前我的筛选条件是:“> CURRENT_TIMESTAMP - 31”。因此,会显示过去31天直到今天的所有库存移动。然而,这只有95%的准确度,因为如果我有一个只有30天的月份,或者像2月一样只有28天的月份,我也会包括上个月的最后几天。现在是我的问题。
是否可能设置一个筛选条件或SQL语句,总是只输出上个月的库存移动?例如,如果输出发生在2023年08月01日,那么我希望得到上个月的所有库存移动,即7月份(2023年07月01日 - 2023年07月31日输出)。
不幸的是,我是SQL的新手,所以很难为我找到一个解决方案。
英文:
Briefly the explanation of my problem:
We use an inventory tool in our company, which should automatically output all inventory movements of the last month at the beginning of each month (i.e. on the 1st). Here I can control via a filter on the date, which data of a table should be output. Currently my filter is as follows: "> CURRENT_TIMESTAMP - 31". So all inventory movements of the last 31 days until today are displayed. However, this is unfortunately only 95% correct, because if I have, for example, a month with only 30 days or as in February with even only 28 days, I always take the last days of the month before also. Now to my question.
Is it possible to set a filter or a SQL statement that will always output me only the inventory movements where the month is a month before the current month ? So for example the output takes place on 08/01/2023, then I would like to get all inventory movements from the previous month so July (07/01/2023 - 07/31/2023 output.
Unfortunately I am a newbie in SQL, so it is hard for me to find a solution for this.
答案1
得分: 1
在SQL Server中,current_timestamp返回一个datetime
值,例如2023-07-22 07:53:41.270。这个函数是ANSI SQL中与SQL Server特定的GETDATE()函数等效的函数。
从current_timestamp或getdate()确定"上个月"的开始方法如下:
- 计算从已知数据(这里我们使用零)到现在的月数:
DATEDIFF(MONTH, 0, GETDATE())
- 将这个月数添加到零,然后减去1个月:
DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
- 将相同的月数添加到零,以获得本月的第一天:
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
因此,我们现在可以筛选出在上个月第一天及之后但在本月第一天之前的数据,例如:
-- T-SQL (SQL Server)
SELECT *
FROM your_table
WHERE timestamp_column >= DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
AND timestamp_column < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0);
这个WHERE子句将动态筛选出在上个月内的任何数据,而不考虑所使用的列的日期/时间精度,即它适用于date、smalldatetime、datetime和datetime2。
注: 如果您愿意,您可以使用current_timestamp
代替getdate()
,但我相信您会发现大多数关于类似需求的信息仍然使用SQL Server特定的getdate()函数 - 所以我也采用了这个方式。
要进一步了解这些日期操作,请尝试以下查询:
select
current_timestamp "current timestamp"
, getdate() "getdate"
, DATEDIFF(MONTH, 0, GETDATE()) "months from zero"
, DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) "day 1 last month"
, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) "day 1 this month";
current timestamp | getdate | months from zero | day 1 last month | day 1 this month |
---|---|---|---|---|
2023-07-22 01:07:00.753 | 2023-07-22 01:07:00.753 | 1482 | 2023-06-01 00:00:00.000 | 2023-07-01 00:00:00.000 |
最后一句话。 不要试图使用"between"来筛选日期范围,比如"上个月"。SQL中"between"的问题在于它包括范围的起始点和结束点 - 这可能导致对于位于边界上的任何数据重复计算。最安全的方法是如前所示使用>=
与<
的组合。参见
英文:
In SQL Server current_timestamp returns a datetime
value such as 2023-07-22 07:53:41.270. This function is the ANSI SQL equivalent to
the SQL Server specific GETDATE() function.
A way determine that start of "last month" from current_timestamp, or getdate(), is as follows:
- calculate the months from a known datum (here we use zero)
DATEDIFF(MONTH, 0, GETDATE())
- add that number of months to zero, then deduct 1 month
DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
- add the same number of months to zero for the first day of the current month:
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
So we can now filter for data that is ">= day 1 of last month" and "< day 1 of this month" e.g:
-- T-SQL (SQL Server)
SELECT *
FROM your_table
WHERE timestamp_column >= DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
AND timestamp_column < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0);
This where clause will dynamically filter for any data falling within the prior month regardless of date/time precision of the column used i.e. it will work for date, smalldatetime, datetime and datetime2
nb: If you prefer you can use current_timestamp
instead of getdate()
but I believe you will find most information about similar needs still uses the SQL Server specific getdate() function - so I have followed suit.
To further understand this date manipulations try this query:
select
current_timestamp "current timestamp"
, getdate() "getdate"
, DATEDIFF(MONTH, 0, GETDATE()) "months from zero"
, DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) "day 1 last month"
, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) "day 1 this month"
current timestamp | getdate | months from zero | day 1 last month | day 1 this month |
---|---|---|---|---|
2023-07-22 01:07:00.753 | 2023-07-22 01:07:00.753 | 1482 | 2023-06-01 00:00:00.000 | 2023-07-01 00:00:00.000 |
Final word. Do not be tempted to use "between" when filtering for a date range such as "last month". The problem with "between" in SQL is that it INCLUDES both the start point and the end point of the range - and this potentially leads to double accounting for any data that is ON a border. It is far safer to use the combination of >=
with <
as shown earlier. see
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论