我正在寻找在日志中聚合数据的最佳方法。在下表中是"谁在一个电台"的日志。 E.g
用户1在#1; 2014年10月2日14:46"之间的电台1上和" 10/2/2014 14:50" (2笔交易)
User2位于" 10/2/2014 15:00"之间的station1和" 10/2/2014 15:15"(5笔交易)
user3在2014年10月3日16:31(1次交易)
上的station1上User2在同一天再次出现在" 10/2/2014 17:04"和" 10/2/2014 17:06"(2笔交易)
Station1 10/2/2014 14:46 User1
Station1 10/2/2014 14:50 User1
Station1 10/2/2014 15:00 User2
Station1 10/2/2014 15:00 User2
Station1 10/2/2014 15:00 User2
Station1 10/2/2014 15:00 User2
Station1 10/2/2014 15:15 User2
Station1 10/2/2014 16:31 User3
Station1 10/2/2014 17:04 User2
Station1 10/2/2014 17:06 User2

我正在寻找类似于&#34的输出;用户在电台上的时间长度以及有多少交易" ...是否可以在不迭代每个项目的情况下执行相同操作?如果是这样我该怎么办呢?
station User start time Duration Transactions
Station1 User1 10/2/2014 14:46 4 min 2
Station1 User2 10/2/2014 15:00 15 min 5
Station1 User3 10/2/2014 16:31 1
Station1 User2 10/2/2014 15:04 2 min 2

