我有一个MS SQL Server 2012表,其中包含人员的每日报告。每天包含一个人的最多1条记录,日期存储为DateTime,时间部分设置为“00:00:00.000”。示例:'2014-01-30 00:00:00.000'
+-----------+-------------------------+----------------+
| Person id | Date | Report content |
+-----------+-------------------------+----------------+
| 1 | 2014-01-29 00:00:00.000 | Account stuff |
+-----------+-------------------------+----------------+
| 2 | 2014-01-29 00:00:00.000 | Coaching stuff |
+-----------+-------------------------+----------------+
| 2 | 2014-01-30 00:00:00.000 | Still coaching |
+-----------+-------------------------+----------------+
所有人员都存放在一个单独的表格中。
如何从数据库中选择一段时间内缺少记录的人员?即使该人报告了30份报告,但有1份报告丢失,他也应该参与结果。可能会发生,每个人都错过了一个或多个报告日。这就是为什么我无法将人们相互比较的原因。
例如,我想知道谁在1月1日到2月1日之间没有创建他/她的报告。
答案 0 :(得分:2)
好吧怎么样
DECLARE @StartDate DATETIME = '01 Jan 2014',
@EndDate DATETIME = '01 Feb 2014'
;WITH Dates AS (
SELECT @StartDate RunDate
UNION ALL
SELECT RunDate + 1
FROM Dates
WHERE RunDate + 1 <= @EndDate
)
, PersonIDs AS (
SELECT DISTINCT
PersonID
FROM MyTable
)
, PersonDates AS (
SELECT RunDate,
PersonID
FROM Dates,
PersonIDs
)
SELECT *
FROM PersonDates pd LEFT JOIN
MyTable mt ON pd.RunDate = mt.[Date] AND pd.PersonID = mt.PersonID
WHERE mt.PersonID IS NULL
OPTION (MAXRECURSION 0)
编辑:
就像简短的观点一样。
使用CTE结构,我使用递归性质来生成日期列表。
然后我检索了一个不同的PersonID
s列表(如果你有一个Person
表,它也有帮助,或者一个活动列表,或MustReportList
等)。
之后我们使用笛卡尔积来生成PersonID的日期列表,以便计算所有日期的所有人。
然后我们将join连接到原始表,并使用IS NULL来确定缺少的条目。
最后,OPTION (MAXRECURSION)
是为了确保一旦超过MAX RECURSION LEVEL,我们就不会得到异常(基本上告诉SQL SERVER你知道你在做什么)。
希望有所帮助。
答案 1 :(得分:1)
试试这个:
SELECT DISTINCT PersonID
FROM
[Table] A
WHERE
NOT EXISTS
(
SELECT 1 FROM [Table]
WHERE
[PersonID] = A.[PersonID]
AND TRY_CAST([Date] AS DATE) BETWEEN TRY_CAST('January 1, 2014' AS DATE) AND TRY_CAST('February 1, 2014' AS DATE)
)
答案 2 :(得分:0)
Select personid from your_table not in
(
Select personid from your_table
Where date between start_date and end_date
)