按年龄范围选择记录

时间:2017-12-20 08:38:50

标签: sql-server

我有下表

[tblRegistration](
    [FirstName] [nvarchar](100) NOT NULL,
    [MiddleName] [nvarchar](100) NOT NULL,
    [LastName] [nvarchar](100) NOT NULL,
    [DateOfBirth] [date] NOT NULL,
    [DateOfRegistration] [datetime] NOT NULL,

我的问题是:从表格tblRegistration中选择年龄介于18至25岁之间的所有记录。

谢谢!

3 个答案:

答案 0 :(得分:2)

起初我认为DATEDIFF(YEAR, DateOfBirth, GETDATE())足以获得一年的差异,但SQL Server只计算两个年份数的简单int减法,因此当被问及2016.12.31和2017.01.01之间的差异时它返回1

因此,另外,必须完成几个月和几天的计算:

SELECT *
FROM
(
    SELECT
        *,
        Age = DATEDIFF(yy, DateOfBirth, GETDATE()) -
            IIF(DATEPART(m, DateOfBirth) < DATEPART(m, GETDATE()), 0,
            IIF(DATEPART(m, DateOfBirth) > DATEPART(m, GETDATE()), 1,
            IIF(DATEPART(d, DateOfBirth) > DATEPART(d, GETDATE()), 1, 0)))
    FROM tblRegistration
) x
WHERE Age BETWEEN 18 AND 25

答案 1 :(得分:0)

您可以使用以下内容:

SELECT * 
FROM tblRegistration 
WHERE DATEDIFF(yyyy, DateOfBirth, GetDate()) BETWEEN 18 and 25

答案 2 :(得分:0)

最初我认为问题是this question的重复,但后来我意识到OP不想列出年龄;他希望过滤年龄。这种情况需要采用不同的方法。

要过滤当前年龄,请从当前日期减去年数,并将结果与​​出生日期进行比较。

DECLARE @today date = CAST(GETDATE() AS date)
DECLARE @from date = DATEADD(day, 1, DATEADD(year, -26, @today))
DECLARE @upto date = DATEADD(day, 1, DATEADD(year, -18, @today))

SELECT *
FROM tblRegistration
WHERE DateOfBirth >= @from AND DateOfBirth < @upto

无需补偿数天和数月。如果列DateOfBirth恰好是datetime列,其中包含 time 出生(即它忽略了时间,就像大多数人一样),它甚至可以工作。

是的,它适用于闰年。例如,在2018-02-28上运行查询时,它将:

  • 排除1992-02-28出生的人(已经庆祝他们的26岁生日)
  • 包括1992-02-29出生的人(有争议;见https://en.wikipedia.org/wiki/February_29#Born_on_February_29
  • 包括2000-02-28出生的人(庆祝他们的18岁生日)
  • 排除在2000-02-29出生的人(再次,值得商榷,但至少与1992-02-29一致)

如果您更喜欢台湾法律(即2月28日正式上午18岁),请调整DECLARE语句如下。

DECLARE @today date = CAST(GETDATE() AS date)
DECLARE @from date = DATEADD(year, -26, DATEADD(day, 1, @today))
DECLARE @upto date = DATEADD(year, -18, DATEADD(day, 1, @today))

由于DateOfBirth未包含在函数调用中(与DATEDIFF方法一样),查询优化器将能够从列{上的索引中完全受益{1}}。 在以下条件下,这可能会带来显着的性能提升:

  • 您有DateOfBirth的索引,并且此索引可能会在查询计划中使用(如果还有其他WHERE条件和联接,则可能不是这种情况。)
  • 索引键的数量很大。 (对于常规的非过滤索引,此数字等于表中的记录数。)
  • 与索引键的数量相比,返回的行数相对较小。

例如,如果您的表中包含100M行,并且您希望检索其中的1%,那么DateOfBirth方法完成的读取量实际上可能比上面的查询高100倍。这是因为查询优化器无法在DATEDIFF方法中使用索引搜索;它将回退到索引扫描