有一个类似顶、赞功能的记录表,
id,contentid,userid,goodorbad,crtime
字段说明:id是自增列。contentid,userid是int类型,外键。goodorbad是int,只存0或1,1代表好,0代表不好。crtime是指添加日期,是datetime类型(2014-08-18 14:17:354) 请分别输出最近8小时、今天、24小时以内、本周、最近30天、本月,支持或反对最多的记录,倒序排列。求以上SQL语句,主要是这个日期范围该怎么计算?
id,contentid,userid,goodorbad,crtime
字段说明:id是自增列。contentid,userid是int类型,外键。goodorbad是int,只存0或1,1代表好,0代表不好。crtime是指添加日期,是datetime类型(2014-08-18 14:17:354) 请分别输出最近8小时、今天、24小时以内、本周、最近30天、本月,支持或反对最多的记录,倒序排列。求以上SQL语句,主要是这个日期范围该怎么计算?
WHERE crtime >= DateAdd(hour,-8,GetDate())
--今天
WHERE crtime >= Convert(datetime,
Convert(varchar(10),
GetDate(),
120),
120)
--最近24小时以内
WHERE crtime >= DateAdd(hour,-24,GetDate())
--本周
WHERE DatePart(week,crtime) = DatePart(week,GetDate())
--本月
WHERE crtime >= Convert(datetime,
Convert(varchar(7),
GetDate(),
120)+'-01',
120)
有一个类似顶、赞功能的记录表,
id,contentid,userid,goodorbad,crtime
字段说明:id是自增列。contentid,userid是int类型,外键。goodorbad是int,只存0或1,1代表好,0代表不好。crtime是指添加日期,是datetime类型(2014-08-18 14:17:354) 请分别输出最近8小时、今天、24小时以内、本周、最近30天、本月,支持或反对最多的记录,倒序排列。 求以上SQL语句,主要是这个日期范围该怎么计算?
*/
-- 环境
IF EXISTS(SELECT 1 FROM sys.objects WHERE type='U' AND name='good')
DROP TABLE dbo.good
go
CREATE TABLE dbo.good(id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,contentid INT NOT NULL,userid INT NOT NULL ,
goodorbad bit NOT null,crtime datetime)
go
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 8,1,1,'2014-7-31 20:00:00'
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 8,1,1,'2014-8-1 13:00:00'
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 9,1,0,'2014-8-1 18:09:00'
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 10,1,1,'2014-8-8 20:00:00'
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 10,1,1,'2014-8-11 16:00:00'
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 8,1,1,'2014-8-15 20:00:00'
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 10,1,1,'2014-8-18 10:00:00'
INSERT INTO dbo.good(contentid,userid,goodorbad,crtime)
SELECT 8,1,0,'2014-8-18 11:00:00'
GO
--@goodorbad = 1代表好,@goodorbad =0代表不好
DECLARE @goodorbad BIT
SET @goodorbad = 1
--8小时
SELECT TOP 1 contentid,COUNT(1)count
FROM dbo.good
WHERE crtime BETWEEN DATEADD(HOUR,-8,GETDATE()) AND GETDATE() AND goodorbad = @goodorbad
GROUP BY contentid,goodorbad
ORDER BY count DESC
--24小时
SELECT TOP 1 contentid,COUNT(1)count
FROM dbo.good
WHERE crtime BETWEEN DATEADD(HOUR,-24,GETDATE()) AND GETDATE() AND goodorbad = @goodorbad
GROUP BY contentid,goodorbad
ORDER BY count DESC
--今天
SELECT TOP 1 contentid,COUNT(1)count
FROM dbo.good
WHERE DATEPART(DAY,crtime) =DATEPART(DAY,GETDATE())
AND goodorbad = @goodorbad
GROUP BY contentid,goodorbad
ORDER BY count DESC
--本周
SELECT TOP 1 contentid,COUNT(1)count
FROM dbo.good
WHERE DATEPART(WEEK,crtime) =DATEPART(WEEK,GETDATE())
AND goodorbad = @goodorbad
GROUP BY contentid,goodorbad
ORDER BY count DESC
--最近30天
SELECT TOP 1 contentid,COUNT(1)count
FROM dbo.good
WHERE crtime BETWEEN DATEADD(DAY,-30,GETDATE()) AND GETDATE() AND goodorbad = @goodorbad
GROUP BY contentid,goodorbad
ORDER BY count DESC
--本月
SELECT TOP 1 contentid,COUNT(1)count
FROM dbo.good
WHERE DATEPART(MONTH,crtime) =DATEPART(MONTH,GETDATE())
AND goodorbad = @goodorbad
GROUP BY contentid,goodorbad
ORDER BY count DESC
DATEADD (Transact-SQL) 发送反馈
请参阅
全部折叠全部展开 语言筛选器: 全部语言筛选器: 多个语言筛选器: Visual Basic语言筛选器: C#语言筛选器: C++语言筛选器: J#语言筛选器: JScript
Visual Basic(声明)
C#
C++
J#
JScript将指定 number 时间间隔(有符号整数)与指定 date 的指定 datepart 相加后,返回该 date。有关所有 Transact-SQL 日期和时间数据类型及函数的概述,请参阅日期和时间数据类型及函数 (Transact-SQL)。有关日期和时间数据类型及函数共有的信息和示例,请参阅使用日期和时间数据。主题链接图标 Transact-SQL 语法约定语法
DATEADD (datepart , number , date )
参数
datepart
是与 integer number 相加的 date 部分。下表列出了所有有效的 datepart 参数。用户定义的变量等效项是无效的。datepart 缩写
year
yy, yyyy
quarter
qq, q
month
mm, m
dayofyear
dy, y
day
dd, d
week
wk, ww
weekday
dw, w
hour
hh
minute
mi, n
second
ss, s
millisecond
ms
microsecond
mcs
nanosecond
ns
number
是一个表达式,可以解析为与 date 的 datepart 相加的 int。用户定义的变量是有效的。如果您指定一个带小数的值,则将小数截去且不进行舍入。date
是一个表达式,可以解析为 time、date、smalldatetime、datetime、datetime2 或 datetimeoffset 值。date 可以是表达式、列表达式、用户定义的变量或字符串文字。如果表达式是字符串文字,则它必须解析为一个 datetime 值。为避免不确定性,请使用四位数年份。有关两位数年份的信息,请参阅 two digit year cutoff 选项。返回类型
返回数据类型为 date 参数的数据类型,字符串文字除外。字符串文字的返回数据类型为 datetime。如果字符串文字的秒数小数位数超过三位 (.nnn) 或包含时区偏移量部分,将引发错误。返回值
datepart 参数
dayofyear、day 和 weekday 返回相同的值。每个 datepart 及其缩写都返回相同的值。如果 datepart 为 month 且 date 月份比返回月份的天数多,因而 date 中的日在返回月份中不存在,则返回返回月份的最后一天。例如,9 月份有 30 天;因此,下面两个语句返回 2006-09-30 00:00:00.000:SELECT DATEADD(month, 1, '2006-08-30') SELECT DATEADD(month, 1, '2006-08-31') number 参数
number 参数不能超出 int 的范围。在下面的语句中,number 的参数超出 int 范围 1。将返回如下错误消息:“将表达式转换为数据类型 int 时出现算术溢出错误。” 复制代码
SELECT DATEADD(year,2147483648, '2006-07-31');
SELECT DATEADD(year,-2147483649, '2006-07-31');
date 参数
date 参数不能增加至其数据范围之外的值。在下面的语句中,与 date 值相加的 number 值超出了 date 数据类型的范围。将返回如下错误消息:“将值添加到 'datetime' 列导致溢出。” 复制代码
SELECT DATEADD(year,2147483647, '2006-07-31');
SELECT DATEADD(year,-2147483647, '2006-07-31');
date 为 smalldatetime 型、datepart 为秒或秒小数部分时的返回值
smalldatetime 值的秒数部分始终为 00。如果 date 的数据类型为 smalldatetime,则适用以下准则:如果 datepart 为 second 且 number 介于 -30 和 +29 之间,则不执行加法。
如果 datepart 为 second 且 number 小于 -30 或大于 +29,则以一分钟为起值执行加法。
如果 datepart 为 millisecond 且 number 介于 -30001 和 +29998 之间,则不执行加法。
如果 datepart 为 millisecond 且 number 小于 -30001 或大于 +29998,则以一分钟为起值执行加法。注释
DATEADD 可用在 SELECT <list>、WHERE、HAVING、GROUP BY 和 ORDER BY 子句中。秒的小数部分精度
不允许将日期部分 microsecond 或 nanosecond 与数据类型为 smalldatetime、date 和 datetime 的 date 相加。毫秒的小数位数为 3 (.123)。微秒的小数位数为 6 (.123456)。纳秒的小数位数为 9 (.123456789)。time、datetime2 和 datetimeoffset 数据类型的最大小数位数为 7 (.1234567)。如果 datepart 为 nanosecond,则 number 必须为 100 才能使 date 的秒小数部分增加。介于 1 和 49 之间的 number 向下舍入为 0,介于 50 和 99 之间的 number 向上舍入为 100。以下语句加的 datepart 为 millisecond、microsecond 或 nanosecond。 复制代码
DECLARE @datetime2 datetime2 = '2007-01-01 13:10:10.1111111'
SELECT '1 millisecond' ,DATEADD(millisecond,1,@datetime2)
UNION ALL
SELECT '2 milliseconds', DATEADD(millisecond,2,@datetime2)
UNION ALL
SELECT '1 microsecond', DATEADD(microsecond,1,@datetime2)
UNION ALL
SELECT '2 microseconds', DATEADD(microsecond,2,@datetime2)
UNION ALL
SELECT '49 nanoseconds', DATEADD(nanosecond,49,@datetime2)
UNION ALL
SELECT '50 nanoseconds', DATEADD(nanosecond,50,@datetime2)
UNION ALL
SELECT '150 nanoseconds', DATEADD(nanosecond,150,@datetime2);
/*
Returns:
1 millisecond 2007-01-01 13:10:10.1121111
2 milliseconds 2007-01-01 13:10:10.1131111
1 microsecond 2007-01-01 13:10:10.1111121
2 microseconds 2007-01-01 13:10:10.1111131
49 nanoseconds 2007-01-01 13:10:10.1111111
50 nanoseconds 2007-01-01 13:10:10.1111112
150 nanoseconds 2007-01-01 13:10:10.1111113
*/
时区偏移量
不允许对时区偏移量执行加法。示例
A. 以 1 为增量递增 datepart
下面的每条语句以 1 为增量递增 datepart。 复制代码
DECLARE @datetime2 datetime2 = '2007-01-01 13:10:10.1111111'
SELECT 'year', DATEADD(year,1,@datetime2)
UNION ALL
SELECT 'quarter',DATEADD(quarter,1,@datetime2)
UNION ALL
SELECT 'month',DATEADD(month,1,@datetime2)
UNION ALL
SELECT 'dayofyear',DATEADD(dayofyear,1,@datetime2)
UNION ALL
SELECT 'day',DATEADD(day,1,@datetime2)
UNION ALL
SELECT 'week',DATEADD(week,1,@datetime2)
UNION ALL
SELECT 'weekday',DATEADD(weekday,1,@datetime2)
UNION ALL
SELECT 'hour',DATEADD(hour,1,@datetime2)
UNION ALL
SELECT 'minute',DATEADD(minute,1,@datetime2)
UNION ALL
SELECT 'second',DATEADD(second,1,@datetime2)
UNION ALL
SELECT 'millisecond',DATEADD(millisecond,1,@datetime2)
UNION ALL
SELECT 'microsecond',DATEADD(microsecond,1,@datetime2)
UNION ALL
SELECT 'nanosecond',DATEADD(nanosecond,1,@datetime2);
/*
Year 2008-01-01 13:10:10.1111111
quarter 2007-04-01 13:10:10.1111111
month 2007-02-01 13:10:10.1111111
dayofyear 2007-01-02 13:10:10.1111111
day 2007-01-02 13:10:10.1111111
week 2007-01-08 13:10:10.1111111
weekday 2007-01-02 13:10:10.1111111
hour 2007-01-01 14:10:10.1111111
minute 2007-01-01 13:11:10.1111111
second 2007-01-01 13:10:11.1111111
millisecond 2007-01-01 13:10:10.1121111
microsecond 2007-01-01 13:10:10.1111121
nanosecond 2007-01-01 13:10:10.1111111
*/
B. 在一条语句中将 datepart 增加一级以上
下面的每条语句将 datepart 与一个足够大的 number 相加,使得 date 的上一级 datepart 也增大。 复制代码
DECLARE @datetime2 datetime2;
SET @datetime2 = '2007-01-01 01:01:01.1111111';
--Statement Result
-------------------------------------------------------------------
SELECT DATEADD(quarter,4,@datetime2); --2008-01-01 01:01:01.110
SELECT DATEADD(month,13,@datetime2); --2008-02-01 01:01:01.110
SELECT DATEADD(dayofyear,365,@datetime2); --2008-01-01 01:01:01.110
SELECT DATEADD(day,365,@datetime2); --2008-01-01 01:01:01.110
SELECT DATEADD(week,5,@datetime2); --2007-02-05 01:01:01.110
SELECT DATEADD(weekday,31,@datetime2); --2007-02-01 01:01:01.110
SELECT DATEADD(hour,23,@datetime2); --2007-01-02 00:01:01.110
SELECT DATEADD(minute,59,@datetime2); --2007-01-01 02:00:01.110
SELECT DATEADD(second,59,@datetime2); --2007-01-01 01:02:00.110
SELECT DATEADD(millisecond,1,@datetime2); --2007-01-01 01:01:01.110
C. 使用表达式作为 number 和 date 形参的实参
以下示例使用不同类型的表达式作为 number 和 date 形参的实参。将列指定为 date
下例将每个 OrderDate 加上 2 天以计算新的 PromisedShipDate。 复制代码
USE AdventureWorks2008R2;
GO
SELECT SalesOrderID
,OrderDate
,DATEADD(day,2,OrderDate) AS PromisedShipDate
FROM Sales.SalesOrderHeader;
将用户定义的变量指定为 number 和 date
下例将用户定义的变量指定为 number 和 date 的参数。 复制代码
DECLARE @days int;
DECLARE @datetime datetime;
SET @days = 365;
SET @datetime = '2000-01-01 01:01:01.111'; /* 2000 was a leap year */
SELECT DATEADD(day, @days, @datetime);
将标量系统函数指定为 date
下例指定 SYSDATETIME 用作 date。 复制代码
SELECT DATEADD(month, 1, SYSDATETIME());
将标量子查询和标量函数指定为 number 和 date
下例将标量子查询和标量函数 MAX(ModifiedDate) 用作 number 和 date 的参数。(SELECT TOP 1 BusinessEntityID FROM Person.Person) 是 number 形参的假实参,用来说明如何从值列表中选择 number 实参。 复制代码
USE AdventureWorks2008R2;
GO
SELECT DATEADD(month,(SELECT TOP 1 BusinessEntityID FROM Person.Person),
(SELECT MAX(ModifiedDate) FROM Person.Person));
将常量指定为 number 和 date
下例将数值和字符常量用作 number 和 date 的参数。SELECT DATEADD(minute, 1, ' 2007-05-07 09:53:01.0376635');将数值表达式和标量系统函数指定为 number 和 date
下例将数值表达式 (-(10/2))、一元运算符 (-)、算术运算符 (/) 和标量系统函数 (SYSDATETIME) 用作 number 和 date 的参数。 复制代码
SELECT DATEADD(month,-(10/2), SYSDATETIME());
将排名函数指定为 number
下例将排名函数用作 number 的参数。 复制代码
USE AdventureWorks2008R2;
GO
SELECT p.FirstName, p.LastName
,DATEADD(day,ROW_NUMBER() OVER (ORDER BY
a.PostalCode),SYSDATETIME()) AS 'Row Number'
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
AND SalesYTD <> 0;
将聚合开窗函数指定为 number
下例将聚合开窗函数用作 number 的参数。 复制代码
USE AdventureWorks2008R2;
GO
SELECT SalesOrderID, ProductID, OrderQty
,DATEADD(day,SUM(OrderQty)
OVER(PARTITION BY SalesOrderID),SYSDATETIME()) AS 'Total'
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664);
GO