SQL Server 查询以查找成员注册的年数

标签 sql sql-server sql-server-2008 sql-server-2005

我有 2 个表:

tbmembers

id   name
----------
 1    abc
 2    def
 3    ghi

tbmemberenrollment

id    memberid(foreign key)   startyear    endyear
--------------------------------------------------
 1            1                2007       2009
 2            1                2011       2012
 3            1                2013       2017

tbmemberenrollment 表中,我想计算成员注册到当年的年数,在这种情况下,结果为 6 年(2007、2008、2009、2011、 2012, 2013)

我想通过SQL查询来计算上面的结果,不知道在SQL Server中如何使用for循环,也不知道如何使用游标来得到上面的结果,求助......

最佳答案

假设您的年份可能重叠(2007-2008,然后是 2008-2009),我认为最好的选择是创建一个年份查找表并对其进行查询,如下所示:

SELECT m.id, m.name, COUNT(DISTINCT y.yearfield) YearCount
FROM tblmembers m 
  CROSS JOIN YearLookup Y 
  INNER JOIN tbmemberenrollment me 
    ON m.id = me.memberid 
      AND YEAR(y.yearfield) >= YEAR(me.startyear)
      AND YEAR(y.yearfield) <= YEAR(me.endyear)
AND YEAR(Y.yearField) <= YEAR(GetDate())
GROUP BY m.id, m.name

SQL Fiddle Demo

如果您的数据没有这些重叠的年份,那么您可以这样做来获得结果:

SELECT m.id, m.name, 
  SUM(
    CASE 
      WHEN YEAR(me.endyear) > YEAR(getDate()) 
      THEN YEAR(getDate()) 
      ELSE YEAR(me.endyear) 
    END - YEAR(me.startyear) + 1
    ) totYears
FROM tblmembers m 
  LEFT JOIN tbmemberenrollment me on m.id = me.memberid
WHERE YEAR(me.startyear) <= YEAR(getDate())
GROUP BY  m.id, m.name

SQL Fiddle Demo

编辑:使用递归 CTE 与查找表

虽然我仍然建议使用查找表,但有时这不是一个可行的选择。在这些情况下,您可以使用递归 CTE 完成同样的事情。

WITH years AS (
  SELECT MAX(endyear) maxyear, MIN(startyear) minyear 
  FROM tbmemberenrollment
  ),
RecursiveCTE AS (
  SELECT minyear yearfield
  FROM years
  UNION ALL
  SELECT DATEADD(year, 1, yearfield)
  FROM RecursiveCTE R 
    JOIN years T
      ON R.yearfield < T.maxyear
  )
SELECT m.id, m.name, COUNT(DISTINCT y.yearfield) YearCount
FROM tblmembers m 
  CROSS JOIN RecursiveCTE Y 
  INNER JOIN tbmemberenrollment me 
    ON m.id = me.memberid 
      AND YEAR(y.yearfield) >= YEAR(me.startyear)
      AND YEAR(y.yearfield) <= YEAR(me.endyear)
AND YEAR(Y.yearField) <= YEAR(GetDate())
GROUP BY m.id, m.name

关于SQL Server 查询以查找成员注册的年数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15747677/

相关文章:

sql - 删除字符串的最后一部分 SQL

php - 在日期之间循环并显示每个日期的记录

sql - 选择查询的问题

mysql - 是否可以使用 MySQL 函数恢复字段中字母的顺序以进行排序?

sql-server - 在 Transact 中从字符串安全转换为日期

sql-server - T-SQL 如何转义星号 (*) 字符

c# - 如何在 sql server 中存储 Microsoft Word 文档的格式化片段

xml - 如何合并 SQL Server 中 Xml 字段中的多个项目

sql - 如何在 sql server 2008 中使用 SUBSTRING 和 Distinct

sql - 根据条件计算子表中记录数的最快方法