【发布时间】:2021-03-09 11:48:30
【问题描述】:
我有下表来监控用户登录到应用程序:
CREATE TABLE [dbo].[userActivity](
[userType] [nchar](10) NULL,
[userInstanceID] [nchar](10) NULL,
[userID] [nchar](10) NULL,
[login] [datetime2](7) NULL
) ON [PRIMARY]
GO
我的数据的一个特殊性是,唯一用户由userType、userInstanceID 和userID 的组合确定。
例如,在下图中,我有三个不同的用户:
- 客户 1 1(红色)
- 员工 1 2(蓝色)
- 客户 2 1(绿色)
我的目标是知道:
- 每个用户登录的次数
- 最近一次登录
- 最早登录
我有一些测试数据:
INSERT [dbo].[userActivity] ([userType], [userInstanceID], [userID], [login]) VALUES (N'customer ', N'1 ', N'1 ', CAST(N'2020-09-17T18:00:07.2492412' AS DateTime2))
GO
INSERT [dbo].[userActivity] ([userType], [userInstanceID], [userID], [login]) VALUES (N'employee ', N'1 ', N'2 ', CAST(N'2020-09-18T09:00:07.2494560' AS DateTime2))
GO
INSERT [dbo].[userActivity] ([userType], [userInstanceID], [userID], [login]) VALUES (N'customer ', N'1 ', N'1 ', CAST(N'2020-08-17T03:00:07.2492412' AS DateTime2))
GO
INSERT [dbo].[userActivity] ([userType], [userInstanceID], [userID], [login]) VALUES (N'customer ', N'2 ', N'1 ', CAST(N'2020-07-23T10:00:07.2492412' AS DateTime2))
GO
INSERT [dbo].[userActivity] ([userType], [userInstanceID], [userID], [login]) VALUES (N'customer ', N'2 ', N'1 ', CAST(N'2020-10-25T11:00:07.2492412' AS DateTime2))
GO
我能够通过以下方式获得我需要的东西:
SELECT DISTINCT userType, userInstanceID, userID, numberOfLogins, MostRecentLogin, oldestLogin FROM (
SELECT userType, userInstanceID, userID,
COUNT(login) OVER(PARTITION BY userType, userInstanceID, userID ORDER BY userType, userInstanceID, userID) AS numberOfLogins,
max(login) OVER(PARTITION BY userType, userInstanceID, userID ORDER BY userType, userInstanceID, userID) AS MostRecentLogin,
min(login) OVER(PARTITION BY userType, userInstanceID, userID ORDER BY userType, userInstanceID, userID) AS oldestLogin
FROM dbo.userActivity) AS summary
我的问题是:这种方法有效吗?我有数百万行和大约 20 列可供每个用户使用。
感谢任何建议。
谢谢!
【问题讨论】:
-
" 这是有效的方法吗?" 不,使用非窗口聚合和
GROUP BY而不是DISTINCT和窗口函数。 -
嗨@Larnu,感谢您的回复!您能否更具体地了解“窗口函数”?
-
它看起来像一个教科书式的例子来介绍
GROUP BY,而不是PARTITION。 -
由于使用了
OVER子句,您上面拥有的是窗口函数@Wilmar。 SELECT - OVER Clause (Transact-SQL)您不想要窗口函数,只是“正常”聚合。 COUNT (Transact-SQL) -
嗨@Damien_The_Unbeliever,感谢您的回复。所以,像这样:
SELECT userType, userInstanceID, userID, count(login) as numberLogin, MAX(login) as MostRecentLogin, MIN(Login) as oldestLogin FROM dbo.userActivity GROUP BY userType, userInstanceID, userID?
标签: sql-server performance tsql distinct partitioning