答案 0 :(得分:0)
运行这些脚本
脚本1
{6, 15}
脚本2
-- =============================================
-- Author: Carlos Aguilar
-- Create date: April 2016
-- Description: Massive Creation of Log Tables in a Database
-- =============================================
DECLARE @SCRIPT NVARCHAR(MAX)
DECLARE @TABLE NVARCHAR(MAX)
DECLARE @COLUMNS NVARCHAR(MAX)
DECLARE _LOGS_ CURSOR FOR
SELECT NAME FROM SYSOBJECTS WHERE TYPE = 'U' AND NAME NOT LIKE '__LOG_%'
OPEN _LOGS_
BEGIN TRY
BEGIN TRAN
FETCH NEXT FROM _LOGS_ INTO @TABLE
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET @COLUMNS = ''
SELECT @COLUMNS = @COLUMNS + '[' + T1.NAME + '] ' + T2.NAME +
CASE
WHEN T1.XTYPE IN (106, 108) THEN
'(' + CONVERT(VARCHAR, T1.XPREC) + ', ' + CONVERT(VARCHAR, T1.XSCALE) + ')'
WHEN T1.XTYPE IN (173, 175, 42, 43, 239, 231, 41, 165, 167) THEN
'(' + CASE WHEN T1.LENGTH = -1 THEN 'MAX' ELSE CONVERT(VARCHAR, T1.LENGTH ) END + ')'
ELSE
''
END
+ ' NULL, '
FROM SYSOBJECTS T0
INNER JOIN SYSCOLUMNS T1
ON T0.ID = T1.ID
INNER JOIN sys.TYPES T2
ON T1.XTYPE = T2.SYSTEM_TYPE_ID
WHERE T0.TYPE = 'U' AND
T0.NAME NOT LIKE '__LOG_%' AND
T0.NAME = @TABLE AND
T1.XTYPE NOT IN (34, 35, 99) AND
T2.NAME <> 'sysname'
SELECT @SCRIPT =
'CREATE TABLE __LOG_' + @TABLE + '(' + @COLUMNS + '
[__DB_USER] nvarchar(128) NULL,
[__APP_NAME] nvarchar(128) NULL,
[__HOST_NAME] nvarchar(128) NULL,
[__IP_ADD] sql_variant NULL,
[__EVENT] varchar(1) NULL,
[__TIME] datetime NULL,
[__PROTOCOL] sql_variant NULL) '
PRINT @SCRIPT
EXEC (@SCRIPT)
SELECT @SCRIPT = 'DELETE FROM __LOG_' + @TABLE
PRINT @SCRIPT
EXEC (@SCRIPT)
FETCH NEXT FROM _LOGS_ INTO @TABLE
END
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
PRINT 'ERROR: ' + ERROR_MESSAGE()
END CATCH
CLOSE _LOGS_
DEALLOCATE _LOGS_
GO
脚本3
-- =============================================
-- Author: Carlos Aguilar
-- Create date: April 2016
-- Description: Massive Creation of Trigger for Log Tables in a Database
-- =============================================
DECLARE @COLUMNS NVARCHAR(MAX)
DECLARE @SCRIPT NVARCHAR(MAX)
DECLARE @TABLE NVARCHAR(MAX)
DECLARE _LOGS_ CURSOR FOR
SELECT NAME FROM SYSOBJECTS WHERE TYPE = 'U' AND NAME NOT LIKE '__LOG_%'
OPEN _LOGS_
BEGIN TRY
BEGIN TRAN
FETCH NEXT FROM _LOGS_ INTO @TABLE
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET @COLUMNS = ''
SELECT @COLUMNS = @COLUMNS + '[' + T1.NAME + '], '
FROM SYSOBJECTS T0
INNER JOIN SYSCOLUMNS T1
ON T0.ID = T1.ID
WHERE T0.TYPE = 'U' AND
T0.NAME NOT LIKE '__LOG_%' AND
T0.NAME = @TABLE AND
T1.XTYPE NOT IN (34, 35, 99)
SELECT @SCRIPT = 'CREATE TRIGGER [dbo].[__LOG_INSERT_' + @TABLE + '] ON [dbo].[' + @TABLE + ']
WITH ENCRYPTION, EXECUTE AS CALLER
FOR INSERT
AS
BEGIN
INSERT INTO __LOG_' + @TABLE + '(' +
@COLUMNS + '
__DB_USER,
__APP_NAME,
__HOST_NAME,
__IP_ADD,
__EVENT,
__TIME,
__PROTOCOL)
SELECT ' + @COLUMNS + '
SUSER_SNAME() AS __DB_USER ,
APP_NAME () AS __APP_NAME,
HOST_NAME () AS __HOST_NAME,
CONNECTIONPROPERTY(''client_net_address'') __IP_ADD,
''I'' AS __EVENT,
GETDATE() AS __TIME,
CONNECTIONPROPERTY(''protocol_type'') AS __PROTOCOL
FROM INSERTED
END'
PRINT @SCRIPT
EXEC (@SCRIPT)
SELECT @SCRIPT = 'CREATE TRIGGER [dbo].[__LOG_UPDATE_' + @TABLE + '] ON [dbo].[' + @TABLE + ']
WITH ENCRYPTION, EXECUTE AS CALLER
FOR UPDATE
AS
BEGIN
INSERT INTO __LOG_' + @TABLE + '(' +
@COLUMNS + '
__DB_USER,
__APP_NAME,
__HOST_NAME,
__IP_ADD,
__EVENT,
__TIME,
__PROTOCOL)
SELECT ' + @COLUMNS + '
SUSER_SNAME() AS __DB_USER ,
APP_NAME () AS __APP_NAME,
HOST_NAME () AS __HOST_NAME,
CONNECTIONPROPERTY(''client_net_address'') __IP_ADD,
''U'' AS __EVENT,
GETDATE() AS __TIME,
CONNECTIONPROPERTY(''protocol_type'') AS __PROTOCOL
FROM INSERTED
END'
PRINT @SCRIPT
EXEC (@SCRIPT)
SELECT @SCRIPT = 'CREATE TRIGGER [dbo].[__LOG_DELETE_' + @TABLE + '] ON [dbo].[' + @TABLE + ']
WITH ENCRYPTION, EXECUTE AS CALLER
FOR DELETE
AS
BEGIN
INSERT INTO __LOG_' + @TABLE + '(' +
@COLUMNS + '
__DB_USER,
__APP_NAME,
__HOST_NAME,
__IP_ADD,
__EVENT,
__TIME,
__PROTOCOL)
SELECT ' + @COLUMNS + '
SUSER_SNAME() AS __DB_USER ,
APP_NAME () AS __APP_NAME,
HOST_NAME () AS __HOST_NAME,
CONNECTIONPROPERTY(''client_net_address'') __IP_ADD,
''D'' AS __EVENT,
GETDATE() AS __TIME,
CONNECTIONPROPERTY(''protocol_type'') AS __PROTOCOL
FROM DELETED
END'
PRINT @SCRIPT
EXEC (@SCRIPT)
FETCH NEXT FROM _LOGS_ INTO @TABLE
END
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
PRINT 'ERROR: ' + ERROR_MESSAGE()
END CATCH
CLOSE _LOGS_
DEALLOCATE _LOGS_
GO
等待1或2天进行用户交易并运行
-- =============================================
-- Author: Carlos Aguilar
-- Create date: April 2016
-- =============================================
CREATE PROCEDURE dbo.SelectLogByDate
(
@StartDate DATETIME,
@EndDate DATETIME
)
AS
BEGIN
CREATE TABLE #TRANSACTIONS
(
[TIMESTAMP] DATETIME,
STATION NVARCHAR(128),
[USER] NVARCHAR(128)
)
DECLARE @TABLE NVARCHAR(MAX)
DECLARE @SQL NVARCHAR(MAX)
DECLARE @ParmDefinition NVARCHAR(MAX);
SET @ParmDefinition = N'@StartDate DATETIME, @EndDate DATETIME'
DECLARE _LOGS_ CURSOR FOR
SELECT NAME FROM SYSOBJECTS WHERE TYPE = 'U' AND NAME LIKE '__LOG_%'
OPEN _LOGS_
BEGIN TRY
BEGIN TRAN
FETCH NEXT FROM _LOGS_ INTO @TABLE
WHILE (@@FETCH_STATUS = 0)
BEGIN
SELECT @SQL = 'INSERT INTO #TRANSACTIONS ([TIMESTAMP], STATION, [USER]) SELECT __TIME, __HOST_NAME, __DB_USER FROM ' +
@TABLE + ' ' +
'WHERE __TIME BETWEEN @StartDate AND @EndDate'
EXECUTE sp_executesql @SQL, @ParmDefinition,
@StartDate = @StartDate,
@EndDate = @EndDate
FETCH NEXT FROM _LOGS_ INTO @TABLE
END
COMMIT
END TRY
BEGIN CATCH
END CATCH
CLOSE _LOGS_
DEALLOCATE _LOGS_
SELECT STATION,
[USER],
MIN([TIMESTAMP]) AS "START TIME",
MAX([TIMESTAMP]) AS "END TIME",
DATEDIFF(MINUTE, MIN([TIMESTAMP]), MAX([TIMESTAMP])) AS DURATION,
COUNT(*) AS TRANSACTIONS
FROM #TRANSACTIONS
GROUP BY STATION,
[USER]
END
GO
答案 1 :(得分:0)
设置数据:
create table #log (Station varchar(20), Dt datetime, UserName varchar(10))
insert into #log values
('Station1', '10/2/2014 14:46', 'User1'),
('Station1', '10/2/2014 14:50', 'User1'),
('Station1', '10/2/2014 15:00', 'User2'),
('Station1', '10/2/2014 15:00', 'User2'),
('Station1', '10/2/2014 15:00', 'User2'),
('Station1', '10/2/2014 15:00', 'User2'),
('Station1', '10/2/2014 15:15', 'User2'),
('Station1', '10/2/2014 16:31', 'User3'),
('Station1', '10/2/2014 17:04', 'User2'),
('Station1', '10/2/2014 17:06', 'User2')
<强>查询:强>
;with TranCount as (
select Station, UserName, count(*) Cnt, MIN(Dt) MinDt
from (select t.*,
(row_number() over (partition by Station order by Dt) -
row_number() over (partition by UserName order by Dt)
) as grp
from #log t
) t
group by grp, Station, UserName
)
-- find time from next record.
-- also number the records to find IN and OUT entries
, cte1 as (
select Station, UserName, Dt
, LEAD(Dt) over (partition by Station, UserName order by Station, Dt) NextDt
, ROW_NUMBER() over (partition by Station, UserName order by Station, Dt) as RN
from #log
group by Station, UserName, Dt
)
-- only select IN entries, the exit time will be in NextDt field.
-- so ignore the even rows.
, cte2 as (
select *
from cte1
where RN % 2 = 1
)
select cte2.Station, cte2.UserName, Dt StartTime
, DATEDIFF(SECOND, Dt, NextDt) / 60 AS Duration, TranCount.Cnt AS TransactionCount
from cte2
inner join TranCount on TranCount.Station = cte2.Station
and TranCount.UserName = cte2.UserName
and TranCount.MinDt = cte2.Dt
order by Station, Dt, UserName
结果:
+----------+----------+-------------------------+----------+------------------+
| Station | UserName | StartTime | Duration | TransactionCount |
+----------+----------+-------------------------+----------+------------------+
| Station1 | User1 | 2014-10-02 14:46:00.000 | 4 | 2 |
| Station1 | User2 | 2014-10-02 15:00:00.000 | 15 | 5 |
| Station1 | User3 | 2014-10-02 16:31:00.000 | NULL | 1 |
| Station1 | User2 | 2014-10-02 17:04:00.000 | 2 | 2 |
+----------+----------+-------------------------+----------+------------------+
如果帖子已回答问题
,请“标记为答案”