Sql server “确定最长时间”;条纹“;在SQL Server中?

Sql server “确定最长时间”;条纹“;在SQL Server中?,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我看了其他一些“连胜”问题,但没有什么和我的情况完全一样,因为他们的问题包括连续的ID 我有下面显示的数据,我正试图确定每个用户在没有收到“否”的情况下熟练掌握“是”的时间最长的“一天”。这几天不一定是连续的。每天实际上是一个工作“班次”,所以我想对每个用户说“用户X已经有8个班次没有“否”。” ProficiencyUser ProficiencyDateAdded ProficiencyMet JDOE 2016-04-09 19:35:51.590

我看了其他一些“连胜”问题,但没有什么和我的情况完全一样,因为他们的问题包括连续的ID

我有下面显示的数据,我正试图确定每个用户在没有收到“否”的情况下熟练掌握“是”的时间最长的“一天”。这几天不一定是连续的。每天实际上是一个工作“班次”,所以我想对每个用户说“用户X已经有8个班次没有“否”。”

ProficiencyUser ProficiencyDateAdded       ProficiencyMet
JDOE            2016-04-09 19:35:51.590    Yes
RTHOMPSON       2016-04-09 19:16:42.237    Yes
MMOUSE          2016-04-09 18:59:03.263    Yes
MMOUSE          2016-04-09 18:54:33.210    Yes
MMOUSE          2016-04-09 18:26:55.750    No
MMOUSE          2016-04-06 18:54:33.210    Yes
MMOUSE          2016-03-26 13:54:33.210    Yes
MMOUSE          2016-04-09 18:54:33.210    Yes

我使用的是SQL Server 2008 R2。

在修改后的需求(请参见注释)中,我给出了从今天的日期到每个用户最后一次“否”输入的“连续天数”:


此查询返回每个用户的最长条纹:

;WITH
TestUser AS -- Convert 'Yes'/'No' to int
(
SELECT
    t.[ProficiencyUser]
    ,t.[ProficiencyDateAdded]
    ,ProficiencyMet = CASE WHEN t.[ProficiencyMet] = 'Yes' THEN 1 ELSE 0 END
FROM [Test] t
)
,ByDates AS -- Get Result per Day per User
(
SELECT
    u.[ProficiencyUser]
    ,ProficiencyDate = CAST(u.[ProficiencyDateAdded] AS date)
    ,ProficiencyMet = CASE WHEN COUNT(u.[ProficiencyMet]) = SUM(CAST(u.[ProficiencyMet] as int)) THEN 1 ELSE 0 END
FROM [TestUser] u
GROUP BY [u].[ProficiencyUser], CAST(u.[ProficiencyDateAdded] AS date)
)
,UserDayRank AS -- rank user days
(
SELECT
    Id = RANK() OVER(PARTITION BY [ProficiencyUser] ORDER BY [ProficiencyDate])
    ,[ProficiencyUser]
    ,[ProficiencyDate]
    ,[ProficiencyMet]
FROM [ByDates]
)
,UserSeq AS -- filter user days, and get islands and gaps per user
(
SELECT
    [Id]
    ,[ProficiencyUser]
FROM [UserDayRank]
WHERE [ProficiencyMet] = 1
)
,Islands AS -- number each user's island
(
SELECT
    Id
    ,GroupId = Id - ROW_NUMBER() OVER(PARTITION BY [ProficiencyUser] ORDER BY [Id])
    ,[ProficiencyUser]
FROM [UserSeq]
)
,IslandLen AS -- get length of user's islands
(
SELECT
    L = COUNT([GroupId])
    ,[ProficiencyUser]
FROM [Islands]
GROUP BY [ProficiencyUser], [GroupId]
)
-- finally get the longest user's island for each user
SELECT [ProficiencyUser], L = MAX(L) FROM [IslandLen]
GROUP BY [ProficiencyUser]
ORDER BY MAX(L) DESC, [ProficiencyUser]

用户是否可以在同一天收到两条不同记录的是和否?是-如示例数据所示,用户可以在同一天收到是和否。您是否可以添加一个相对复杂的示例,其中包含一些可能的组合(例如,同一天的是和否,该人休假期间几天内没有数据等)并显示该示例的预期结果?在原始帖子中添加了更多条目。我在想,如果我修改我的要求,计算从今天开始到最后一次“否”的天数,这可能会更容易。将基本上只显示他们的“当前”连胜。在更新的场景中,MMOUSE有2天的连胜(3月26日至4月6日)。然后,MMOUSE连续1天(4月9日)。对吗?我看到的是这样的排序数据:运行此命令输出的用户子集只有用户名列输出(无条纹)更新版本正常工作。所以这里有很多事情要做,我对SQL不是很精通,无法完全理解。显示的“计数”是否为每个用户连续“移位”的计数?我有一个用户的最后一个“否”是在3月19日。使用上面的SQL,他返回“7”。从今天算起减去那个日期,是22天。7代表什么?你能在SqlFiddler中准备一些数据并给我发送一个链接吗?
;WITH
TestUser AS -- Convert 'Yes'/'No' to int
(
SELECT
    t.[ProficiencyUser]
    ,t.[ProficiencyDateAdded]
    ,ProficiencyMet = CASE WHEN t.[ProficiencyMet] = 'Yes' THEN 1 ELSE 0 END
FROM [Test] t
)
,ByDates AS -- Get Result per Day per User
(
SELECT
    u.[ProficiencyUser]
    ,ProficiencyDate = CAST(u.[ProficiencyDateAdded] AS date)
    ,ProficiencyMet = CASE WHEN COUNT(u.[ProficiencyMet]) = SUM(CAST(u.[ProficiencyMet] as int)) THEN 1 ELSE 0 END
FROM [TestUser] u
GROUP BY [u].[ProficiencyUser], CAST(u.[ProficiencyDateAdded] AS date)
)
,UserDayRank AS -- rank user days
(
SELECT
    Id = RANK() OVER(PARTITION BY [ProficiencyUser] ORDER BY [ProficiencyDate])
    ,[ProficiencyUser]
    ,[ProficiencyDate]
    ,[ProficiencyMet]
FROM [ByDates]
)
,UserSeq AS -- filter user days, and get islands and gaps per user
(
SELECT
    [Id]
    ,[ProficiencyUser]
FROM [UserDayRank]
WHERE [ProficiencyMet] = 1
)
,Islands AS -- number each user's island
(
SELECT
    Id
    ,GroupId = Id - ROW_NUMBER() OVER(PARTITION BY [ProficiencyUser] ORDER BY [Id])
    ,[ProficiencyUser]
FROM [UserSeq]
)
,IslandLen AS -- get length of user's islands
(
SELECT
    L = COUNT([GroupId])
    ,[ProficiencyUser]
FROM [Islands]
GROUP BY [ProficiencyUser], [GroupId]
)
-- finally get the longest user's island for each user
SELECT [ProficiencyUser], L = MAX(L) FROM [IslandLen]
GROUP BY [ProficiencyUser]
ORDER BY MAX(L) DESC, [ProficiencyUser]