准备测试数据
为了提供不同时间粒度示例的演示,就需要测试数据。为了演示方便,本文提供一个测试数据表(登录信息数据表----LoginInfo),以及改变插入测试数据。该测试数据表就是简单记录每个用户每次的登路时间信息。
LoginInfo创建的脚本的T-SQL代码如下:
IF OBJECT_ID(N'dbo.LoginInfo', 'U') IS NOT NULL
BEGIN
DROP TABLE dbo.LoginInfo;
END
GO
CREATE TABLE dbo.LoginInfo (
LoginInfoID INT IDENTITY(1, 1) NOT NULL,
UserID INT NOT NULL,
LoginTime DATETIME NOT NULL
);
GO
IF OBJECT_ID(N'PK_U_CL_LoginInfo_LoginInfoID', N'PK') IS NULL
BEGIN
ALTER TABLE [dbo].[LoginInfo] ADD CONSTRAINT [PK_U_CL_LoginInfo_LoginInfoID] PRIMARY KEY CLUSTERED
(
[LoginInfoID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
ON [PRIMARY];
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[LoginInfo]', N'U') AND name = N'IX_U_NCL_LoginInfo_LoginTime_UserID')
BEGIN
CREATE NONCLUSTERED INDEX [IX_U_NCL_LoginInfo_LoginTime_UserID] ON [dbo].[LoginInfo]
(
[LoginTime] ASC,
[UserID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
ON [PRIMARY];
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[LoginInfo]', N'U') AND name = N'IX_NU_NCL_LoginInfo_UserID')
BEGIN
CREATE NONCLUSTERED INDEX [IX_NU_NCL_LoginInfo_UserID] ON [dbo].[LoginInfo]
(
[UserID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
ON [PRIMARY];
END
GO
向LoginInfo数据表插入测试数据的T-SQL脚本如下:
-- 方法1、 模拟100个用户在2015年登陆时间的信息记录
TRUNCATE TABLE dbo.LoginInfo;
GO
DECLARE
@intUserTotal AS INT,
@dtmStartDateTime AS DATETIME,
@dtmEndDateTime AS DATETIME;
SELECT
@intUserTotal = 100,
@dtmStartDateTime = '2015-01-01',
@dtmEndDateTime = '2015-12-31';
-- 插入数据
INSERT INTO dbo.LoginInfo (
UserID
,LoginTime
) SELECT
T.Num AS UserID
,T2.LoginTime
FROM dbo.ufn_GetNums(1, @intUserTotal) AS T
CROSS APPLY (
SELECT CONVERT(DATETIME, CONVERT(VARCHAR(14), DATEADD(HOUR, Num * 4, @dtmStartDateTime), 120) + CAST(dbo.ufn_RandNum(0,59) AS VARCHAR(2)) + ':'+ CAST(dbo.ufn_RandNum(0,59) AS VARCHAR(2)) + '.'+ CAST(dbo.ufn_RandNum(0,997) AS VARCHAR(3)), 120) AS LoginTime
FROM dbo.ufn_GetNums(0, DATEDIFF(HOUR, @dtmStartDateTime, @dtmEndDateTime) / 4)
) AS T2
ORDER BY T2.LoginTime ASC, T.Num ASC;
GO
-- 方法2、 模拟1000个用户在2015年登陆时间的信息记录
TRUNCATE TABLE dbo.LoginInfo;
GO
DECLARE
@intUserTotal AS INT,
@dtmStartDateTime AS DATETIME,
@dtmEndDateTime AS DATETIME;
SELECT
@intUserTotal = 1000,
@dtmStartDateTime = '2015-01-01',
@dtmEndDateTime = '2015-12-31';
SELECT
T.Num AS UserID
,T2.LoginTime
FROM dbo.ufn_GetNums(1, @intUserTotal) AS T
CROSS APPLY (
SELECT CONVERT(DATETIME, CONVERT(VARCHAR(14), DATEADD(HOUR, Num * 4, @dtmStartDateTime), 120) + CAST(dbo.ufn_RandNum(0,59) AS VARCHAR(2)) + ':'+ CAST(dbo.ufn_RandNum(0,59) AS VARCHAR(2)) + '.'+ CAST(dbo.ufn_RandNum(0,997) AS VARCHAR(3)), 120) AS LoginTime
FROM dbo.ufn_GetNums(0, DATEDIFF(HOUR, @dtmStartDateTime, @dtmEndDateTime) / 4)
) AS T2;
GO
注意:
1、以上填充测试数据提供了两个方法:一个是模拟100个用户的小数据,另一个是模拟1000个用户的稍大数据,时间段都是2015年的登录时间。
2、本文为了演示的方便采用了模拟100个用户的小数据。
查看测试数据表中的数据,如下图:
注意:
1、以上截图仅仅显示很小部分的数据。
向测试数据表添加相关时间粒度字段列
向测试数据表中增加LoginDays、LoginMonths、LoginQuarters和LoginYears字段列,T-SQL脚本如下:
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.LoginInfo', 'U') AND name = N'LoginDays')
BEGIN
ALTER TABLE LoginInfo ADD LoginDays INT NOT NULL CONSTRAINT DF_LoginInfo_LoginDays DEFAULT 0;
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.LoginInfo', 'U') AND name = N'LoginMonths')
BEGIN
ALTER TABLE LoginInfo ADD LoginMonths INT NOT NULL CONSTRAINT DF_LoginInfo_LoginMonths DEFAULT 0;
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.LoginInfo', 'U') AND name = N'LoginQuarters')
BEGIN
ALTER TABLE LoginInfo ADD LoginQuarters INT NOT NULL CONSTRAINT DF_LoginInfo_LoginQuarters DEFAULT 0;
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.LoginInfo', 'U') AND name = N'LoginYears')
BEGIN
ALTER TABLE LoginInfo ADD LoginYears SMALLINT NOT NULL CONSTRAINT DF_LoginInfo_LoginYears DEFAULT 0;
END
GO
查询测试数据表,如下图:
注意:
1、以上截图的仅仅显示部分数据。
修改新增字段值,相关的脚本如下:
UPDATE dbo.LoginInfo
SET LoginDays = dbo.ufn_Days(LoginTime)
,LoginMonths = dbo.ufn_Months(LoginTime)
,LoginQuarters = dbo.ufn_Quarters(LoginTime)
,LoginYears = dbo.ufn_Years(LoginTime)
WHERE LoginDays = 0
AND LoginMonths = 0
AND LoginQuarters = 0
AND LoginYears = 0;
GO
注意:
1、以上新增的字段没有创建相应的索引。
再次查看测试数据,如下图:
基于日月季年统计汇总的演示
基于日统计汇总,T-SQL如下:
-- 基于日统计汇总
-- 方法1、传统的使用
SELECT CONVERT(CHAR(10), LoginTime, 120) AS LoginDayDateFormat, COUNT(1) AS DayLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY CONVERT(CHAR(10), LoginTime, 120)
ORDER BY LoginDayDateFormat ASC;
GO
-- 方法2、使用时间粒度转换函数
SELECT dbo.ufn_Days2Date(dbo.ufn_Days(LoginTime)) AS LoginDayDate, COUNT(1) AS DayLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY dbo.ufn_Days(LoginTime)
ORDER BY LoginDayDate ASC;
GO
-- 方法3、使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Days2Date(LoginDays) AS LoginDayDate, COUNT(1) AS DayLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginDays
ORDER BY LoginDays ASC;
GO
-- 方法4、嵌套查询与使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Days2Date(T.LoginDays) AS LoginDayDate, T.DayLoginTimesTotal
FROM (
SELECT LoginDays, COUNT(1) AS DayLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginDays
) AS T
ORDER BY LoginDays ASC;
GO
查询以上四个方法的图形实际执行计划,如下图:
基于月统计汇总,T-SQL如下:
-- 基于月统计汇总
-- 方法1、传统的使用
SELECT CONVERT(CHAR(7), LoginTime, 120) AS LoginMonthDateFormat, COUNT(1) AS MonthLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY CONVERT(CHAR(7), LoginTime, 120)
ORDER BY LoginMonthDateFormat ASC;
GO
-- 方法2、使用时间粒度转换函数
SELECT dbo.ufn_Months2Date(dbo.ufn_Months(LoginTime)) AS LoginMonthBasedate, COUNT(1) AS MonthLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY dbo.ufn_Months(LoginTime)
ORDER BY LoginMonthBasedate ASC;
GO
-- 方法3、使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Months2Date(LoginMonths) AS LoginMonthBasedate, COUNT(1) AS MonthLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginMonths
ORDER BY LoginMonths ASC;
GO
-- 方法4、嵌套查询与使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Months2Date(T.LoginMonths) AS LoginMonthBasedate, T.MonthLoginTimesTotal
FROM (
SELECT LoginMonths, COUNT(1) AS MonthLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginMonths
) AS T
ORDER BY LoginMonths ASC;
GO
查询以上四个方法的图形实际执行计划,如下图:
基于季统计汇总,T-SQL如下:
-- 基于季统计汇总
-- 方法1、传统的使用
SELECT CONVERT(CHAR(4), LoginTime, 120) + '0' + CAST(DATEPART(QUARTER, LoginTime) AS CHAR(1)) AS LoginQuarterDateFormat, COUNT(1) AS QuarterLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY CONVERT(CHAR(4), LoginTime, 120) + '0' + CAST(DATEPART(QUARTER, LoginTime) AS CHAR(1))
ORDER BY LoginQuarterDateFormat ASC;
GO
-- 方法2、使用时间粒度转换函数
SELECT dbo.ufn_Quarters2Date(dbo.ufn_Quarters(LoginTime)) AS LoginQuarterBasedate, COUNT(1) AS QuarterLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY dbo.ufn_Quarters(LoginTime)
ORDER BY LoginQuarterBasedate ASC;
GO
-- 方法3、使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Quarters2Date(LoginQuarters) AS LoginQuarterBasedate, COUNT(1) AS QuarterLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginQuarters
ORDER BY LoginQuarters ASC;
GO
-- 方法4、嵌套查询与使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Quarters2Date(T.LoginQuarters) AS LoginQuarterBasedate, T.QuarterLoginTimesTotal
FROM (
SELECT LoginQuarters, COUNT(1) AS QuarterLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginQuarters
) AS T
ORDER BY LoginQuarters ASC;
GO
查询以上四个方法的图形实际执行计划,如下图:
基于年统计汇总,T-SQL如下:
-- 基于年统计汇总
-- 方法1、传统的使用
SELECT CONVERT(CHAR(4), LoginTime, 120) AS LoginYearDateFormat, COUNT(1) AS YearLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY CONVERT(CHAR(4), LoginTime, 120)
ORDER BY LoginYearDateFormat ASC;
GO
-- 方法2、使用时间粒度转换函数
SELECT dbo.ufn_Years2Date(dbo.ufn_Years(LoginTime)) AS LoginYearBasedate, COUNT(1) AS YearLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY dbo.ufn_Years(LoginTime)
ORDER BY LoginYearBasedate ASC;
GO
-- 方法3、使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Years2Date(LoginYears) AS LoginYearBasedate, COUNT(1) AS YearLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginYears
ORDER BY LoginYears ASC;
GO
-- 方法4、嵌套查询与使用时间粒度字段列和时间粒度转换函数
SELECT dbo.ufn_Years2Date(T.LoginYears) AS LoginYearBasedate, T.YearLoginTimesTotal
FROM (
SELECT LoginYears, COUNT(1) AS YearLoginTimesTotal
FROM dbo.LoginInfo
GROUP BY LoginYears
) AS T
ORDER BY LoginYears ASC;
GO
查询以上四个方法的图形实际执行计划,如下图:
注意:
总结语
本文仅仅提供了测试数据表的创建以及相关的数据填充,向测试表中增加时间粒度相关的字段列,使用时间粒度相关函数简单了基于日月季年统计汇总的演示。
参考清单列表
- SQL Server时间粒度系列----第1节时间粒度概述
本文目录列表: 1.什么是时间粒度?2.SQL Server提供的时间粒度3.SQL Server时间粒度代码演示 4.SQL Server基准日期 5.总结语6.参考清单列表 什么是时间粒度 ...
- SQL Server时间粒度系列----第4节季、年时间粒度详解
本文目录列表: 1.SQL Server季时间粒度2.SQL Server年时间粒度 3.总结语 4.参考清单列表 SQL Serve季时间粒度 季时间粒度也即是季度时间粒度.一年每3 ...
- SQL Server时间粒度系列----第3节旬、月时间粒度详解
本文目录列表: 1.SQL Server旬时间粒度2.SQL Server月有关时间粒度 3.SQL Server函数重构 4.总结语 5.参考清单列表 SQL Server旬时间粒度 ...
- 【目录】sql server 进阶篇系列
随笔分类 - sql server 进阶篇系列 sql server 下载安装标记 摘要: SQL Server 2017 的各版本和支持的功能 https://docs.microsoft.com/ ...
- SQL Server调优系列基础篇
前言 关于SQL Server调优系列是一个庞大的内容体系,非一言两语能够分析清楚,本篇先就在SQL 调优中所最常用的查询计划进行解析,力图做好基础的掌握,夯实基本功!而后再谈谈整体的语句调优. 通过 ...
- SQL Server调优系列基础篇(常用运算符总结——三种物理连接方式剖析)
前言 上一篇我们介绍了如何查看查询计划,本篇将介绍在我们查看的查询计划时的分析技巧,以及几种我们常用的运算符优化技巧,同样侧重基础知识的掌握. 通过本篇可以了解我们平常所写的T-SQL语句,在SQL ...
- SQL Server调优系列基础篇(并行运算总结篇二)
前言 上一篇文章我们介绍了查看查询计划的并行运行方式. 本篇我们接着分析SQL Server的并行运算. 闲言少叙,直接进入本篇的正题. 技术准备 同前几篇一样,基于SQL Server2008R2版 ...
- SQL Server调优系列基础篇(索引运算总结)
前言 上几篇文章我们介绍了如何查看查询计划.常用运算符的介绍.并行运算的方式,有兴趣的可以点击查看. 本篇将分析在SQL Server中,如何利用先有索引项进行查询性能优化,通过了解这些索引项的应用方 ...
- SQL Server调优系列进阶篇(查询语句运行几个指标值监测)
前言 上一篇我们分析了查询优化器的工作方式,其中包括:查询优化器的详细运行步骤.筛选条件分析.索引项优化等信息. 本篇我们分析在我们运行的过程中几个关键指标值的检测. 通过这些指标值来分析语句的运行问 ...
随机推荐
- 通过html和css做出下拉导航栏的效果
通过观察了百度的首页,对于更多产品一栏,觉得可以不涉及JS便可写出下拉导航栏的效果 1.先设计出大体的框架 <div class="nav"> <ul> & ...
- ABP理论学习之设置管理
返回总目录 本篇目录 介绍 定义设置 获取设置值 更改设置 关于缓存 介绍 每个应用程序都需要存储一些设置信息,然后在应用程序中的某个地方使用这些设置.ABP提供了健壮的基础设施来存储或检索服务端和客 ...
- ReactJS入门(四)—— 组件API
本篇将介绍 React 组件的API,其中主要的几个API我们在第一篇的时候便已介绍过,这里可以做个温故知新. 本篇的代码你也可以在我的Github上获取到. setState 参数: nextSta ...
- 新版C#编译器关于函数闭包的一处更改
感谢@DiryBoy的补充,他提到这个问题在MSDN上是有说明的: http://msdn.microsoft.com/en-us/library/vstudio/hh678682.aspx 在Vis ...
- 干掉Unity3D
我为什么想干掉Unity3D? 这个问题容我不答,每个做技术的人总有一些完美主义. 你使用u3d的过程中是不是痛并快乐着呢. 就从两个国内具有相当普遍性的痛点说起. il2cpp,unity作出了这个 ...
- Html5 布局方式
在Html5之前,统一采用的是Div+css的方式进行布局,但是却和开发人员的命名方式,喜好有关.在新的Html5中,布局却显得更加人性化,更易理解了.如增加了Header,Footer,Sectio ...
- 30个你必须记住的CSS选择符
所以你学会了基础的id,类和后代选择符,然后你就一直用它们了吗?如果是这样,你丢失了(css的)巨大的灵活性.在本文中提到的很多选择器属于CSS3规范的一部分,因此,只有在现代浏览器中才可使用. 1. ...
- $watch $apply and $evalAsync vs $timeout
$watch $scope对象上的$watch方法会给Angular事件循环内的每个$digest调用装配一个脏值检查. 如果在表达式上检测到变化, Angular总是会返回$digest循环. $w ...
- ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介
概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...
- Java 循环中标签的作用
continue和break可以改变循环的执行流程,但在多重循环中,这两条语句无法直接从内层循环跳转到外层循环.在C语言中,可以通过goto语句实现多重循环的跳转,但在非循环结构中使用goto语句会使 ...