Bil*_*lly 68 sql t-sql sql-server
我想根据我的db table [member]字段"date_created"获取上个月的记录.
sql是做什么的?
澄清,上个月 - 2009年1月8日至2009年8月31日
如果今天是2010年3月1日,我需要获取2009年1月12日至2009年12月31日的记录.
Dav*_*ker 100
SELECT *
FROM Member
WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate()))
AND DATEPART(yyyy, date_created) = DATEPART(yyyy, DATEADD(m, -1, getdate()))
Run Code Online (Sandbox Code Playgroud)
你需要检查月份和年份.
Clo*_*use 81
所有现有(工作)答案都有两个问题之一:
1.忽略指数:
在大多数情况下,当被搜索的列具有一个被调用的函数(包括隐式,如同CAST
)时,优化器必须忽略列上的索引并搜索每个记录.这是一个简单的例子:
我们正在处理的时间戳,大多数的RDBMS倾向于此信息存储为某种类型的增加值,通常是一个long
或BIGINTEGER
的毫/纳秒数.因此,当前时间看起来像这样存储:
1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
Run Code Online (Sandbox Code Playgroud)
你没有'2014'
在那里看到'年'值(),对吗?事实上,来回翻译需要相当复杂的数学.因此,如果您在搜索列上调用任何提取/日期部分函数,则服务器必须执行所有数学计算,以确定是否可以将其包含在结果中.在小桌子上这不是问题,但随着所选行的百分比减少,这变得越来越大.那么在这种情况下,你第二次做这个问题MONTH
......好吧,你得到了照片.
2.意外数据:
取决于在SQL Server的特定版本,并且列数据类型,使用BETWEEN
(或类似的含上限范围:<=
)可能导致错误的数据被选择.从本质上讲,您最终可能会在"下一天"的午夜包含数据,或者排除"当前"日记录的某些部分.
你应该做什么:
所以我们需要一种对我们的数据安全的方法,并且将使用索引(如果可行).那么正确的方式是:
WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth
Run Code Online (Sandbox Code Playgroud)
鉴于只有一个月,@startOfPreviousMonth
可以很容易地替换/派生:
DATEADD(month, -1, @startOCurrentfMonth)
Run Code Online (Sandbox Code Playgroud)
如果需要在服务器中派生当前月初,可以通过以下方式完成:
DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
Run Code Online (Sandbox Code Playgroud)
这里有一个简短的解释.初始DATEDIFF(...)
将获得当前时代的开始(0001-01-01
- AD,CE,无论如何)之间的差异,基本上返回一个大整数.这是几个月来的开始计数当前的月份.然后我们将这个数字添加到时代的开始,即在给定月份的开始.
所以你的完整脚本可能/看起来应该类似于以下内容:
DECLARE @startOfCurrentMonth DATETIME
SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
SELECT *
FROM Member
WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally misspelled
AND date_created < @startOfCurrentMonth
Run Code Online (Sandbox Code Playgroud)
因此,所有日期操作仅在一个值上执行一次; 优化器可以自由使用索引,并且不会包含不正确的数据.
mrd*_*nny 12
添加到目前为止提供的选项根本不会使用您的索引.
像这样的东西会起作用,并利用表上的索引(如果存在).
DECLARE @StartDate DATETIME, @EndDate DATETIME
SET @StartDate = dateadd(mm, -1, getdate())
SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate)
SET @EndDate = dateadd(mm, 1, @StartDate)
SELECT *
FROM Member
WHERE date_created BETWEEN @StartDate AND @EndDate
Run Code Online (Sandbox Code Playgroud)
小智 10
DECLARE @StartDate DATETIME, @EndDate DATETIME
SET @StartDate = DATEADD(mm, DATEDIFF(mm,0,getdate())-1, 0)
SET @EndDate = DATEADD(mm, 1, @StartDate)
SELECT *
FROM Member
WHERE date_created BETWEEN @StartDate AND @EndDate
Run Code Online (Sandbox Code Playgroud)
升级到mrdenny的解决方案,这样你就可以从YYYY-MM-01上个月获得
上个月视为该月的最后一天。2016 年 1 月 31 日,该月的最后一天是 1 月 31 日,这与过去 30 天不同。
SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
314778 次 |
最近记录: |