MSSQL:从 Session 出勤数据中识别群组
MSSQL: identify Cohorts from Session Attendance data
我有按主题划分的 session 组出席率数据,其中一行是一个用户在给定的 date/time 上参加 session。一组产品可以有一定数量的 session,例如10,它们通常在同一时间 (StartTime) 和星期几 (DayOfWeek) 提供。
我想确定团体发售的开始和结束日期,即给定群组的第一个 session 和最后一个 session。群组将从参加群组 session 的相同用户列表中确定。
Table: ---GroupSessions---
GroupSessionDate UserID Topic StartTime DayOfWeek ArrivalStatus
Jan-08-2015 1 A 11:30:00 AM Thursday Arrived
Jan-08-2015 2 A 11:30:00 AM Thursday Arrived
Jan-08-2015 3 A 11:30:00 AM Thursday Arrived
Jan-08-2015 4 A 11:30:00 AM Thursday Arrived
Jan-15-2015 1 A 11:30:00 AM Thursday Arrived
Jan-15-2015 2 A 11:30:00 AM Thursday Arrived
Jan-15-2015 3 A 11:30:00 AM Thursday Arrived
Jan-15-2015 4 A 11:30:00 AM Thursday Arrived
Jan-22-2015 1 A 11:30:00 AM Thursday Arrived
Jan-22-2015 2 A 11:30:00 AM Thursday Arrived
Jan-22-2015 3 A 11:30:00 AM Thursday Arrived
Jan-22-2015 4 A 11:30:00 AM Thursday Missed
May-15-2015 5 A 09:00:00 AM Friday Arrived
May-15-2015 2 A 09:00:00 AM Friday Arrived
May-15-2015 6 A 09:00:00 AM Friday Arrived
May-22-2015 5 A 09:00:00 AM Friday Arrived
May-22-2015 6 A 09:00:00 AM Friday Arrived
May-22-2015 2 A 09:00:00 AM Friday Missed
May-29-2015 5 A 09:00:00 AM Friday Arrived
May-29-2015 6 A 09:00:00 AM Friday Arrived
May-29-2015 2 A 09:00:00 AM Friday Missed
在上面的示例中,有 2 个同类群组。同类群组 1 将由用户 1、2、3 和 4 组成,几乎所有人都在 2015 年 1 月 8 日至 2015 年 1 月 22 日期间参加了小组课程(主题 A)。参加 Jan-15-2015 session 和 Jan-08-2015 session 的用户相同,几乎所有人都参加了 Jan-22-2015 session。
同类群组 2(也针对主题 A)由用户 2、5、6 组成,发售日期为 2015 年 5 月 15 日至 29 日。
session 的数量不是按产品设置的,因为它会根据需求而变化,所以我无法考虑从产品日期开始的 session 的数量。
我看过 Oracle/SQL: Split two inter-related lists into independent cohorts
但问题仍未得到解答。
通常我会进行视觉检查并将用户分配到同类群组,但我有数万行,并且希望有一种更有效的方法来使用 SQL 来完成这项工作。我是 运行 女士 SQL 2014.
我已经尝试将 OUTER APPLY 与 table 一起使用,但我并没有真正得到我想要的结果。
你能给我指明正确的方向吗?
SQL:
</p>
<pre><code>SELECT src.UserID
,src.GroupSessionDate
,src.StartTime
,src.DayofWeek
,src.Topic
,prevsessdata.GroupSessionDate
FROM GroupSessions src OUTER APPLY
(SELECT TOP 1 * GroupSessions prevsd WHERE src.Topic=prevsd.Topic
AND src.UserID=prevsd.UserID AND src.DayOfWeek=prevsd.DayOfWeek
AND src.StartTime=prevsd.StartTime
AND prevsd.GroupSessionDate<src.GroupSessionDate) prevsessdata
编辑:
可以做出的假设:
- session通常间隔 1 周(节假日除外)
- 同一群组中的所有 session 将有相同的主题,在一周的同一天和相同的开始时间
- 用户可以停止参加,但他们会在他们错过的 session 中列出 -(抱歉,我错过了原始问题中的这个关键细节!)
- 虽然用户可以参加多个主题的群组,但通常会为所有 session 群组产品列出相同的用户,因此在某些情况下,用户可能也会被列为另一个群组的一部分(此处用户 2 参加了 1 月和 5 月的发售)。但这仅限于 10-12 人中的 1 或 2 个用户。
期望的输出:
对于每个主题、开始时间和 DoW,列出队列 Start/End 日期。
谢谢!
我想你正在寻找这样的东西:
; WITH T AS (
SELECT CONVERT(DATE, REPLACE(GroupSessionDate, '-', ' ')) GroupSessionDate, Topic, StartTime, [DayOfWeek]
, STUFF((SELECT ', ' + CONVERT(NVARCHAR, UserID)
FROM GroupSessions
WHERE GroupSessionDate = G.GroupSessionDate
AND Topic = G.Topic
AND StartTime = G.StartTime
AND [DayOfWeek] = G.[DayOfWeek]
ORDER BY UserID
FOR XML PATH ('')), 1, 2, '') [Cohort]
FROM GroupSessions G
GROUP BY GroupSessionDate, Topic, StartTime, [DayOfWeek])
SELECT Cohort, MIN(GroupSessionDate) SessionStartDate, MAX(GroupSessionDate) SessionEndDate, Topic, StartTime, [DayOfWeek]
FROM T
GROUP BY Topic, StartTime, [DayOfWeek], Cohort, DATEDIFF(dd, 0, GroupSessionDate) % 7
ORDER BY MIN(GroupSessionDate)
一个简单的group by语句。确实,从您的要求来看,您需要做的就是按主题、开始时间、星期几和 groupsessiondate 分组以找到每个 "cohort" 然后再次对其进行排序以找到每个的最小/最大日期这些。
如果这没有产生正确的结果,您可能需要使用其他一些标准来进一步缩小范围。
我有按主题划分的 session 组出席率数据,其中一行是一个用户在给定的 date/time 上参加 session。一组产品可以有一定数量的 session,例如10,它们通常在同一时间 (StartTime) 和星期几 (DayOfWeek) 提供。
我想确定团体发售的开始和结束日期,即给定群组的第一个 session 和最后一个 session。群组将从参加群组 session 的相同用户列表中确定。
Table: ---GroupSessions---
GroupSessionDate UserID Topic StartTime DayOfWeek ArrivalStatus
Jan-08-2015 1 A 11:30:00 AM Thursday Arrived
Jan-08-2015 2 A 11:30:00 AM Thursday Arrived
Jan-08-2015 3 A 11:30:00 AM Thursday Arrived
Jan-08-2015 4 A 11:30:00 AM Thursday Arrived
Jan-15-2015 1 A 11:30:00 AM Thursday Arrived
Jan-15-2015 2 A 11:30:00 AM Thursday Arrived
Jan-15-2015 3 A 11:30:00 AM Thursday Arrived
Jan-15-2015 4 A 11:30:00 AM Thursday Arrived
Jan-22-2015 1 A 11:30:00 AM Thursday Arrived
Jan-22-2015 2 A 11:30:00 AM Thursday Arrived
Jan-22-2015 3 A 11:30:00 AM Thursday Arrived
Jan-22-2015 4 A 11:30:00 AM Thursday Missed
May-15-2015 5 A 09:00:00 AM Friday Arrived
May-15-2015 2 A 09:00:00 AM Friday Arrived
May-15-2015 6 A 09:00:00 AM Friday Arrived
May-22-2015 5 A 09:00:00 AM Friday Arrived
May-22-2015 6 A 09:00:00 AM Friday Arrived
May-22-2015 2 A 09:00:00 AM Friday Missed
May-29-2015 5 A 09:00:00 AM Friday Arrived
May-29-2015 6 A 09:00:00 AM Friday Arrived
May-29-2015 2 A 09:00:00 AM Friday Missed
在上面的示例中,有 2 个同类群组。同类群组 1 将由用户 1、2、3 和 4 组成,几乎所有人都在 2015 年 1 月 8 日至 2015 年 1 月 22 日期间参加了小组课程(主题 A)。参加 Jan-15-2015 session 和 Jan-08-2015 session 的用户相同,几乎所有人都参加了 Jan-22-2015 session。
同类群组 2(也针对主题 A)由用户 2、5、6 组成,发售日期为 2015 年 5 月 15 日至 29 日。
session 的数量不是按产品设置的,因为它会根据需求而变化,所以我无法考虑从产品日期开始的 session 的数量。
我看过 Oracle/SQL: Split two inter-related lists into independent cohorts 但问题仍未得到解答。
通常我会进行视觉检查并将用户分配到同类群组,但我有数万行,并且希望有一种更有效的方法来使用 SQL 来完成这项工作。我是 运行 女士 SQL 2014.
我已经尝试将 OUTER APPLY 与 table 一起使用,但我并没有真正得到我想要的结果。
你能给我指明正确的方向吗?
SQL:
</p>
<pre><code>SELECT src.UserID
,src.GroupSessionDate
,src.StartTime
,src.DayofWeek
,src.Topic
,prevsessdata.GroupSessionDate
FROM GroupSessions src OUTER APPLY
(SELECT TOP 1 * GroupSessions prevsd WHERE src.Topic=prevsd.Topic
AND src.UserID=prevsd.UserID AND src.DayOfWeek=prevsd.DayOfWeek
AND src.StartTime=prevsd.StartTime
AND prevsd.GroupSessionDate<src.GroupSessionDate) prevsessdata
编辑: 可以做出的假设:
- session通常间隔 1 周(节假日除外)
- 同一群组中的所有 session 将有相同的主题,在一周的同一天和相同的开始时间
- 用户可以停止参加,但他们会在他们错过的 session 中列出 -(抱歉,我错过了原始问题中的这个关键细节!)
- 虽然用户可以参加多个主题的群组,但通常会为所有 session 群组产品列出相同的用户,因此在某些情况下,用户可能也会被列为另一个群组的一部分(此处用户 2 参加了 1 月和 5 月的发售)。但这仅限于 10-12 人中的 1 或 2 个用户。
期望的输出: 对于每个主题、开始时间和 DoW,列出队列 Start/End 日期。
谢谢!
我想你正在寻找这样的东西:
; WITH T AS (
SELECT CONVERT(DATE, REPLACE(GroupSessionDate, '-', ' ')) GroupSessionDate, Topic, StartTime, [DayOfWeek]
, STUFF((SELECT ', ' + CONVERT(NVARCHAR, UserID)
FROM GroupSessions
WHERE GroupSessionDate = G.GroupSessionDate
AND Topic = G.Topic
AND StartTime = G.StartTime
AND [DayOfWeek] = G.[DayOfWeek]
ORDER BY UserID
FOR XML PATH ('')), 1, 2, '') [Cohort]
FROM GroupSessions G
GROUP BY GroupSessionDate, Topic, StartTime, [DayOfWeek])
SELECT Cohort, MIN(GroupSessionDate) SessionStartDate, MAX(GroupSessionDate) SessionEndDate, Topic, StartTime, [DayOfWeek]
FROM T
GROUP BY Topic, StartTime, [DayOfWeek], Cohort, DATEDIFF(dd, 0, GroupSessionDate) % 7
ORDER BY MIN(GroupSessionDate)
一个简单的group by语句。确实,从您的要求来看,您需要做的就是按主题、开始时间、星期几和 groupsessiondate 分组以找到每个 "cohort" 然后再次对其进行排序以找到每个的最小/最大日期这些。
如果这没有产生正确的结果,您可能需要使用其他一些标准来进一步缩小范围。